如何解决使用未初始化的内存C ++ Box2D
我正在尝试使用Box2d创建一个简单的打砖块游戏,现在我正在尝试检测球与块之间的碰撞,但是当我调试代码时,它一直给我错误:变量'block'正在使用而未初始化”。我该怎么解决这个问题?游戏中的方块(红色)是这样的:
#ifndef ARKANOID_H
#define ARKANOID_H
#include "../Framework/Test.h"
#include <vector>
struct Contact
{
Contact(const b2Vec2& normal,const b2Vec2& contactPt,float32 penetration = 0.0f)
: m_normal(normal),m_contactPt(contactPt),m_penetrationDepth(penetration) {}
b2Vec2 m_normal;
b2Vec2 m_contactPt;
float32 m_penetrationDepth;
};
class Ball
{
public:
Ball(): m_position(0.0f,0.0f),m_veLocity(0.0f,m_radius(0.5f){}
Ball(const b2Vec2& position,const b2Vec2& veLocity,float32 radius = 0.5f)
: m_position(position),m_veLocity(veLocity),m_radius(radius)
{
m_invMass = m_mass > 0.0f ? 1.0f / m_mass : 0.0f;
}
const b2Vec2& GetPosition(){return m_position;}
void SetPosition(const b2Vec2& newPosition){m_position = newPosition;}
float GeTradius() { return m_radius; }
void Update(float deltaTime);
void Render(DebugDraw& debugDraw);
void AddContact(const Contact& cp);
void HandleContacts();
void ApplyForce(const b2Vec2& force);
protected:
b2Vec2 m_position;
b2Vec2 m_veLocity;
float32 m_radius;
float m_invMass;
float m_mass;
std::vector<Contact> m_contacts;
};
class Block
{
public:
Block( const b2Vec2 center,const b2Vec2& halfExtent );
void Render(DebugDraw& debugDraw);
b2Vec2 GetClosestPosition(const b2Vec2& pos);
protected:
b2AABB m_aabb;
};
class Paddle
{
public:
Paddle(b2Vec2& center,float width);
void Update(float deltaTime);
void Render(DebugDraw& debugDraw);
void SetSpeed(float speed) { m_speed = speed; }
b2Vec2 GetLeftPos() { return m_center - b2Vec2( m_width *0.5f,0.0f ); }
b2Vec2 GetRightPos() { return m_center + b2Vec2( m_width *0.5f,0.0f ); }
float GetHeight() { return m_center.y; }
void SetMoveRight();
void SetMoveLeft();
void Stop();
void SetWorldLimits(float min,float max);
protected:
b2Vec2 m_center;
float m_width;
float m_min_X;
float m_max_X;
b2Vec2 m_direction;
float m_speed;
};
class ArkanoidGame : public Test
{
public:
static Test* Create()
{
return new ArkanoidGame;
}
ArkanoidGame();
void CreateBlocks();
virtual void Step(Settings* settings);
void CheckCollisions();
void CheckOutofWorld();
bool IsOutofWorld(Ball* ball);
void UpdateBalls(float deltaTime);
void Render();
void Keyboard(unsigned char key);
void KeyboardUp(unsigned char key);
void AddBall();
void RemoveBall(Ball* ball);
void ApplyGravity();
b2Vec2 m_worldBoxMin;
b2Vec2 m_worldBoxMax;
Paddle m_paddle;
std::vector<Ball*> m_balls;
std::vector<Block*> m_blocks;
};
#endif
#include "../Framework/Render.h"
#include "Arkanoid.h"
#include <vector>
void Ball::Render(DebugDraw& debugDraw)
{
debugDraw.DrawSolidCircle(m_position,m_radius,b2Vec2(0.0f,1.0f),b2Color(1.0f,0.0f,0.0f));
}
void Ball::Update(float deltaTime)
{
HandleContacts();
//Update position
//***To Do***
b2Vec2 m_force(b2Vec2_zero);
b2Vec2 acceleration = m_invMass * m_force;
m_veLocity += deltaTime * acceleration;
m_position += deltaTime * m_veLocity;
m_force = b2Vec2_zero;
}
void Ball::AddContact(const Contact& cp)
{
m_contacts.push_back(cp);
}
void Ball::HandleContacts()
{
//Resolve Collision
if (m_contacts.size() > 0)
{
//Prevent interpenetration => directly update position
b2Vec2 deltaPos(0.0f,0.0f);
for (size_t i = 0; i<m_contacts.size(); ++i)
{
deltaPos += m_contacts[i].m_penetrationDepth * m_contacts[i].m_normal;
}
m_position += deltaPos;
//Average contact normal
b2Vec2 collisionnormal(0.0f,0.0f);
for (size_t i = 0; i<m_contacts.size(); ++i)
{
collisionnormal += m_contacts[i].m_normal;
}
collisionnormal.normalize();
//Update veLocity
//***To Do*** ///fait
float restitution = 0.6f;
b2Vec2 vp = b2Dot(m_veLocity,collisionnormal) * (collisionnormal);
b2Vec2 vt = m_veLocity - vp;
m_veLocity = vt + (-restitution * vp);
}
m_contacts.clear();
}
void Ball::ApplyForce(const b2Vec2& force)
{
b2Vec2 m_force(b2Vec2_zero);
m_force += force;
}
Block::Block(const b2Vec2 center,const b2Vec2& halfExtent)
{
m_aabb.lowerBound = center - halfExtent;
m_aabb.upperBound = center + halfExtent;
}
void Block::Render(DebugDraw& debugDraw)
{
debugDraw.DrawAABB(&m_aabb,0.0f));
}
b2Vec2 Block::GetClosestPosition(const b2Vec2& pos)
{
b2Vec2 closestPosition;
if (pos.x < m_aabb.lowerBound.x)
{
if (pos.y < m_aabb.lowerBound.y)
{
closestPosition = m_aabb.lowerBound;
}
else if (pos.y > m_aabb.upperBound.y)
{
closestPosition = b2Vec2(m_aabb.lowerBound.x,m_aabb.upperBound.y);
}
else
{
closestPosition = b2Vec2(m_aabb.lowerBound.x,pos.y);
}
}
else if (pos.x > m_aabb.upperBound.x)
{
if (pos.y < m_aabb.lowerBound.y)
{
closestPosition = b2Vec2(m_aabb.upperBound.x,m_aabb.lowerBound.y);
}
else if (pos.y > m_aabb.upperBound.y)
{
closestPosition = m_aabb.upperBound;
}
else
{
closestPosition = b2Vec2(m_aabb.upperBound.x,pos.y);
}
}
else
{
if (pos.y < m_aabb.lowerBound.y)
{
closestPosition = b2Vec2(pos.x,m_aabb.lowerBound.y);
}
else if (pos.y > m_aabb.upperBound.y)
{
closestPosition = b2Vec2(pos.x,m_aabb.upperBound.y);
}
else
{
closestPosition = pos;
}
}
return closestPosition;
}
Paddle::Paddle(b2Vec2& center,float width)
: m_center(center),m_width(width),m_direction(0.0f,m_speed(12.0f),m_min_X(-b2_maxFloat),m_max_X(b2_maxFloat)
{
}
void Paddle::SetWorldLimits(float min,float max)
{
//***To Do***
}
void Paddle::Update(float deltaTime)
{
//***To Do***
}
void Paddle::Render(DebugDraw& debugDraw)
{
b2Vec2 halfExtent(m_width*0.5f,0.0f);
debugDraw.DrawSegment(m_center + halfExtent,m_center - halfExtent,b2Color(0.0f,1.0f,0.0f));
}
void Paddle::SetMoveRight()
{
m_direction = b2Vec2(1.0f,0.0f);
}
void Paddle::SetMoveLeft()
{
m_direction = b2Vec2(-1.0f,0.0f);
}
void Paddle::Stop()
{
m_direction = b2Vec2_zero;
}
ArkanoidGame::ArkanoidGame()
: m_worldBoxMin(-25.0f,m_worldBoxMax(25.0f,50.0f),m_paddle(b2Vec2(0.0f,2.0f),4.0f)
{
m_paddle.SetWorldLimits(m_worldBoxMin.x,m_worldBoxMax.x);
CreateBlocks();
}
void ArkanoidGame::CreateBlocks()
{
b2Vec2 blockHalfExtent(3.0f,1.0f);
int nbColumn = 6;
int nbNbrow = 3;
b2Vec2 startPos = b2Vec2(-15.0f,35.0f);
for (int i = 0; i < nbNbrow; i++)
{
for (int j = 0; j < nbColumn; j++)
{
b2Vec2 pos = startPos + b2Vec2(blockHalfExtent.x * 2.0f * j,blockHalfExtent.y * 2.0f * i);
Block* newBlock = new Block(pos,blockHalfExtent);
m_blocks.push_back(newBlock);
}
}
}
void ArkanoidGame::Step(Settings* settings)
{
float timestep = settings->hz > 0.0f ? 1.0f / settings->hz : float32(0.0f);
ApplyGravity();
m_paddle.Update(timestep);
UpdateBalls(timestep);
CheckCollisions();
CheckOutofWorld();
Render();
}
void ArkanoidGame::UpdateBalls(float deltaTime)
{
for (size_t i = 0; i < m_balls.size(); ++i)
{
m_balls[i]->Update(deltaTime);
}
}
void ArkanoidGame::CheckCollisions()
{
//Box interior normals
b2Vec2 rightN(-1.0f,0.0f);
b2Vec2 leftN(1.0f,0.0f);
b2Vec2 upN(0.0f,-1.0f);
b2Vec2 downN(0.0f,1.0f);
b2Vec2 blockHalfExtent(3.0f,1.0f); /////
Block* block;
//Check collisions for all particules
std::vector<Ball*>::iterator it;
for (it=m_balls.begin(); it!= m_balls.end(); ++it)
{
Ball* ball = *it;
b2Vec2 pos = ball->GetPosition();
float32 radius = ball->GeTradius();
//Check collisions for each wall
//Left
float left = pos.x - radius;
if( left <= m_worldBoxMin.x )
{
ball->AddContact( Contact(leftN,b2Vec2( left,pos.y ),m_worldBoxMin.x - left ) );
}
//Right
float right = pos.x + radius;
if( right >= m_worldBoxMax.x )
{
ball->AddContact(Contact(rightN,b2Vec2( right,right - m_worldBoxMax.x ) );
}
//Up
float up = pos.y + radius;
if( up >= m_worldBoxMax.y )
{
ball->AddContact(Contact(upN,b2Vec2( pos.x,up ),up - m_worldBoxMax.y ) );
}
//Check Collision with paddle
//***To Do***
//Check collisions with blocks
//***To Do***
Block*block;
b2Vec2 toClosest = ball->GetPosition()- block->GetClosestPosition(pos);
float distance = toClosest.normalize();
float penetrationDepth = distance - ball->GeTradius();
if (penetrationDepth < 0.0f)
{
ball->HandleContacts();
}
//Add contact and destroy the block
}
}
void ArkanoidGame::CheckOutofWorld()
{
for (size_t i = 0; i < m_balls.size(); )
{
if (IsOutofWorld(m_balls[i]))
{
//Remove ball
RemoveBall(m_balls[i]);
}
else
{
i++;
}
}
}
bool ArkanoidGame::IsOutofWorld(Ball* ball)
{
//***To Do***
return false;
}
void ArkanoidGame::Render()
{
m_paddle.Render(m_debugDraw);
//Render Ball
for (size_t i = 0; i < m_balls.size();++i)
{
m_balls[i]->Render(m_debugDraw);
}
//Render Blocks
for (size_t i = 0; i < m_blocks.size(); ++i)
{
m_blocks[i]->Render(m_debugDraw);
}
//Render Box
b2Vec2 Box[4];
Box[0].Set(m_worldBoxMin.x,m_worldBoxMin.y);
Box[1].Set(m_worldBoxMin.x,m_worldBoxMax.y);
Box[2].Set(m_worldBoxMax.x,m_worldBoxMax.y);
Box[3].Set(m_worldBoxMax.x,m_worldBoxMin.y);
m_debugDraw.DrawSegment(Box[0],Box[1],1.0f));
m_debugDraw.DrawSegment(Box[1],Box[2],1.0f));
m_debugDraw.DrawSegment(Box[2],Box[3],1.0f));
}
void ArkanoidGame::Keyboard(unsigned char key)
{
switch (key)
{
case 'a':
{
m_paddle.SetMoveLeft();
}
break;
case 'd':
{
m_paddle.SetMoveRight();
}
break;
case 'n':
{
AddBall();
}
break;
}
}
void ArkanoidGame::KeyboardUp(unsigned char key)
{
switch (key)
{
case 'a':
case 'd':
m_paddle.Stop();
break;
}
}
void ArkanoidGame::AddBall()
{
float angle = RandomFloat(-b2_pi*0.25f,b2_pi*0.25f);
b2Rot rot(angle);
float speed = RandomFloat(10.0f,20.0f);
b2Vec2 dir(0.0f,speed);
Ball* ball = new Ball(b2Vec2(0.0f,5.0f),b2Mul(rot,dir));
m_balls.push_back(ball);
}
void ArkanoidGame::RemoveBall(Ball* ball)
{
std::vector<Ball*>::iterator it = m_balls.begin();
while (it != m_balls.end())
{
if ((*it) == ball)
{
std::swap(*it,m_balls.back());
m_balls.pop_back();
break;
}
++it;
}
}
void ArkanoidGame::ApplyGravity()
{
for (Ball* ball : m_balls)
{
ball->ApplyForce(b2Vec2(0.0f,-9.81f));
}
}
解决方法
您具有以下代码:
Block*block;
b2Vec2 toClosest = ball->GetPosition()- block->GetClosestPosition(pos);
您永远不会为block
分配任何内容,因此它应该在哪个块的最接近位置?
我的猜测是您想遍历所有块,因此需要另一个迭代器,如下所示:
std::vector<Block*>::iterator itb;
for (itb = m_blocks.begin); itb != m_blocks.end(); ++itb) {
b2Vec2 toClosest = ball->getPosition - itb->getClosestPosition(pos);
float distance = toClosest.Normalize();
float penetrationDepth = distance - ball->GetRadius();
if (penetrationDepth < 0.0f)
{
ball->HandleContacts();
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。