# SDL Bullet Movement

I'm currently working on my first space shooter, and I'm in the process of making my ship shoot some bullets/lasers. Unfortunately, I'm having a hard time getting the bullets to fly vertically. I'm a total noob when it comes to this so you might have a hard time understanding my code :/

    // Position Bullet Function
projectilex = x + 17;
projectiley = y + -20;
if(keystates[SDLK_SPACE])
{
alive = true;
}


And here's my show function

    if(alive)
{

if(frame == 2)
{
frame = 0;
}
apply_surface(projectilex,projectiley,ShootStuff,screen,&lazers[frame]);
frame++;
projectiley + 1;
}


I'm trying to get the bullet to fly vertically... and I have no clue how to do that. I've tried messing with the y coordinate but that makes things worse. The laser/bullet just follows the ship :(

How would I get it to fire at the starting position and keep going in a vertical line without it following the ship?

int main( int argc, char* args[] )
{
Player p;
Timer fps;
bool quit = false;
if( init() == false )
{
return 1;
}

{
return 1;
}

clip[ 0 ].x = 0;
clip[ 0 ].y = 0;
clip[ 0 ].w = 30;
clip[ 0 ].h = 36;

clip[ 1 ].x = 31;
clip[ 1 ].y = 0;
clip[ 1 ].w = 39;
clip[ 1 ].h = 36;

clip[ 2 ].x = 71;
clip[ 2 ].y = 0;
clip[ 2 ].w = 29;
clip[ 2 ].h = 36;

lazers [ 0 ].x = 0;
lazers [ 0 ].y = 0;
lazers [ 0 ].w = 3;
lazers [ 0 ].h = 9;

lazers [ 1 ].x = 5;
lazers [ 1 ].y = 0;
lazers [ 1 ].w = 3;
lazers [ 1 ].h = 7;

while( quit == false )
{
fps.start();
//While there's an event to handle
while( SDL_PollEvent( &event ) )
{
p.handle_input();
//If a key was pressed

//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
quit = true;
}

}

//Scroll background
bgX -= 8;

//If the background has gone too far
if( bgX <= -GameBackground->w )
{
//Reset the offset
bgX = 0;
}
p.move();
apply_surface( bgX, bgY,GameBackground, screen );
apply_surface( bgX + GameBackground->w, bgY, GameBackground, screen );

apply_surface(0,0, FullHealthBar,screen);

p.shoot();
p.show();
//Apply the message
//Update the screen
if( SDL_Flip( screen ) == -1 )
{
return 1;
}
SDL_Flip(GameBackground);
if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
{
SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
}
}
//Clean up
clean_up();
return 0;
}

• Wow, kinda strange your functions. Can you add more details? Like where/when they're called/triggered? Jan 19, 2012 at 3:05
• Oh sorry :(. The position bullet function is called whenever the user presses the space bar and so is the show function so it kind of looks like this: if(keystates[SDLK_SPACE]){//Position Bullet Function go here //show function go here}
– Grey
Jan 19, 2012 at 3:08
• Oh, nevermind. And wow haha, now you confused myself, or yourself! if you know that the space is pressed to call the position function, why do you check inside the function if space is pressed? i dont know what you're trying, but there may be a better way! Jan 19, 2012 at 3:12
• By the way, i have an answer, but i may still want to see more from your code. So i make sure that it will well integrate for you. But if you care sharing, tell me so i post it more "pseudo code" that may still work for you. And use the edit button! it's way better than adding code in the comments :) Jan 19, 2012 at 3:14
• Alright. I gave you my main. Is that enough? Thanks for all your help!
– Grey
Jan 19, 2012 at 4:07

Well i was about to write a formerly answer, but seeing your code, it appears that you dont have any Entity system. So it may complicate you, but lets try to solve this.

We need a class to follow what are those bullets, and where are they, dont we?

So lets create something!

class Bullet
{
Vector2 position;
Vector2 speed;
};


What must we do? Lets try to describe in plain english what will the code do to shoot bullets.

Every frame, check if the space bar is pressed. If it is pressed, and wasnt before, create a new bullet, going to where the player is faced. If the bullet hits something, delete it, make some nice explode animation and take hp of the object that took the hit. If the bullet just goes after the screen boundaries, just delete it.

Lets try to pass it to C++.

First of all, you have to have some kind of container to storage your bullets. Of course you'll have more than one, so thats why.

Some kind like this on your initialization should do:

std::list<Bullet*> bullets;


I dont recommend lists for a game, but they're easier to deal for now.

Now, the code to shoot:

if(event.type == SDL_KEYDOWN)
{
if(event.key == SDLK_SPACE)
{
Bullet* toShoot = new Bullet();
toShoot.speed = player.direction * 5;
toShoot.position = player.position + toShoot.speed;
}

}


The most tricky part here is the player.direction * 5; Well, probably, you have a vector pointing where the player is facing, if you dont have, you SHOULD! When you multiply a vector by a number, you can get a nice speed direction going to that direction! so you'll have a 5px going into that direction. That may not be too right, but should work as a basis for you. Study distance and the pitagoras's formula d = sqrt(x^2 + y^2); If you just want the bullet to go up, change toShoot.speed = player.direction * 5;with toShoot.speed = Vector(0, 5);

for(list<Bullet*>::iterator it = bullets.begin(); it != bullets.end();)
{
(*it)->position += (*it)->speed;
if(isOutOfBound((*it)->position))
{
delete (*it);
bullets.erase(it++); //remove from the list and take next
}
else if(collideWithSomething((*it)->position))
{
Entity collisor = getCollisor((*it)->position);
collisor.takeHit();
playSound(Explosion);
makeAnimation(Explosion);
delete (*it);
bullets.erase(it++);
}
else
{
++it; //take next object
}
}


This should do :D

Remembering, the most of these classes you maybe dont have, but you should think about creating something similar.

PBullet.XPos=XPos+Enterprise.LImageLength/2; //get bullet YX start ship location
PBullet.YPos=YPos+Enterprise.LImageHeight/2; //get bullet YX start ship location
PBullet.XVel= PBullet.ShipSpeed*cos(ShipFacing);  //work out angle of bullet
PBullet.YVel= PBullet.ShipSpeed*sin(ShipFacing);  //work out angle of bullet
PBullet.TimeOfEvent= SDL_GetTicks(); //start timer for duration of bullet alive


You also need somthing like

GameObject ::apply_surface(SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip)
{
SDL_Rect sourceImage;
sourceImage.x = ShipSpritesheetX; //position in image file left to right
sourceImage.y = ShipSpritesheetY; //position in image file up and down
sourceImage.w = LImageHeight; //width of sprite in image
sourceImage.h = LImageLength; //height of sprite in image
SDL_Rect offset; //Holds offsets
offset.x = XPos;  //Get offsets
offset.y = YPos;
SDL_BlitSurface( source, &sourceImage, destination, &offset );  //Blit
}

PBullet.apply_surfacing(PlayerBullet, screen,NULL ); //display bullet while firing