Bullets not spawning properly

I am trying to make a BulletHell game using SDL2 but I am having troubles with spawning bullets. I tried making a list/vector that was going to store my bullets and on keypress was going to shoot them out iterating through the list. Unfortunately I can still only shoot only one bullet at a time, but if I press the shoot key twice it does not copy the bullet again like in LazyFoo’s tutorial, nor does it keep shooting 10 bullets. It only shoots the one and I have to wait for the bullet to go out of the screen to shoot again. Here’s my code: https://gist.github.com/cogile1312/5f616e09f861103f74bc67c31368cb6b

Hello and welcome to the forum!

Each time a key pressed (‘k’) event is occurring, you’re looping through your bullet list and set each bullets state to active, is this intentional? If it’s indeed intentional, what do you hope to achieve with that?

Don’t you instead only want to pick one (1) free bullet from the list and update the position and state of that specific bullet, along with bullets that has previously been shot and not yet has been destroyed?
Or are you planning on shooting a big group of bullets at the same time?

What’s happening in your code at the moment is that each bullet spawns and is set to the same position. They are then updated and moved at the same speed and what looks like 1 bullet is actually all your bullets being rendered on top of each other, moving at the same speed, in the same direction.

Well, that makes sense. My intention is to on key press to shoot one bullet and on keyhold to rapid fire the 10 bullets in the list.

What I recommend you to do is to have two lists.
The first list is a static list containing all the created bullets. This list is created at the startup of the application and destroyed/cleared at the application shutdown.
The second list is a dynamic list containing bullet object pointers. This list is filled during application runtime and cleared at the end of each frame.

What you then basically need to do is this, in the named order:

  1. Poll for key events.
  2. If a key event occur, and if the key that’s being pressed is ‘k’, check the static bullet list and look for a bullet object that’s unused (i.e, that has the bool variable active set to false).
  3. If a free bullet is found, set that bullet to used (i.e, set the bool variable active to true).
  4. Add a pointer to that specific bullet object into the dynamic bullet list.
  5. Loop through the dynamic bullet list and update and render each bullet object inside it. When a bullet object should be destroyed (for example when it collides with a wall, an enemy etc), mark that specific bullet object as unused (i.e, set the bool variable active to false) and then remove it from the dynamic bullet list. The actual bullet won’t be destroyed in the static bullet list, only the pointer to it that’s in the dynamic bullet list, and when a bullet should later be shot, that bullet object can be picked again. The static bullet list is basically a bullet object pool.

By using this object pool pattern, you avoid creating and destroying bullets during runtime and also avoid copying data around.

Okay, I’m just having troubles with the syntax now, how do I pick only one bullet with the not active flag ? How do I make it so that I don’t select all of the bullets with the bool variable actove set to false ?

What you need to do to retrieve a free bullet object from your static bullet list (if you use the procedure I mentioned in my previous post) is to loop through the list, check for a bullet object that isn’t in use, set it to a used state and then return it to be used/updated/rendered later.

Code example
typedef std::vector<CBullet*> BulletList;

void Update(void)
{
	if(MouseButtonPressed(MOUSE_BUTTON_LEFT))
	{
		CBullet* pBullet = RetrieveFreeBullet();

		if(pBullet)
			DynamicBulletList.push_back(pBullet);
	}

	BulletList::const_iterator ItBeg = DynamicBulletList.begin();
	BulletList::const_iterator ItEnd = DynamicBulletList.end();

	for(; ItBeg != ItEnd;)
	{
		CBullet* pBullet = (*ItBeg);

		UpdateBulletPosition(pBullet);

		if(BulletVsGeometry(pBullet) || BulletVsEnemy(pBullet))
		{
			pBullet->SetIsInUse(false);

			DynamicBulletList.erase((*ItBeg));
		}

		else
			++ItBeg;
	}
}

void Render(void)
{
	BulletList::const_iterator ItBeg = DynamicBulletList.begin();
	BulletList::const_iterator ItEnd = DynamicBulletList.end();

	for(; ItBeg != ItEnd; ++ItBeg)
	{
		RenderBullet((*ItBeg));
	}
}

CBullet* RetrieveFreeBullet(void)
{
	BulletList::const_iterator ItBeg = StaticBulletList.begin();
	BulletList::const_iterator ItEnd = StaticBulletList.end();

	for(; ItBeg != ItEnd; ++ItBeg)
	{
		CBullet* pBullet = (*ItBeg);

		if(pBullet->GetIsInUse())
			continue;

		pBullet->SetIsInUse(true);

		return pBullet;
	}

	/*
	If no free bullet is found, nullptr is returned
	You might always wanna return a valid bullet object pointer so instead of returning nullptr, 
	you can return the first bullet object in the list or maybe a random index
	*/
	return nullptr;
}