SDL// Help With Gravity

Started by
1 comment, last by Justindano 12 years, 7 months ago
Hey guys,
Ive been doing some testing grounds with gravity and my square can jump, It jumps very cool But my problem is when it comes back down it doesnt stop, it keeps going down and down.. I tried to set it but yet i cant make it happen,
Please help me,
Thanks in Advance :)

//Code::

//Libs
#include <sdl.h>
#include <sdl_image.h>
#include <string>

//Screen attbs
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//Frames
const int FRAMES_PER_SECOND = 20;

//Square attbs
const int SQUARE_WIDTH = 20;
const int SQUARE_HEIGHT = 20;

//Coin attbs
const int OBJECT_WIDTH = 100;
const int OBJECT_HEIGHT = 100;

//The surfaces
SDL_Surface *square = NULL;
SDL_Surface *object = NULL;
SDL_Surface *screen = NULL;

SDL_Rect box1;

//Event
SDL_Event event;

class Square
{
private:
//Collision box
SDL_Rect box;

//Offset and velocity
int x, y;
int xVel, yVel;
int xAccel, yAccel;
public:
Square();

//Handle input, move and show
void handle_input();

void show();
void move();

bool Jumping;
};

//Timer
class Timer
{
private:
//The clock time
int startTicks;

//The paused ticks
int pausedTicks;

//Timer status
bool paused;
bool started;

public:
//Init variables
Timer();

//The timer
void start();
void stop();
void pause();
void unpause();

//Get timers time
int get_ticks();

//Check status
bool is_started();
bool is_paused();
};

SDL_Surface *load_image( std::string filename )
{
//The images
SDL_Surface *loadedImage = NULL;
SDL_Surface *optimizedImage = NULL;

//Load the image
loadedImage = IMG_Load( filename.c_str() );

if( loadedImage != NULL )
{
//Set optimizedImage
optimizedImage = SDL_DisplayFormat( loadedImage );

//Free surface
SDL_FreeSurface( loadedImage );

if( optimizedImage != NULL )
{
//Set colorkey
SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF ) );

}
}

return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
//Hold offset
SDL_Rect offset;

//Get offset
offset.x = x;
offset.y = y;

//Blit the surface
SDL_BlitSurface( source, clip, destination, &offset );
}

bool check_collision( SDL_Rect A, SDL_Rect B )
{
//Sides of rect A and B
int leftA, leftB;
int rightA, rightB;
int topA, topB;
int bottomA, bottomB;

//Calculate the sides of rectA
leftA = A.x;
rightA = A.x + A.w;
topA = A.y;
bottomA = A.y + A.h;

//Calculate sides of rectB
leftB = B.x;
rightB = B.x + B.w;
topB = B.y;
bottomB = B.y + B.h;

//Check if sides hit
if( bottomA <= topB )
{
return false;
}
if( topA >= bottomB )
{
return false;
}
if( leftA >= rightB )
{
return false;
}
if( rightA <= leftB )
{
return false;
}
return true;
}

bool init()
{
//Initialize
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return false;
}

//Setup screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

if( screen == NULL )
{
return false;
}

//Set caption
SDL_WM_SetCaption( "Collision test", NULL );

return true;
}

bool load_files()
{
//Load the square
square = load_image( "square.bmp" );
if( square == NULL)
{
return false;
}

//Load the object
object = load_image( "object.png" );
if( object == NULL )
{
return false;
}

return true;

}

void clean_up()
{
//Free the surfaces
SDL_FreeSurface( square );
SDL_FreeSurface( object );
SDL_FreeSurface( screen );

SDL_Quit();
}

Square::Square()
{
box.x = 1;
box.y = 460;
box.w = SQUARE_WIDTH;
box.h = SQUARE_HEIGHT;

xVel = 0;
yVel = 40;

xAccel = 0;
yAccel = 5;

Jumping = false;
}

void Square::handle_input()
{
//If key was pressed
if( event.type == SDL_KEYDOWN )
{
switch( event.key.keysym.sym )
{
case SDLK_LEFT: xVel -= SQUARE_WIDTH /3; break;
case SDLK_RIGHT: xVel += SQUARE_WIDTH /3; break;
case SDLK_SPACE:
yVel = 40;
Jumping = true;
}
}
else if( event.type == SDL_KEYUP )
{
switch( event.key.keysym.sym )
{
case SDLK_LEFT: xVel += SQUARE_WIDTH /3; break;
case SDLK_RIGHT: xVel -= SQUARE_WIDTH /3; break;
if( Jumping )
{
if( yVel > -40 )
{
yVel = yVel - yAccel;
box.y = box.y + yVel;

if( box.y <= 460 )
{
yVel = 0;
yAccel = 0;
}
}
}
}
}
}

void Square::move()
{
//Move the dot left or right
box.x += xVel;

//Keep square in bounds
if( ( box.x < 0 ) || ( box.x + SQUARE_WIDTH > SCREEN_WIDTH ) || ( check_collision( box, box1 ) ) )
{
box.x -= xVel;
}
if( Jumping )
{
box.y -= yVel;

}
if( yVel > -40 )
{
yVel = yVel - yAccel;
}

if( check_collision( box, box1 ) == true )
{
yVel = 0;
yAccel = 0;
}

}

void Square::show()
{
apply_surface( box.x, box.y, square, screen );
}

Timer::Timer()
{
//Init variables
startTicks = 0;
pausedTicks = 0;
paused = false;
started = false;
}

void Timer::start()
{
//Start timer
started = true;

//Unpause
paused = false;

//Get current time
startTicks = SDL_GetTicks();
}

void Timer::stop()
{
//Pause timer
started = false;

//Unpause
paused = false;
}

void Timer::pause()
{
//if timer is stil running
if( ( started == true ) && ( paused == false ) )
{
//Pause
paused = true;

//Get paused ticks
pausedTicks = SDL_GetTicks() - startTicks;
}
}

void Timer::unpause()
{
//If timer is paused
if( paused == true )
{
//Unpause
paused = false;

//Reset ticks
startTicks = SDL_GetTicks() - pausedTicks;

//Reset paused ticks
pausedTicks = 0;
}
}

int Timer::get_ticks()
{
//if timer is running
if( started == true )
{
//If timer is paused
if( paused == true )
{
//Return number of ticks
return pausedTicks;
}
else
{
//Return current time
return SDL_GetTicks() - startTicks;
}
}

//If the timer isnt running
return 0;
}

bool Timer::is_started()
{
return started;
}

bool Timer::is_paused()
{
return paused;
}

int main( int argc, char* args[] )
{
//Quit flag
bool quit = false;

Square mySquare;

//frame rate
Timer fps;

//Set object coordinates
box1.x = 200;
box1.y = 380;
box1.w = OBJECT_WIDTH;
box1.h = OBJECT_HEIGHT;

if( init() == false )
{
return 1;
}
if( load_files() == false )
{
return 1;
}

//While user hasnt quit
while( quit == false )
{
//start timer
fps.start();

//Poll events
while( SDL_PollEvent( &event ) )
{
mySquare.handle_input();

//IF user has Xed out
if( event.type == SDL_QUIT )
{
quit = true;
}
}
//Move the square
mySquare.move();

//Fill the screen
SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );

//Show the square
mySquare.show();

apply_surface( box1.x, box1.y, object, screen );

//Update screen
if( SDL_Flip( screen ) == -1 )
{
return 1;
}

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

//Clean up
clean_up();

return 0;
}
Advertisement
When your square jumps, you need to compare the squares height with the grounds height at the squares current x, z location. If your squares current height is the same height or less than the grounds height at the position, just stop your jumping.

I just noticed you must be making a 2d game. Then all you need to do is check the y position at the squares current x position. If the y position of your square is less than or equal to the y position of the ground at the current x position of the square, set "jumping" to false.

If your testing for jumping on objects, test if your square for collision with the other object, if there was a collision, set jumping to false. Of course this will take a little more thinking because maybe you jump into the side of another object, then your square would just stop moving, so if that was the case your square should stop moving on the x axis, and just "fall" down on the y axis until it lands on the ground or another object.

Hope that's helpful in some way

When your square jumps, you need to compare the squares height with the grounds height at the squares current x, z location. If your squares current height is the same height or less than the grounds height at the position, just stop your jumping.

I just noticed you must be making a 2d game. Then all you need to do is check the y position at the squares current x position. If the y position of your square is less than or equal to the y position of the ground at the current x position of the square, set "jumping" to false.

If your testing for jumping on objects, test if your square for collision with the other object, if there was a collision, set jumping to false. Of course this will take a little more thinking because maybe you jump into the side of another object, then your square would just stop moving, so if that was the case your square should stop moving on the x axis, and just "fall" down on the y axis until it lands on the ground or another object.

Hope that's helpful in some way

I dont get it, Maybe i can understand if you post some code :)

EDIT::: I just got it working..
I just added this in the move function

if( box.y + SQUARE_WIDTH > SCREEN_WIDTH )
{
box.y = 460;
}

It was Simple!! :D

This topic is closed to new replies.

Advertisement