• Advertisement
Sign in to follow this  

Jumping in a 2d game

This topic is 4795 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey, ive been working on a 2d game for a while now. Ive already gone alot farther then I ever planned and have big plans for its future. I unfortunatly never took physics in school and dont understand at all how to add jumping into my game. What I have now is when I press the jump button (UP) I move 10 pixels up. Im going to add something that lets it load slower then an instant jump, possiable 1 at a time, spaces out by a timer im guessing. Anyways, I tried putting into the game loop to lower the character down by one but yet it wont go, I understand the concepts of jumping, I just dont know how to do it. Any advice? Also the jumn n run tutorials absoultly suck in my opinion. Well there just not for me, they are helpful for others.

Share this post


Link to post
Share on other sites
Advertisement
I haven't yet made a game where there has been jumping but I guess you should have a velocity variable. When jumping up increase up_velocity by some value (gravity). Then every frame add the velocity to the sprite's y co-ordinate and every frame decrease it a bit.. I guess that's how it could be done.

(Not sure though, since I haven't done this ever.)

Share this post


Link to post
Share on other sites
My understanding of jumping (though I also haven't implemented this yet, I've thought about it a fair amount) is as follows:

a) you can only jump when you're standing on something
b) variable-height jumps should be allowed
c) as a general rule, flight should not be allowed

So what I'm planning on for my response to the "jump" key being pressed looks like this:

If (I am standing on the ground) // Begin the jump
valid_jump = true;
velocity += JUMP_VELOCITY;
jump_duration = 0;

If (valid_jump AND jump_duration < MAX_JUMP_LENGTH)
velocity -= gravity; // Ignoring gravity allows variable-length jumps
jump_duration++;
Else
valid_jump = false;


Realize that this is entirely untested pseudocode. You'll have to figure out when the player is standing on the ground on your own, too. The line where I subtract gravity from the player's velocity assumes that the player regularly has gravity added to his velocity; hence, subtracting it here means that the player ignores gravity for as long as the jump button is pressed and MAX_JUMP_LENGTH is not exceeded. This allows the player to "float" upwards. Probably a better way to handle this would be, in the player's position update code (where gravity would be added), to check if the player's in a valid jump and the jump button is pressed, and to actually ignore gravity there.

Share this post


Link to post
Share on other sites
Ok, that works, but I have no clue how to add velocity for my player. Right now he just has his xpos and ypos. Also I dont know where to put gravity in, if my player jumps up, he stays up.

Share this post


Link to post
Share on other sites
Quote:
Original post by Thrust
Ok, that works, but I have no clue how to add velocity for my player. Right now he just has his xpos and ypos. Also I dont know where to put gravity in, if my player jumps up, he stays up.


Just add a new int variable to your player struct/class/what ever. And gravity can be a global constant.


struct Player {
int x_pos;
int y_pos;
int x_velocity;
int y_velocity;
};

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
ok but I dont know what velocity does, or how to calculate it or gravity.


Also now that I made a struct for the player, it doesent work. I get parse errors everywhere.


//struct Player
struct player{
int x_pos;
int y_pos;
int x_vel;
int y_vel;
};
int spriteh = 40;
int spritew = 29;

player.x_pos =32;
player.y_pos = 566;



small example...

Share this post


Link to post
Share on other sites

//struct Player
struct player{
int x_pos;
int y_pos;
int x_vel;
int y_vel;
};
int spriteh = 40;
int spritew = 29;

player.x_pos =32;
player.y_pos = 566;

what you mean is [smile] :

typedef struct player {
int x_pos;
int y_pos;
int x_vel;
int y_vel;
} Player;

Player.x_pos = 32;
//blah blah blah

Share this post


Link to post
Share on other sites
Quote:
Original post by Alpha_ProgDes

typedef struct player {
int x_pos;
int y_pos;
int x_vel;
int y_vel;
} Player;

Player pl;
pl.x_pos = 32;



Anyway, the OP should learn programming first.. Or what ever language he's using.

Share this post


Link to post
Share on other sites

#include <iostream>
#include <stdlib.h>
#include <winsock2.h>
#include <SDL/SDL.h>


//Globals
int map [20][25]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//Functions
void drawMap();
void drawScene();
//draws bitmaps, x = o is top, y = 0 is left, sprite is the image
void draw(int x, int y, SDL_Surface *sprite, SDL_Surface *screen);

//Surfaces
SDL_Surface *tilemap;
//Sprite
SDL_Surface *sprite1 = SDL_LoadBMP("gfx/sprites/sprite1.bmp");
SDL_Surface *cloud = SDL_LoadBMP("gfx/tiles/cloud.bmp");
SDL_Surface *sun = SDL_LoadBMP("gfx/tiles/sun.bmp");
//Tiles
SDL_Surface *tile1 = SDL_LoadBMP("gfx/tiles/tile1.bmp");
SDL_Surface *tile2 = SDL_LoadBMP("gfx/tiles/tile2.bmp");

//struct Player
typedef struct player
{
int x_pos;
int y_pos;
int x_vel;
int y_vel;
}player;

int spriteh = 40;
int spritew = 29;
player.x_pos = 32;
player.y_pos = 566;
//------------------------------------------------------------------------------

using namespace std;

int main(int argc, char *argv[])
{
Uint8* keys;

//Sets transparency
SDL_SetColorKey(sprite1, SDL_SRCCOLORKEY,
SDL_MapRGB(sprite1->format, 255, 100, 255));
SDL_SetColorKey(cloud, SDL_SRCCOLORKEY,
SDL_MapRGB(cloud->format, 255, 100, 255));
SDL_SetColorKey(sun, SDL_SRCCOLORKEY,
SDL_MapRGB(sun->format, 255, 100, 255));

//boolean used to determine if the game is running
bool isRunning;
//A SDL event, used to keep gamerunning.
SDL_Event event;

//unload function
atexit(SDL_Quit);

//sets the video mode that SDL uses
// Peremiters are window width, window height,color depth, then flags
tilemap = SDL_SetVideoMode(800, 640, 0, SDL_HWSURFACE|SDL_DOUBLEBUF);

//gives the boolean a value
isRunning = true;
drawMap();


//Main game loop
while(isRunning == true)
{
//Poll event
SDL_PollEvent(&event);

//vent that ends SDL and main game loop
if(event.type == SDL_KEYDOWN)
{
if(event.key.keysym.sym == SDLK_ESCAPE)
isRunning = false;
}
keys = SDL_GetKeyState(NULL);
if ( keys[SDLK_UP] )
{
if (map[((player.y_pos-2)/32)][(player.x_pos/32)] == 1 && map[((player.y_pos-2)/32)][((player.x_pos+spritew)/32)] == 1)
{
player.y_pos-=2;
}
}
if ( keys[SDLK_DOWN] )
{
if (map[(((player.y_pos+2)+spriteh)/32)][(player.x_pos/32)] == 1 && map[(((player.y_pos+2)+40)/32)][((player.x_pos+spritew)/32)] == 1 )
{
player.y_pos+=2;
}
}
if ( keys[SDLK_LEFT] )
{
if (map[(player.y_pos/32)][(((player.x_pos-2))/32)] == 1 && map[((player.y_pos+spriteh)/32)][(((player.x_pos-2))/32)] == 1 && map[((player.y_pos+(spriteh/2))/32)][(((player.x_pos-2))/32)] == 1)
{
player.x_pos-=2;
}
}
if ( keys[SDLK_RIGHT] )
{
if (map[(player.y_pos/32)][(((player.x_pos+2))/32)] == 1 && map[((player.y_pos+spriteh)/32)][(((player.x_pos+2)+spritew)/32)] == 1 && map[((player.y_pos+(spriteh/2))/32)][(((player.x_pos+2)+spritew)/32)] == 1)
{
player.x_pos+=2;
}
}
drawScene();
}


cout << "Testing a tile map..." <<endl;
cout << "Lets hope this works." << endl;
cout << "Geebers, it did (Knew that was going to happen)"<<endl;
cout << "Now for colision..." << endl;
cout << "Haha I actuially did it, woohoo!" << endl;

if (event.type == SDL_QUIT)
{
SDL_FreeSurface(tile1);
SDL_FreeSurface(tile2);
SDL_FreeSurface(sprite1);
SDL_FreeSurface(cloud);
SDL_FreeSurface(sun);
isRunning = false;
}

return 0;
}



//------------------------------------------------------------------------------------

//Draws stuff to the screen
void draw(int x, int y, SDL_Surface *sprite, SDL_Surface *screen)
{
SDL_Rect source;
SDL_Rect dest;

source.x = 0;
source.y = 0;
source.w = sprite->w;
source.h = sprite->h;

dest.x = x;
dest.y = y;
dest.w = source.w;
dest.h = source.h;

SDL_BlitSurface(sprite, &source, screen, &dest);

return;
}



//DRAWS MAP!!!

void drawMap()
{

int map [20][25]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

for(int y = 0;y < 20; y++)
{
for(int x = 0;x < 25; x++)
{
if(map[y][x] == 1)
{
draw(x*32,y*32,tile1,tilemap);
}
else if (map[y][x] == 0)
{
draw(x*32,y*32,tile2,tilemap);
}
}
}
}


//draws background
void drawScene()
{
drawMap();
draw(40,40,cloud,tilemap);
draw(330,60,cloud,tilemap);
draw(670,40,sun,tilemap);
draw(40,40,cloud,tilemap);
draw(player.x_pos, player.y_pos, sprite1, tilemap);

SDL_Flip(tilemap);
}





Still doesent work. This is so frustrating. I think I might just go back to my other way and get rid of the struct part of it. But I still have no idea about how to make my character sucked towards the ground, jump, etc...

Share this post


Link to post
Share on other sites
Quote:
Original post by tentoid
Quote:
Original post by Alpha_ProgDes

typedef struct player {
int x_pos;
int y_pos;
int x_vel;
int y_vel;
} Player;

Player pl;
pl.x_pos = 32;



Anyway, the OP should learn programming first.. Or what ever language he's using.


good correction... oops [grin]

well, you burn, you learn [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by Thrust
*** Source Snippet Removed ***


Still doesent work. This is so frustrating. I think I might just go back to my other way and get rid of the struct part of it. But I still have no idea about how to make my character sucked towards the ground, jump, etc...


Well you need to make an instance of that struct (a variable). First you define what the struct contains and the name of the struct. Then you can create a new variable of that type.

Once again:

// you may need to do some typedef stuff here if you use C and not C++
struct player {
//blaa
}

player my_player;
my_player.x = 5;


Also it would be a good idea to have a function to update the state of the player (and enemies etc.). See Derakon's pseudo code example how to implement jumping..

Share this post


Link to post
Share on other sites
Ok the struct works now, I just dont know how to use velocity or gravity.

Share this post


Link to post
Share on other sites
You don't have to have a gravity variable or any type of physics.
simply make to functions, one that starts the jump, the other handles the jump.

here is two functions as an example.

The start function:



void Jump(void)
{

Player.jump = true;
Player.yspeed = 10;

}





and the handle function



void HandleJump(void)
{

Player.y -= Player.yspeed;
Player.yspeed--;

if(/* collision on feet */)
Player.jump = false;

}






Then, you call the jump start button when the jump key is pressed and you only call the handle jump function when the player is jumping.

gravity is not necessary because the yspeed will decrease until it is negative, therefore the player will go up, then fall till he lands.

Share this post


Link to post
Share on other sites
His code would make complete sense, if I knew how to use velocity and gravity. I dont understand those two, if I did jumping would be alot easier.

Share this post


Link to post
Share on other sites
Quote:

Ok the struct works now, I just dont know how to use velocity or gravity.


Velocity is the speed and direction of an object: The change in it's position over time. To update an objects position based on velocity, every time segment do posx+=velx and posy+=vely, but also remember to do collision detection. You can think of gravity as a velocity vector too, where velx=0 and vely is variable because gravity causes acceleration. Look up the formula for acceleration due to gravity and use that to compute a velocity vector for gravity at every time segment and add that to any other velocity vectors that are in place on your character, provided your character is not on the ground.

Share this post


Link to post
Share on other sites
basic physics lesson [smile]

ok position is affected by velocity and velocity is affected by acceleration.

so your player has position x which is (for now) 0.
he has a jumping velocity of 5 meters per second (5 m/s)
and gravity is 9.8 meter per second squared (9.8 m/s^2)
but you knew all that [smile]

so the code is, for moving:

struct player {

int y_pos;
int y_vel;
};

Player pl;
pl.y_pos = 0;
pl.y_vel = -5 // because the y-coordinates on the screen are positive (increasing) going down the screen.

if (key_up)
y_pos = y_pos + y_vel;

i'll stop there, in case you have questions

Share this post


Link to post
Share on other sites
Quote:
Original post by Thrust
His code would make complete sense, if I knew how to use velocity and gravity. I dont understand those two, if I did jumping would be alot easier.


I don't think you're ready for this yet.. You need to know the most basic physics (forces), which includes gravity, acceleration etc. When you know that, you will also know exactly what to do in this case. It's quite simple if you understand how forces work.

Share this post


Link to post
Share on other sites
Quote:
Original post by Thrust
His code would make complete sense, if I knew how to use velocity and gravity. I
don’t understand those two, if I did jumping would be a lot easier.


I see you say this over and over but the fact is you don't really need to understand velocity or gravity all that well for 2D. Let me see if I can break it down using Stompys code as an example.

First, your character should now contain an x_velocity and a y_velocity. This will control the speed that they move at on either the X(left and right) axis or the Y(up and down) axis.

If you add negative velocity to the X position of the character they will appear to move left on the screen. Likewise, add positive velocity to the X axis and your character will appear to move to the right. This also carries over to the Y axis, positive velocity moving down the screen, negative velocity moving up the screen.

Now here is where I am guessing you are running into trouble. You don't quite know what to set the velocity to initially. Depending on how you do it, it really doesn't matter. Just play around with some values for now. When it comes time for you to calculate anything relating to real physics of velocity you will have a lot of this groundwork already done.

So back to the point. Disregard gravity entirely. The concept is a little bit over kill for a basic 2D game that it seems like you are describing. We will be applying the "fake" gravity that Stompy described.


void Jump(void)
{

Player.jump = true;
Player.yspeed = 10;

}


This is good but I would make one alteration just so we don’t get unexpected behavior.


void Jump(void)
{
if(Player.jump == true)
return;

Player.jump = true;
Player.yspeed = 10;

}


Now there are no infinite jump chains. :)

Now looking at this jump we can see a couple things. The player enters a state of jumping if he is not already in one. His yspeed here is also assigned a value of 10 to start with.

Let’s say our character is standing at the bottom of the screen. For simplicity lets say our resolution is 640x480 and our character is standing on line 300.

With that established, lets look at the effect of the jumping state of the character when he goes through his update loop.


void HandleJump(void)
{
Player.y -= Player.yspeed;
Player.yspeed--;

if(/* collision on feet */)
Player.jump = false;
}


Our character is jumping as evidenced by Player.Jump, so we know to run the HandleJump function. Otherwise he would just sit there and do nothing.

So when we enter the HandleJump we immediately subtract the speed of the jump (Player.yspeed) from the Players position on the screen. This makes him move upward slightly.

This is where we finally simulate gravity. We subtract one from the yspeed here. So the next time around, the jump won’t carry the character as high. And after that even lower, until the Player.yspeed is a negative number being subtracted from our Player.y. And you don’t need to be a Astrophysics major to know that subtracting a negative number from a positive number makes the positive number bigger.

This will all continue until we detect our character back at ground level. Once he’s back on the ground we set Player.Jump to false and Player.yspeed to zero and our jump is done.

Hope this all made sense.

Share this post


Link to post
Share on other sites
I have no questions so far. Please continue with the lesson. Thanks for the help...

Share this post


Link to post
Share on other sites

All you have to do us subtract a value or values from your y coord a number of times then add the same number to your y coord, once you've got the height you desire till he's back at the value he started.


If you really want to avoid physics just use a look up table with number of minus values (the thrust up) to add to your y, and then an equal number of positive values to add to the y (the effect of gravity).

ie
int table[] = {-3,-2,-1,0,0,1,2,3}; // an array of 8 elements
int index = 0

if (doingJump){

yCoord += table[index];

//breaking it down for simplicity,

index++;
if (index >=8) doingJump = false;
}


Use an index to access the relevent table offset, that you then increment each frame......(very) basic but effective, though your jump will always look the same. Make sure you reset index when you set doingJump, and don't trigger a jump if doing one already.

Can't think of a simpler way to do it till you learn a buit more about the action of fources like gravity on objects.




Share this post


Link to post
Share on other sites
Hi,

Physics is just a little math. Small physics class:

a. Objects are located in space so they have a position x,y.

b. Objects have a movement speed. The speed is a measure of how many units the object moves in a given time. So if a car is moving at 30km/h then the car moves 30km in one hour. If you consider that a kilometer is 1000 meters then athe car is moving at 30000m/h. Also if you consider an hour has 3600 seconds then you can say the car is moving at 8.33m/s. Now, in your game a meter may be represented by 10 pixels (or 5 or 100, you choose the scale). Then you may say your car moves 83.3 pixels/sec.

c. Basically that example means that you can define speed as:
speed = distance_moved / time_used_to_move_that_distance

or, with a simple multiplication:
distance_moved = speed * time_used_to_move_that_distance

or simply put:
v = d / t or
d = v * t

So this little formula will help you getting the third value if you have two of the parameters. This is the basic for physics.

Still with me?

c. Example: Your game takes about N milliseconds for each frame. So you can use the formula and know that in the previous example, your car moved at 83.3pixels/sec. N msecs means that each frame takes N/1000 seconds. So you know that you car moves:
d = v * t
d = 83.3pix/sec * N/1000 seconds
d = 83.3 * N / 1000 pixels.

Where N is the milliseconds from frame to frame. N may vary in each computer, its not a fixed value. It should be computed each frame.

Ok, now i need to know if you got it. Try to program this concept in your game. Then write another post and I'll try to help you with acceleration.

Luck!
Guimo


Share this post


Link to post
Share on other sites

//jumps
void Jump(void)
{

p1.jump = true;
p1.y_vel = 96;
}

void HandleJump(void)
{
Player.y -= Player.yspeed;
Player.yspeed--;

if(map[(((p1.y_pos+2)+spriteh)/32)][(p1.x_pos/32)] == 1 && map[(((p1.y_pos+2)+40)/32)][((p1.x_pos+spritew)/32))
Player.jump = false;
}





if ( keys[SDLK_UP] )
{
Jump();
}




Now where would I implement HandleJump?

Share this post


Link to post
Share on other sites
You know what, on second thought, maybe you aren't quite ready for this...

I would recommend going back and working on structure of programming before getting into all this.

[Edited by - JustHeath on January 6, 2005 4:21:50 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement