SDL Velocity Regulation Problem

Started by
4 comments, last by rip-off 15 years, 4 months ago
I have been working on a game for a little whiles now and I recently have gotten my plane to shoot. However, I can't seem to regulate the speed of the bullet. First shot, its a good speed, second is way too fast. This is my code: Bullet::Bullet() { //Initialize the velocity bXVel = 0; bYVel = 0; isShooting = false; isMoving = false; } void Bullet::handle_input(int x, int y) { //If a key was pressed if( event.type == SDL_KEYDOWN ) { //Adjust the velocity switch( event.key.keysym.sym ) { case SDLK_SPACE: //Initialize the offsets bX = x; bY = y; isShooting = true; isMoving = true; break; } } } void Bullet::show() { if (isShooting) { apply_surface ( bX + 40, bY + 23, bullet, screen ); bXVel += BULLET_WIDTH / 20; } } void Bullet::move() { if (isMoving) { //Move the bullet left or right bX += bXVel + 1; } if ( bX + BULLET_WIDTH == SCREEN_WIDTH ) { SDL_FreeSurface( bullet ); bX = 0; bY = 0; bXVel = 0; isShooting = false; isMoving = false; } } I do have a frame rate regulator that regulates the "screen"'s framerate and the bullet is being applied to the screen, wouldnt that work?
Advertisement
We would need to see the calling code.

Are you limiting the "logical" framerate (the number of times per second your game logic, like movement, is allowed to happen) in addition to the graphical framerate?
Quote:Original post by rip-off
We would need to see the calling code.

Are you limiting the "logical" framerate (the number of times per second your game logic, like movement, is allowed to happen) in addition to the graphical framerate?


//Cap the frame rate
if( fps.get_ticks() < 1000 / FRAMES_PER_SECOND )
{
SDL_Delay( ( 1000 / FRAMES_PER_SECOND ) - fps.get_ticks() );
}
}

const int FRAMES_PER_SECOND = 40;

Thats it for limitation.

How do you limit logic?
Well, looking at your code more carefully I can see some problems.

Why do you adjust the velocity in show()?

Why do you add bXVel + 1 to bX?

Why do you free the surface in move() when you don't acquire it in this class?

Is event global? Why not pass it to the function instead?

Why aren't all the variables reset when SPACE is pressed? Why are you using switch() when you are only testing for a specific case?

Can a bullet be shooting and not moving? What about movingand not shooting? If these combinations don't make sense, then maybe the two conditions are really one and the same.

I think your comparison should be this:
if ( bX + BULLET_WIDTH >= SCREEN_WIDTH ){   // ...}

Otherwise your bullet could leave the screen without being reset (which I think is what is happening).

This is overlooking "bigger picture" issues, such as why are you trying to reuse bullet instances at all. It would simplify everything if you didn't do this.
Quote:Original post by rip-off
Well, looking at your code more carefully I can see some problems.

Why do you adjust the velocity in show()?

Why do you add bXVel + 1 to bX?

Why do you free the surface in move() when you don't acquire it in this class?

Is event global? Why not pass it to the function instead?

Why aren't all the variables reset when SPACE is pressed? Why are you using switch() when you are only testing for a specific case?

Can a bullet be shooting and not moving? What about movingand not shooting? If these combinations don't make sense, then maybe the two conditions are really one and the same.

I think your comparison should be this:
*** Source Snippet Removed ***
Otherwise your bullet could leave the screen without being reset (which I think is what is happening).

This is overlooking "bigger picture" issues, such as why are you trying to reuse bullet instances at all. It would simplify everything if you didn't do this.


Ok,I am fairly new to SDL and I dont udnerstand all the functions yet. But to answer a few of your questions:
1) I I just havnt botherd moving that peice of code down, I've just been trying to mkae it work
2) Just makes it move by an interval of 2 instead of 1
3) So the bullet doesnt go off the screen and crash the program. I dont understand what aquire is
4)The rest i dont understand of your questions

As far as the comparison goese to show it's off the screen or not, I don't understand whats so wrong with mine. It simpily looks the same in different context.

Sorry that my knowledge it quite limited, so please bear with me on this.
Quote:
Just makes it move by an interval of 2 instead of 1

If you want to move it by 2, then set XVel to 2. I don't understand why you do this:
bXVel += BULLET_WIDTH / 20;

Quote:
So the bullet doesnt go off the screen and crash the program.

If the bullet goes off the screen it won't crash the program.

Quote:
I dont understand what aquire is

In this context, it means to load the surface. For example, a call to SDL_LoadBMP(). If you call SDL_FreeSurface(bullet), then the bullet pointer is invalid. However, when the space bar is pressed again you will want the bullet surface. So you shouldn't free it.

Quote:
As far as the comparison goese to show it's off the screen or not, I don't understand whats so wrong with mine. It simpily looks the same in different context.

They are very different.

Lets say that x = 21 and y = 50. I am going to assume BULLET_WIDTH is 20, and SCREEN_WIDTH is 600. If we move the bullet by 2 pixels every frame, then the bullet can never be exactly equal at SCREEN_WIDTH.


Here is a quick mock up of how I might write it:
class Bullet{public:   Bullet(int x, int y, int speed)   :      x(x),      y(y),      vx(speed),      vy(0)   {   }   void draw(SDL_Surface *screen, SDL_Surface *bullet)   {      // These magic numbers should really be explained.      // I just assume they are right...      apply_surface( x + 40, y + 23, bullet, screen );   }   // Returns true as long as the bullet is inside the screen (x only)   bool update()   {      x += vx;      y += vy;      return x >= 0 && (x + BULLET_WIDTH) < SCREEN_WIDTH;   }private:   int x, y, vx, vy;};#include <vector>int main(int, char**){    // init SDL    // load images    Ship ship;    std::vector<Bullet> bullets;    bool running = true;    while(running)    {        SDL_Event event;        while(SDL_PollEvent(&event))        {           if(event.type == SDL_KEYDOWN)           {              if(event.key.keysym.sym == SDLK_SPACE)              {                  Bullet bullet(ship.x(),ship.y(),/* figure out direction */);                  bullets.push_back(bullet);              }           }        }        ship.update();        for(int i = 0 ; i < bullets.size() ; ++i)        {            if(!bullets.update())            {                bullets.erase(bullets.begin() + i);                --i; // Don't skip any elements            }        }        ship.draw(screen,shipSurface);        for(int i = 0 ; i < bullets.size() ; ++i)        {            bullets.draw(screen,bulletSurface());        }        // limit frame rate    }    // clean up}

Notice:
- no globals
- we can have many bullets
- we never reuse bullet instances
- we can have any number of bullets on screen at once
- when a bullet leaves the screen
- no booleans for "shooting" of "moving", every bullet is always moving and shooting
- the bullet logic is much simpler

This topic is closed to new replies.

Advertisement