Problem with creating array of bullets/ SDL2.0 Game


#1

Hi, I am trying to make an array of bullets in my first game, but i have a problem. When I have just one bullet, everything works, but i need to have more of them. Crucial parts of a code:

Player.h

#ifndef _PLAYER_H
#define _PLAYER_H

class Player
{
private:
SDL_Texture* playerTexture;

Game* game;

public:

int getPlayerWidth() const;
int getPlayerHeight() const;

int player_w;
int player_h;

int GetPosX();
int GetPosY();

Player(Game&, std::string);

void HandleEvent(SDL_Event& e);

void move();
bool loadFromFile(std::string);
void render();

static const int MAX_BULLETS = 10;
Bullet* mBullets[MAX_BULLETS];

~Player();

private:

int mPospX, mPospY;
int mVelpX, mVelpY;
};

#endif

Bullet.h

#ifndef _BULLET_H
#define _BULLET_H

class Bullet
{
private:

SDL_Texture* bulletTexture;

Game* game;

public:

  Bullet(Game& game);									     				
  bool loadFromFile(std::string);											

  int GetBulletWidth() const;												
  int GetBulletHeight() const;											
  bool GetIsAlive();														

  void Update();															
  void Fire(int StartPosX, int StartPosY, int XSpeed, int YSpeed);		
  void Render();															

private:

  bool IsAlive;															
  int mPosbX;																
  int mPosbY;																
  int mVelbX;																
  int mVelbY;																
  int bullet_w;															
  int bullet_h;															

};

#endif

Player::Player(Game& game, std::string path)
{
this->game = &game;

mVelpX = 0;
mVelpY = 0;

player_w = 70;
player_h = 70;

mPospX = this->game->getWindowWidth() / 2 - player_w / 2;
mPospY = this->game->getWindowHeight()*0.9 - player_h;

for (int i = 0; i < MAX_BULLETS;i++)
{
mBullets[i] = new Bullet(game);
}

loadFromFile(path.c_str());
}

void Player::HandleEvent(SDL_Event& e)
{

case SDLK_SPACE:
for (int i = 0; i < MAX_BULLETS;i++)
{
mBullets[i]->Fire(GetPosX() + getPlayerWidth() / 2 - mBullets[i]->GetBulletWidth / 2, GetPosY() - getPlayerHeight() / 2 + mBullets[i]->GetBulletHeight(), 0, 7);
}
break;

void Player::move()
{
mPospX = mPospX + mVelpX;

if ((mPospX > game->getWindowWidth() - player_w) || (mPospX < 0))
{
mPospX = mPospX - mVelpX;
}

if ((mPospX < game->getBorderL(mPospY)) || (mPospX + player_w > game->getBorderR(mPospY)))
{
printf(“collision\n”);
}

mPospY = mPospY + mVelpY;

if ((mPospY < 0) || (mPospY + player_h / 2 > game->getWindowHeight()*0.9 - player_h / 2))
{
mPospY = mPospY - mVelpY;
}

for (int i = 0; i < MAX_BULLETS;i++)
{
mBullets[i]->Update();
}
}

void Player::render()
{
SDL_Rect renderQuad = { mPospX, mPospY, player_w, player_h };
SDL_RenderCopy(game->renderer, playerTexture, NULL, &renderQuad);

for (int i = 0; i < MAX_BULLETS;i++)
{
mBullets[i]->Render();
}
}

Bullet.cpp

Bullet::Bullet(Game& game)
{
this->game = &game;

std::string path = "img/bullet.png";

IsAlive = false;
mPosbX = 0;
mPosbY = 0;
mVelbX = 0;
mVelbY = 0;

loadFromFile(path.c_str());

}

void Bullet::Update()
{

	if (IsAlive)
	{
		mPosbX = mPosbX + mVelbX;
		mPosbY = mPosbY - mVelbY;
	}
	if (mPosbY < 0)
	{
		IsAlive = false;
	}

}

void Bullet::Fire(int StartPosX, int StartPosY, int XSpeed, int YSpeed)
{

	mPosbX = StartPosX;
	mPosbY = StartPosY;
	mVelbX = XSpeed;
	mVelbY = YSpeed;
	IsAlive = true;

}

void Bullet::Render()
{

	if (IsAlive)
	{
		SDL_Rect renderQuad = { mPosbX, mPosbY, bullet_w, bullet_h };
		SDL_RenderCopy(game->renderer, bulletTexture, NULL, &renderQuad);
	}

}

Problems I recieve, trying to debug:
‘mBullets’: undeclared identifier- in loops using mBullets[i]

Do you have any advices, what should I try to do?


#2

Bullet* mBullets[MAX_BULLETS];

By doing this, you’re statically defining (in this case) 10 pointers on (in this case) 10 Bullet arrays.
You can either change it to a dynamic array, using a double pointer:
Bullet** m_pBullets*[MAX_BULLETS];
And then new each bullet.

Or you can dynamically fill an STL container instead, which I highly recommend:
std::vector<Bullet*> m_BulletVector;

In the creation process, you can create the bullets like this:

for(unsigned int i = 0; i < MAX_BULLETS; ++i)
{
	m_BulletVector.emplace_back(new Bullet(game));
}

Then, in the update process, you can update the bullets like this:

std::vector<Bullet*>::iterator ItBeg = m_BulletVector.begin();
std::vector<Bullet*>::iterator ItEnd = m_BulletVector.end();

for(; ItBeg != ItEnd; ++ItBeg)
{
	(*ItBeg)->Update();
}

And finally, in the render process, you can render the bullets like this:

std::vector<Bullet*>::iterator ItBeg = m_BulletVector.begin();
std::vector<Bullet*>::iterator ItEnd = m_BulletVector.end();

for(; ItBeg != ItEnd; ++ItBeg)
{
	(*ItBeg)->Render();
}

#3

I have just found a solution, sometimes i don’t see simple, but crucial things. What i had to do was just add #include in player.h, not just in player.cpp and now it works. I will try to use dynamic array as You said. Thanks for help <3.


#4

But aren’t std::vectors kind of slower than pure C arrays?


#5

I have no knowledge of that, but you might be right. The bullets are created at the startup of the game and not during runtime though, so it won’t matter when it comes to performance.
During the update and render of the bullets (i.e while looping through the std::vector), I guess it might be slow, but as long as there’s only a few bullets there won’t be a performance problem there either.