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

Using uninitialized memory 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,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, b2Color(1.0f, 0.0f, 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, 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,0.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, pos.y ), 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], b2Color(0.0f, 0.0f, 1.0f));
    m_debugDraw.DrawSegment(box[1], box[2], b2Color(0.0f, 0.0f, 1.0f));
    m_debugDraw.DrawSegment(box[2], box[3], b2Color(0.0f, 0.0f, 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();
    }
}