使用未初始化的内存C ++ Box2D

问题描述

我正在尝试使用Box2d创建一个简单的打砖块游戏,现在我正在尝试检测球与块之间的碰撞,但是当我调试代码时,它一直给我错误:变量'block'正在使用而未初始化”。我该怎么解决这个问题?游戏中的方块(红色)是这样的:

enter image description here

#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();
    }
}