Advertisement

Drawing Multiple Sprites (projectiles)

Started by January 07, 2015 11:23 AM
18 comments, last by BeerNutts 10 years ago

Hi,

I'm trying to create more than one projectile in an array because using when using one projectile, when you fire a second time, the first projectile disappears for the projectile to fire again.

I thought using for-loops would the best way to go about it but not sure what I am doing wrong.


//Here is instantiating the class
for (int i = 0; i < PROJECTILES; i++)
{
_projectile[i] = new Projectile();
}

//Projectile Inits
for (int i = 0; i < PROJECTILES; i++)
{
_projectile[i]->_speed = 0.8f;
_projectile[i]->_frameTime = 250;
_projectile[i]->_launched = false;
}

//Loading Projectile Content
for (int i = 0; i < PROJECTILES; i++)
	{
		_projectile[i]->_texture = new Texture2D();
		_projectile[i]->_boundry = new Rect();
		_projectile[i]->_texture = projTexture;
		_projectile[i]->_boundry = projRect;
	}

//Spacebar to fire
for (int i = 0; i < PROJECTILES; i++)
	{
		if (state->IsKeyDown(Input::Keys::SPACE))
		{
			_projectile[i]->_boundry->X = _player->_position->X + 35;
			_projectile[i]->_boundry->Y = _player->_position->Y + 59;
			_projectile[i]->_launched = true;
		}
		if (i == 5)
		{
			i = 0;
		}
	}

/?Draw Projectile
for (int i = 0; i < PROJECTILES; i++)
	{
		if (_projectile[i]->_launched)
		{
			SpriteBatch::Draw(_projectile[i]->_texture, _projectile[i]->_boundry, 0.5f, 0.0f);
			_projectile[i]->_boundry->Y -= _projectile[i]->_speed * elapsedTime;
		}
	}

Now the issue I'm having is that PROJECTILES = 5 so it draws all five projectiles at the same time below each other, and when fired the all move together.
The speed is also stacking so the five projectiles move faster than the 1 projectile should be moving at.

Not sure what mistakes I am making and I'm not sure if I have given enough information.

Thank you

Ryan

When that sort of problem happens you usually update the old projectiles with new information, overwriting whatever they had before. Make sure you only fire a projectile once.

In your code you iterate over the array and when you press space you select one of the five projectiles and change it. You should instead have an array that you add projectiles too and later update only the ones in there, and remove them if they hit or go too far away or whatever.

1. Fire -> add to array.

2. Update -> update the ones in the array (remove from array if they are 'dead')

3. Draw -> draw the ones in the array.

Advertisement

//Loading Projectile Content
for (int i = 0; i < PROJECTILES; i++)
	{
		_projectile[i]->_texture = new Texture2D();
		_projectile[i]->_boundry = new Rect();
		_projectile[i]->_texture = projTexture;
		_projectile[i]->_boundry = projRect;
	}

I highly doubt anything will work at all with this kind of code.
This makes absolutely no sense.
You create new pointers, and then you change them to something else immediately (which is also a memory leak and a crash if you ever actually attempted to free this memory).

All 5 bullets are pointing to the same texture and boundary. Very clearly they will all be drawn in the same spot. If they aren’t, you have another bug (hint: don’t mix updating and rendering as you are doing now).



    //Spacebar to fire
    for (int i = 0; i < PROJECTILES; i++) {
        if (state->IsKeyDown(Input::Keys::SPACE)) {
            _projectile[i]->_boundry->X = _player->_position->X + 35;
            _projectile[i]->_boundry->Y = _player->_position->Y + 59;
            _projectile[i]->_launched = true;
        }
        if (i == 5) {
            i = 0;
        }
    }

Why are you setting i to 0?


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

When that sort of problem happens you usually update the old projectiles with new information, overwriting whatever they had before. Make sure you only fire a projectile once.

In your code you iterate over the array and when you press space you select one of the five projectiles and change it. You should instead have an array that you add projectiles too and later update only the ones in there, and remove them if they hit or go too far away or whatever.

1. Fire -> add to array.

2. Update -> update the ones in the array (remove from array if they are 'dead')

3. Draw -> draw the ones in the array.

How do you 'remove' from an array. I know you can remove from an List but not from an Array.


//Loading Projectile Content
for (int i = 0; i < PROJECTILES; i++)
	{
		_projectile[i]->_texture = new Texture2D();
		_projectile[i]->_boundry = new Rect();
		_projectile[i]->_texture = projTexture;
		_projectile[i]->_boundry = projRect;
	}
I highly doubt anything will work at all with this kind of code.
This makes absolutely no sense.
You create new pointers, and then you change them to something else immediately (which is also a memory leak and a crash if you ever actually attempted to free this memory).

All 5 bullets are pointing to the same texture and boundary. Very clearly they will all be drawn in the same spot. If they aren’t, you have another bug (hint: don’t mix updating and rendering as you are doing now).




    //Spacebar to fire
    for (int i = 0; i < PROJECTILES; i++) {
        if (state->IsKeyDown(Input::Keys::SPACE)) {
            _projectile[i]->_boundry->X = _player->_position->X + 35;
            _projectile[i]->_boundry->Y = _player->_position->Y + 59;
            _projectile[i]->_launched = true;
        }
        if (i == 5) {
            i = 0;
        }
    }
Why are you setting i to 0?


L. Spiro

It made no sense because I missed a bit of code out where I was assigning a Texture2D-Load("", false) to a variable and then assign that to the bit inside the loop. According to my lecturer it was more efficient.

I was setting i=0 so that it would re-iterate through the loop after the loop had reached PROJECTILES.

Doing it by hand would involve having the array as well as remembering how many elements are in it. Removing means decrementing the remembered number of elements and overwriting the removed element with one of the existing elements (either by swapping with the last element or moving all elements behind it one towards the front).

Of course I would not do that by hand without a very good reason because std::vector would encapsulate most of the annoying groundwork for me, including the ability to grow if the current array cannot store all currently active projectiles.
Advertisement

I was setting i=0 so that it would re-iterate through the loop after the loop had reached PROJECTILES.


Modifying the variable a for-loop is iterating over inside the loop is one of those things that will make people you are working with/for extremely angry with you. If you need finer control over the iteration (and you do not need that here, I have no clue what you are trying there) use a while-loop.


All 5 bullets are pointing to the same texture and boundary. Very clearly they will all be drawn in the same spot. If they aren’t, you have another bug (hint: don’t mix updating and rendering as you are doing now).

The image used is supposed to be the same and they are supposed to be drawn from the same position. It's just when I press the spacebar, they all draw at the same time :-( I need them to draw one at a time.


I was setting i=0 so that it would re-iterate through the loop after the loop had reached PROJECTILES.

I see no reason why you should need to 're-iterate' through that loop. In fact, the way that loop is currently presented is an infinite loop. The snippets of code as you've presented them aren't going to draw anything cause it never gets out of that 'Spacebar to fire' loop, so what are we missing?

Your "spacebar to fire" code loops will set all projectiles to fire, using the same position. The keydown check will be the same for the entire loop, so if it's true for the first iteration of the loop, it will be true for all of them.

What you could do instead is something like:

- Check if spacebar is pressed.

- If it is, iterate over the array, checking if the projectile is not launched.

- If a projectile is not launched, launch it, and stop looping through the array.

You will need to clear the "launched" flag when the projectile has done whatever it should be doing.

And, as already mentioned, you shouldn't update logic in your draw code.

Another way of doing this would be to e.g. have a std::vector of projectiles, and add a new projectile to the vector when you press the spacebar.

Hello to all my stalkers.

This topic is closed to new replies.

Advertisement