C++ Game Asteroid

Started by
10 comments, last by Tom Sloper 5 years, 8 months ago

Hey guys,

I am getting an exception when I run my code. It's an asteroid game and I am using VS2012 express for it.

When I run my code I get this warning dialogue box and then it takes me to UpdateBullet function.

 

error.png

error 2.png

Advertisement

Would be good to see a bit more code, but looks a lil bit like a null/invalid memory access.  Maybe post some code from the bullet's update function.
Potentially something accessed within the system object is null during the bullet's update. I'm assuming no multi-threading here also.

Personally I would guess that either a bullet is null, or that you're deleting bullets from inside the vector (which will invalidate all subsequent iterators). For a better stab at fixing the problem, more code is needed.

Hello to all my stalkers.

1 hour ago, Lactose said:

Personally I would guess that either a bullet is null, or that you're deleting bullets from inside the vector (which will invalidate all subsequent iterators). For a better stab at fixing the problem, more code is needed.

[

#include "Game.h"
#include "System.h"
#include "OrthoCamera.h"
#include "Background.h"
#include "Ship.h"
#include "Asteroid.h"
#include "Explosion.h"
#include "Keyboard.h"
#include "Random.h"
#include "Maths.h"
#include "Bullet.h"
#include "Collision.h"
#include <algorithm>

Game::Game() :
    camera_(0),
    background_(0),
    player_(0),
    collision_(0)
{
    camera_ = new OrthoCamera();
    camera_->SetPosition(D3DXVECTOR3(0.0f, 0.0f, 0.0f));
    camera_->SetFrustum(800.0f, 600.0f, -100.0f, 100.0f);
    background_ = new Background(800.0f, 600.0f);
    collision_ = new Collision();
}

Game::~Game()
{
    delete camera_;
    delete background_;
    delete player_;
    DeleteBullet();
    DeleteAllAsteroids();
    DeleteAllExplosions();
    delete collision_;
}

void Game::Update(System *system)
{
    UpdatePlayer(system);
    UpdateAsteroids(system);
    UpdateBullet(system);
    UpdateCollisions();
}

void Game::RenderBackgroundOnly(Graphics *graphics)
{
    camera_->SetAsView(graphics);
    background_->Render(graphics);
}

void Game::RenderEverything(Graphics *graphics)
{
    camera_->SetAsView(graphics);

    background_->Render(graphics);

    if (player_)
    {
        player_->Render(graphics);
    }

    for (AsteroidList::const_iterator asteroidIt = asteroids_.begin(),
        end = asteroids_.end();
        asteroidIt != end;
        ++asteroidIt)
    {
        (*asteroidIt)->Render(graphics);
    }

    if (bullet_) //**TODO: Candidate for crash
    {
        bullet_->Render(graphics);
    }

    for (ExplosionList::const_iterator explosionIt = explosions_.begin(),
        end = explosions_.end();
        explosionIt != end;
        ++explosionIt)
    {
        (*explosionIt)->Render(graphics);
    }
}

void Game::InitialiseLevel(int numAsteroids)
{
    DeleteAllAsteroids();
    DeleteAllExplosions();

    SpawnPlayer();
    SpawnAsteroids(numAsteroids);
}

bool Game::IsLevelComplete() const
{
    return (asteroids_.empty() && explosions_.empty());
}

bool Game::IsGameOver() const
{
    return (player_ == 0 && explosions_.empty());
}

void Game::DoCollision(GameEntity *a, GameEntity *b)
{
    Ship *player = static_cast<Ship *>(a == player_ ? a : (b == player_ ? b : 0));
    Bullet *bullet = static_cast<Bullet *>(a == bullet_ ? a : (b == bullet_ ? b : 0));
    Asteroid *asteroid = static_cast<Asteroid *>(IsAsteroid(a) ? a : (IsAsteroid(b) ? b : 0));

    if (player && asteroid)
    {
        AsteroidHit(asteroid);
        DeletePlayer();
    }

    if (bullet && asteroid)
    {
        AsteroidHit(asteroid);
        DeleteBullet();
    }
}

void Game::SpawnPlayer()
{
    DeletePlayer();
    player_ = new Ship();
    player_->EnableCollisions(collision_, 10.0f);
}

void Game::DeletePlayer()
{
    delete player_;
    player_ = 0;
}

void Game::UpdatePlayer(System *system)
{
    if (player_ == 0)
        return;

    Keyboard *keyboard = system->GetKeyboard();

    float acceleration = 0.0f;
    if (keyboard->IsKeyHeld(VK_UP) || keyboard->IsKeyHeld('W'))
    {
        acceleration = 1.0f;
    }
    else if (keyboard->IsKeyHeld(VK_DOWN) || keyboard->IsKeyHeld('S'))
    {
        acceleration = -1.0f;
    }

    float rotation = 0.0f;
    if (keyboard->IsKeyHeld(VK_RIGHT) || keyboard->IsKeyHeld('D'))
    {
        rotation = -1.0f;
    }
    else if (keyboard->IsKeyHeld(VK_LEFT) || keyboard->IsKeyHeld('A'))
    {
        rotation = 1.0f;
    }

    player_->SetControlInput(acceleration, rotation);
    player_->Update(system);
    WrapEntity(player_);

    if (keyboard->IsKeyPressed(VK_SPACE))
    {
        D3DXVECTOR3 playerForward = player_->GetForwardVector();
        D3DXVECTOR3 bulletPosition = player_->GetPosition() + playerForward * 10.0f;
        SpawnBullet(bulletPosition, playerForward);
    }
}

void Game::UpdateAsteroids(System *system)
{
    for (AsteroidList::const_iterator asteroidIt = asteroids_.begin(),
        end = asteroids_.end();
        asteroidIt != end;
    ++asteroidIt)
    {
        (*asteroidIt)->Update(system);
        WrapEntity(*asteroidIt);
    }
}

void Game::UpdateBullet(System *system)
{
    if (bullet_)
    {
          bullet_->Update(system);
        WrapEntity(bullet_);
    }
}

void Game::WrapEntity(GameEntity *entity) const
{
    D3DXVECTOR3 entityPosition = entity->GetPosition();
    entityPosition.x = Maths::WrapModulo(entityPosition.x, -400.0f, 400.0f);
    entityPosition.y = Maths::WrapModulo(entityPosition.y, -300.0f, 300.0f);
    entity->SetPosition(entityPosition);
}

void Game::DeleteAllAsteroids()
{
    for (AsteroidList::const_iterator asteroidIt = asteroids_.begin(),
        end = asteroids_.end();
        asteroidIt != end;
        ++asteroidIt)
    {
        delete (*asteroidIt);
    }

    asteroids_.clear();
}

void Game::DeleteAllExplosions()
{
    for (ExplosionList::const_iterator explosionIt = explosions_.begin(),
        end = explosions_.end();
        explosionIt != end;
    ++explosionIt)
    {
        delete (*explosionIt);
    }

    explosions_.clear();
}

void Game::SpawnBullet(const D3DXVECTOR3 &position,
    const D3DXVECTOR3 &direction)
{
    DeleteBullet();
    bullet_ = new Bullet(position, direction);
    bullet_->EnableCollisions(collision_, 3.0f);
}

void Game::DeleteBullet()
{
    delete bullet_;
    bullet_ = 0;
}

void Game::SpawnAsteroids(int numAsteroids)
{
    float halfWidth = 800.0f * 0.5f;
    float halfHeight = 600.0f * 0.5f;
    for (int i = 0; i < numAsteroids; i++)
    {
        float x = Random::GetFloat(-halfWidth, halfWidth);
        float y = Random::GetFloat(-halfHeight, halfHeight);
        D3DXVECTOR3 position = D3DXVECTOR3(x, y, 0.0f);
        SpawnAsteroidAt(position, 3);
    }
}

void Game::SpawnAsteroidAt(const D3DXVECTOR3 &position, int size)
{
    const float MAX_ASTEROID_SPEED = 1.0f;

    float angle = Random::GetFloat(Maths::TWO_PI);
    D3DXMATRIX randomRotation;
    D3DXMatrixRotationZ(&randomRotation, angle);
    D3DXVECTOR3 velocity = D3DXVECTOR3(0.0f, Random::GetFloat(MAX_ASTEROID_SPEED), 0.0f);
    D3DXVec3TransformNormal(&velocity, &velocity, &randomRotation);

    Asteroid *asteroid = new Asteroid(position, velocity, size);
    asteroid->EnableCollisions(collision_, size * 5.0f);
    asteroids_.push_back(asteroid);
}

bool Game::IsAsteroid(GameEntity *entity) const
{
    return (std::find(asteroids_.begin(),
        asteroids_.end(), entity) != asteroids_.end());
}

void Game::AsteroidHit(Asteroid *asteroid)
{
    int oldSize = asteroid->GetSize();
    if (oldSize > 1)
    {
        int smallerSize = oldSize -1;
        D3DXVECTOR3 position = asteroid->GetPosition();
        SpawnAsteroidAt(position, smallerSize);
        SpawnAsteroidAt(position, smallerSize);
    }
    DeleteAsteroid(asteroid);
}

void Game::DeleteAsteroid(Asteroid *asteroid)
{
    asteroids_.remove(asteroid);
    delete asteroid;
}

void Game::UpdateCollisions()
{
    collision_->DoCollisions(this);
}


]

 

 

 

this the code of Game.cpp

1 hour ago, Lactose said:

Personally I would guess that either a bullet is null, or that you're deleting bullets from inside the vector (which will invalidate all subsequent iterators). For a better stab at fixing the problem, more code is needed.

#include "Bullet.h"
#include "Graphics.h"

Bullet::Bullet(const D3DXVECTOR3 &position,
    const D3DXVECTOR3 &direction)
{
    const float BULLET_SPEED = 4.0f;

    SetPosition(position);
    D3DXVECTOR3 normalisedDirection;
    D3DXVec3Normalize(&normalisedDirection, &direction);
    velocity_ = normalisedDirection * BULLET_SPEED;
}

void Bullet::Update(System *system)
{
    D3DXVECTOR3 position = GetPosition();
    D3DXVec3Add(&position, &position, &velocity_);
    SetPosition(position);
}

void Bullet::Render(Graphics *graphics) const
{
    const float RADIUS = 3.0f;

    struct DummyVert
    {
        float x, y, z;
        D3DCOLOR diffuse;
    };

    DummyVert square[5] =
    {
        {-RADIUS, -RADIUS, 0.0f, 0xffffffff},
        {-RADIUS,  RADIUS, 0.0f, 0xffffffff},
        { RADIUS,  RADIUS, 0.0f, 0xffffffff},
        { RADIUS, -RADIUS, 0.0f, 0xffffffff},
        {-RADIUS, -RADIUS, 0.0f, 0xffffffff},
    };

    D3DXVECTOR3 position = GetPosition();
    D3DXMATRIX translationMatrix;
    D3DXMatrixTranslation(&translationMatrix,
        position.x,
        position.y,
        position.z);

    D3DXMATRIX identityMatrix;
    D3DXMatrixIdentity(&identityMatrix);

    DWORD dummyFvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
    graphics->SetVertexFormat(dummyFvf);
    graphics->DisableLighting();
    graphics->SetModelMatrix(&translationMatrix);
    graphics->DrawImmediate(D3DPT_LINESTRIP,
        4,
        &square[0],
        sizeof(square[0]));
    graphics->SetModelMatrix(&identityMatrix);
    graphics->EnableLighting();
}

 

this is of Bullet.cpp

2 hours ago, magellanic said:

Would be good to see a bit more code, but looks a lil bit like a null/invalid memory access.  Maybe post some code from the bullet's update function.
Potentially something accessed within the system object is null during the bullet's update. I'm assuming no multi-threading here also.

#include "Bullet.h"
#include "Graphics.h"

Bullet::Bullet(const D3DXVECTOR3 &position,
    const D3DXVECTOR3 &direction)
{
    const float BULLET_SPEED = 4.0f;

    SetPosition(position);
    D3DXVECTOR3 normalisedDirection;
    D3DXVec3Normalize(&normalisedDirection, &direction);
    velocity_ = normalisedDirection * BULLET_SPEED;
}

void Bullet::Update(System *system)
{
    D3DXVECTOR3 position = GetPosition();
    D3DXVec3Add(&position, &position, &velocity_);
    SetPosition(position);
}

void Bullet::Render(Graphics *graphics) const
{
    const float RADIUS = 3.0f;

    struct DummyVert
    {
        float x, y, z;
        D3DCOLOR diffuse;
    };

    DummyVert square[5] =
    {
        {-RADIUS, -RADIUS, 0.0f, 0xffffffff},
        {-RADIUS,  RADIUS, 0.0f, 0xffffffff},
        { RADIUS,  RADIUS, 0.0f, 0xffffffff},
        { RADIUS, -RADIUS, 0.0f, 0xffffffff},
        {-RADIUS, -RADIUS, 0.0f, 0xffffffff},
    };

    D3DXVECTOR3 position = GetPosition();
    D3DXMATRIX translationMatrix;
    D3DXMatrixTranslation(&translationMatrix,
        position.x,
        position.y,
        position.z);

    D3DXMATRIX identityMatrix;
    D3DXMatrixIdentity(&identityMatrix);

    DWORD dummyFvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
    graphics->SetVertexFormat(dummyFvf);
    graphics->DisableLighting();
    graphics->SetModelMatrix(&translationMatrix);
    graphics->DrawImmediate(D3DPT_LINESTRIP,
        4,
        &square[0],
        sizeof(square[0]));
    graphics->SetModelMatrix(&identityMatrix);
    graphics->EnableLighting();
}

 

Bullet.cpp

 

 

#include "Game.h"
#include "System.h"
#include "OrthoCamera.h"
#include "Background.h"
#include "Ship.h"
#include "Asteroid.h"
#include "Explosion.h"
#include "Keyboard.h"
#include "Random.h"
#include "Maths.h"
#include "Bullet.h"
#include "Collision.h"
#include <algorithm>

Game::Game() :
    camera_(0),
    background_(0),
    player_(0),
    collision_(0)
{
    camera_ = new OrthoCamera();
    camera_->SetPosition(D3DXVECTOR3(0.0f, 0.0f, 0.0f));
    camera_->SetFrustum(800.0f, 600.0f, -100.0f, 100.0f);
    background_ = new Background(800.0f, 600.0f);
    collision_ = new Collision();
}

Game::~Game()
{
    delete camera_;
    delete background_;
    delete player_;
    DeleteBullet();
    DeleteAllAsteroids();
    DeleteAllExplosions();
    delete collision_;
}

void Game::Update(System *system)
{
    UpdatePlayer(system);
    UpdateAsteroids(system);
    UpdateBullet(system);
    UpdateCollisions();
}

void Game::RenderBackgroundOnly(Graphics *graphics)
{
    camera_->SetAsView(graphics);
    background_->Render(graphics);
}

void Game::RenderEverything(Graphics *graphics)
{
    camera_->SetAsView(graphics);

    background_->Render(graphics);

    if (player_)
    {
        player_->Render(graphics);
    }

    for (AsteroidList::const_iterator asteroidIt = asteroids_.begin(),
        end = asteroids_.end();
        asteroidIt != end;
        ++asteroidIt)
    {
        (*asteroidIt)->Render(graphics);
    }

    if (bullet_) //**TODO: Candidate for crash
    {
        bullet_->Render(graphics);
    }

    for (ExplosionList::const_iterator explosionIt = explosions_.begin(),
        end = explosions_.end();
        explosionIt != end;
        ++explosionIt)
    {
        (*explosionIt)->Render(graphics);
    }
}

void Game::InitialiseLevel(int numAsteroids)
{
    DeleteAllAsteroids();
    DeleteAllExplosions();

    SpawnPlayer();
    SpawnAsteroids(numAsteroids);
}

bool Game::IsLevelComplete() const
{
    return (asteroids_.empty() && explosions_.empty());
}

bool Game::IsGameOver() const
{
    return (player_ == 0 && explosions_.empty());
}

void Game::DoCollision(GameEntity *a, GameEntity *b)
{
    Ship *player = static_cast<Ship *>(a == player_ ? a : (b == player_ ? b : 0));
    Bullet *bullet = static_cast<Bullet *>(a == bullet_ ? a : (b == bullet_ ? b : 0));
    Asteroid *asteroid = static_cast<Asteroid *>(IsAsteroid(a) ? a : (IsAsteroid(b) ? b : 0));

    if (player && asteroid)
    {
        AsteroidHit(asteroid);
        DeletePlayer();
    }

    if (bullet && asteroid)
    {
        AsteroidHit(asteroid);
        DeleteBullet();
    }
}

void Game::SpawnPlayer()
{
    DeletePlayer();
    player_ = new Ship();
    player_->EnableCollisions(collision_, 10.0f);
}

void Game::DeletePlayer()
{
    delete player_;
    player_ = 0;
}

void Game::UpdatePlayer(System *system)
{
    if (player_ == 0)
        return;

    Keyboard *keyboard = system->GetKeyboard();

    float acceleration = 0.0f;
    if (keyboard->IsKeyHeld(VK_UP) || keyboard->IsKeyHeld('W'))
    {
        acceleration = 1.0f;
    }
    else if (keyboard->IsKeyHeld(VK_DOWN) || keyboard->IsKeyHeld('S'))
    {
        acceleration = -1.0f;
    }

    float rotation = 0.0f;
    if (keyboard->IsKeyHeld(VK_RIGHT) || keyboard->IsKeyHeld('D'))
    {
        rotation = -1.0f;
    }
    else if (keyboard->IsKeyHeld(VK_LEFT) || keyboard->IsKeyHeld('A'))
    {
        rotation = 1.0f;
    }

    player_->SetControlInput(acceleration, rotation);
    player_->Update(system);
    WrapEntity(player_);

    if (keyboard->IsKeyPressed(VK_SPACE))
    {
        D3DXVECTOR3 playerForward = player_->GetForwardVector();
        D3DXVECTOR3 bulletPosition = player_->GetPosition() + playerForward * 10.0f;
        SpawnBullet(bulletPosition, playerForward);
    }
}

void Game::UpdateAsteroids(System *system)
{
    for (AsteroidList::const_iterator asteroidIt = asteroids_.begin(),
        end = asteroids_.end();
        asteroidIt != end;
    ++asteroidIt)
    {
        (*asteroidIt)->Update(system);
        WrapEntity(*asteroidIt);
    }
}

void Game::UpdateBullet(System *system)
{
    if (bullet_)
    {
          bullet_->Update(system);
        WrapEntity(bullet_);
    }
}

void Game::WrapEntity(GameEntity *entity) const
{
    D3DXVECTOR3 entityPosition = entity->GetPosition();
    entityPosition.x = Maths::WrapModulo(entityPosition.x, -400.0f, 400.0f);
    entityPosition.y = Maths::WrapModulo(entityPosition.y, -300.0f, 300.0f);
    entity->SetPosition(entityPosition);
}

void Game::DeleteAllAsteroids()
{
    for (AsteroidList::const_iterator asteroidIt = asteroids_.begin(),
        end = asteroids_.end();
        asteroidIt != end;
        ++asteroidIt)
    {
        delete (*asteroidIt);
    }

    asteroids_.clear();
}

void Game::DeleteAllExplosions()
{
    for (ExplosionList::const_iterator explosionIt = explosions_.begin(),
        end = explosions_.end();
        explosionIt != end;
    ++explosionIt)
    {
        delete (*explosionIt);
    }

    explosions_.clear();
}

void Game::SpawnBullet(const D3DXVECTOR3 &position,
    const D3DXVECTOR3 &direction)
{
    DeleteBullet();
    bullet_ = new Bullet(position, direction);
    bullet_->EnableCollisions(collision_, 3.0f);
}

void Game::DeleteBullet()
{
    delete bullet_;
    bullet_ = 0;
}

void Game::SpawnAsteroids(int numAsteroids)
{
    float halfWidth = 800.0f * 0.5f;
    float halfHeight = 600.0f * 0.5f;
    for (int i = 0; i < numAsteroids; i++)
    {
        float x = Random::GetFloat(-halfWidth, halfWidth);
        float y = Random::GetFloat(-halfHeight, halfHeight);
        D3DXVECTOR3 position = D3DXVECTOR3(x, y, 0.0f);
        SpawnAsteroidAt(position, 3);
    }
}

void Game::SpawnAsteroidAt(const D3DXVECTOR3 &position, int size)
{
    const float MAX_ASTEROID_SPEED = 1.0f;

    float angle = Random::GetFloat(Maths::TWO_PI);
    D3DXMATRIX randomRotation;
    D3DXMatrixRotationZ(&randomRotation, angle);
    D3DXVECTOR3 velocity = D3DXVECTOR3(0.0f, Random::GetFloat(MAX_ASTEROID_SPEED), 0.0f);
    D3DXVec3TransformNormal(&velocity, &velocity, &randomRotation);

    Asteroid *asteroid = new Asteroid(position, velocity, size);
    asteroid->EnableCollisions(collision_, size * 5.0f);
    asteroids_.push_back(asteroid);
}

bool Game::IsAsteroid(GameEntity *entity) const
{
    return (std::find(asteroids_.begin(),
        asteroids_.end(), entity) != asteroids_.end());
}

void Game::AsteroidHit(Asteroid *asteroid)
{
    int oldSize = asteroid->GetSize();
    if (oldSize > 1)
    {
        int smallerSize = oldSize -1;
        D3DXVECTOR3 position = asteroid->GetPosition();
        SpawnAsteroidAt(position, smallerSize);
        SpawnAsteroidAt(position, smallerSize);
    }
    DeleteAsteroid(asteroid);
}

void Game::DeleteAsteroid(Asteroid *asteroid)
{
    asteroids_.remove(asteroid);
    delete asteroid;
}

void Game::UpdateCollisions()
{
    collision_->DoCollisions(this);
}

 

 

 

 

 

this is Game.cpp

You are doing it wrong. Why are you using so many pointers? To pick one example, Game::camera_ seems to be a pointer. Why?

You can simply use objects --not pointers to objects-- in most places and let the destructors be called automatically. For the few situations where you do need a pointer (say, because you want to have a container of objects derived from a common base class, with polymorphic behavior), you probably want to use something like std::unique_ptr, which again will clean up nicely automatically.

 

6 minutes ago, alvaro said:

You are doing it wrong. Why are you using so many pointers? To pick one example, Game::camera_ seems to be a pointer. Why?

You can simply use objects --not pointers to objects-- in most places and let the destructors be called automatically. For the few situations where you do need a pointer (say, because you want to have a container of objects derived from a common base class, with polymorphic behavior), you probably want to use something like std::unique_ptr, which again will clean up nicely automatically.

 

Hey Alvaro. Thanks for going through the code but this is a test that I have got. I am supposed to find the bugs in this code and something is forcing the build to crash. But I'll honestly let them know a more optimized code for the given. Anyways the main issue is the bug. I have already fixed a few but I can't know what is causing this game to crash

 

Thanks

34 minutes ago, sidbhati32 said:

I am supposed to find the bugs in this code

You said this was your code.

If this is a test (which you say it is), we won't solve it for you. Ask the people who gave you the test for a hint.

Hello to all my stalkers.

12 minutes ago, Lactose said:

You said this was your code.

If this is a test (which you say it is), we won't solve it for you. Ask the people who gave you the test for a hint.

Yeah it is. Kind of an assignment or a test you can say. But no problem. You can give me hints for doing it either? It will land me a job, that's what I want to say.

Placeholder values like 0xCD or 0xDEADBEEF are often used by debug builds to catch initialization errors like this. The error message in the first screen suggests to me that  `Game::bullet_` is nonzero but also uninitialized; find out why.

Are you sure you deserve the job, if you don't know C++ and debugging skills?

RIP GameDev.net: launched 2 unusably-broken forum engines in as many years, and now has ceased operating as a forum at all, happy to remain naught but an advertising platform with an attached social media presense, headed by a staff who by their own admission have no idea what their userbase wants or expects.Here's to the good times; shame they exist in the past.
15 minutes ago, sidbhati32 said:

It will land me a job, that's what I want to say.

If you need more help than given by the people assigning the test, you aren't currently at a good enough level to deserve the job. Helping you means tricking the employers.

Hello to all my stalkers.

This topic is closed to new replies.

Advertisement