Jumping routine with physics - need a little help

I’m having trouble applying some physics to my little Mario style game
I’m trying to write with SDL and VC6.

I’ve been working at this for weeks now. I got the falling works good
and the left/right movement works well too, but I just can’t for the
life of me get the jumping working right:

int RunGame() { Uint8 *keys;

unsigned int
ticks = SDL_GetTicks(),
ticks_last = ticks,
tick_delta, // Time per Frame.
frame_rate; // Frames per Second.

[…]

// Main Loop.
int done = 0;
while (!done) {
SDL_Event event;
ticks = SDL_GetTicks();
tick_delta = ticks - ticks_last;

[…]

  keys = SDL_GetKeyState(NULL);
  int moveX = 0, moveY = 0;

  // Want to Jump? If you're standing on someting solid, go ahead.
  if (!jumping && keys[SDLK_SPACE] && !CanMove(guy, foreground,

dDown, 16711935)) {
velY = max_jump_vel * true_accel;
jumping = true;
}

  // Jump.
  if (jumping) {
     velY -= true_accel;

[Note: CanMove(…) is a function I wrote for collision detection; ]
[ so the player doesn’t go through any barriers. ]

     if (velY >= 0)     // Going Up.
        moveY = CanMove(guy, foreground, dUp, 16711935, velY);
     else jumping = false;
     //else if (velY < 0) // Finished going Up, now Down.
        //moveY = CanMove(guy, foreground, dDown, 16711935, velY);
  }

  // Stop Jumping, since you've hit a floor.
  if (!CanMove(guy, foreground, dDown, 16711935)) {
     velY = 0;
     jumping = false;
  }
  // Cieling check.
  if (!CanMove(guy, foreground, dUp, 16711935)) {
     velY = 0;
     jumping = false;
  }

  // Gravity.
  if (!jumping && CanMove(guy, foreground, dDown, 16711935)) {
     // You're in the air, so fall.
     velY += true_accel;
     moveY = CanMove(guy, foreground, dDown, 16711935, velY);
  }

  // Left / Right Movement.
  if (keys[SDLK_LEFT]) {
     velX -= true_accel;
     if (velX < -walk_max_vel) velX = -walk_max_vel;
     moveX = velX > 0 ?
        CanMove(guy, foreground, dRight, 16711935, velX) :
        CanMove(guy, foreground, dLeft, 16711935, velX);
     if (!moveX) velX = 0;
  }
  if (keys[SDLK_RIGHT]) {
     velX += true_accel;
     if (velX > walk_max_vel) velX = walk_max_vel;
     moveX = velX < 0 ?
        CanMove(guy, foreground, dLeft, 16711935, velX) :
        CanMove(guy, foreground, dRight, 16711935, velX);
     if (!moveX) velX = 0;
  }

  // Standing. Stopped.
  if (!keys[SDLK_LEFT] && !keys[SDLK_RIGHT]) {
     // Slow down if theres some leftover velocity.
     if (velX < 0) {
        velX += true_accel;
        moveX = CanMove(guy, foreground, dLeft, 16711935, velX);
     }
     else if (velX > 0) {
        velX -= true_accel;
        moveX = CanMove(guy, foreground, dRight, 16711935, velX);
     }
  }

  // Apply Movement & Draw Character.
  guyX += moveX;
  guyY += moveY;

  DrawIMG(guy, guyX, guyY);
  SDL_Flip(screen);

[…]

}

}

Thanks for any help and suggestions, and any suggestions to improve any
part of this code are very welcome too. this is the FIRST time I’ve ever
attempted to code this kidna game. I come from a application programming
background, on both win32 and linux, c/c++/Perl/Java. Game programming
is realitively new to me.–
Blaza

Blaza wrote:

I’m having trouble applying some physics to my little Mario style game
I’m trying to write with SDL and VC6.

I’ve been working at this for weeks now. I got the falling works good
and the left/right movement works well too, but I just can’t for the
life of me get the jumping working right:

int RunGame() { Uint8 *keys;

unsigned int
ticks = SDL_GetTicks(),
ticks_last = ticks,
tick_delta, // Time per Frame.
frame_rate; // Frames per Second.

[…]

// Main Loop.
int done = 0;
while (!done) {
SDL_Event event;
ticks = SDL_GetTicks();
tick_delta = ticks - ticks_last;

OOPs, this piece of code should be here:
int true_accel = accel * tick_delta/10;> […]

  keys = SDL_GetKeyState(NULL);
  int moveX = 0, moveY = 0;

  // Want to Jump? If you're standing on someting solid, go ahead.
  if (!jumping && keys[SDLK_SPACE] && !CanMove(guy, foreground,

dDown, 16711935)) {
velY = max_jump_vel * true_accel;
jumping = true;
}

  // Jump.
  if (jumping) {
     velY -= true_accel;

[Note: CanMove(…) is a function I wrote for collision detection; ]
[ so the player doesn’t go through any barriers. ]

     if (velY >= 0)     // Going Up.
        moveY = CanMove(guy, foreground, dUp, 16711935, velY);
     else jumping = false;
     //else if (velY < 0) // Finished going Up, now Down.
        //moveY = CanMove(guy, foreground, dDown, 16711935, velY);
  }

  // Stop Jumping, since you've hit a floor.
  if (!CanMove(guy, foreground, dDown, 16711935)) {
     velY = 0;
     jumping = false;
  }
  // Cieling check.
  if (!CanMove(guy, foreground, dUp, 16711935)) {
     velY = 0;
     jumping = false;
  }

  // Gravity.
  if (!jumping && CanMove(guy, foreground, dDown, 16711935)) {
     // You're in the air, so fall.
     velY += true_accel;
     moveY = CanMove(guy, foreground, dDown, 16711935, velY);
  }

  // Left / Right Movement.
  if (keys[SDLK_LEFT]) {
     velX -= true_accel;
     if (velX < -walk_max_vel) velX = -walk_max_vel;
     moveX = velX > 0 ?
        CanMove(guy, foreground, dRight, 16711935, velX) :
        CanMove(guy, foreground, dLeft, 16711935, velX);
     if (!moveX) velX = 0;
  }
  if (keys[SDLK_RIGHT]) {
     velX += true_accel;
     if (velX > walk_max_vel) velX = walk_max_vel;
     moveX = velX < 0 ?
        CanMove(guy, foreground, dLeft, 16711935, velX) :
        CanMove(guy, foreground, dRight, 16711935, velX);
     if (!moveX) velX = 0;
  }

  // Standing. Stopped.
  if (!keys[SDLK_LEFT] && !keys[SDLK_RIGHT]) {
     // Slow down if theres some leftover velocity.
     if (velX < 0) {
        velX += true_accel;
        moveX = CanMove(guy, foreground, dLeft, 16711935, velX);
     }
     else if (velX > 0) {
        velX -= true_accel;
        moveX = CanMove(guy, foreground, dRight, 16711935, velX);
     }
  }

  // Apply Movement & Draw Character.
  guyX += moveX;
  guyY += moveY;

  DrawIMG(guy, guyX, guyY);
  SDL_Flip(screen);

[…]

}

}

Thanks for any help and suggestions, and any suggestions to improve
any part of this code are very welcome too. this is the FIRST time
I’ve ever attempted to code this kidna game. I come from a
application programming background, on both win32 and linux,
c/c++/Perl/Java. Game programming is realitively new to me.


Blaza

Hi,

I’m having trouble applying some physics to my little Mario style game
I’m trying to write with SDL and VC6.

I’ve been working at this for weeks now. I got the falling works good
and the left/right movement works well too, but I just can’t for the
life of me get the jumping working right:

You haven’t said what the problem is. I think I found something, but I
can’t be sure about it. If your character makes just a small hop and
immediately drops down again, I may have found your problem:

 // Want to Jump? If you're standing on someting solid, go ahead.
 if (!jumping && keys[SDLK_SPACE] && !CanMove(guy, foreground,

dDown, 16711935)) {
velY = max_jump_vel * true_accel;
jumping = true;
}

You start jumping here, ok. This, of course, means that the CanMove(guy,
foreground, dDown, 16711935) check returns false.

 // Jump.
 if (jumping) {
    velY -= true_accel;
    if (velY >= 0)     // Going Up.

(*) moveY = CanMove(guy, foreground, dUp, 16711935, velY);
else jumping = false;
//else if (velY < 0) // Finished going Up, now Down.
//moveY = CanMove(guy, foreground, dDown, 16711935, velY);
}

This starts jumping, right? The moveY in (*) is the amount the character
should move upwards, as I take it. This seems to involve a ceiling
check, with CanMove again. Let’s assume this passes, and moveY is still up.

 // Stop Jumping, since you've hit a floor.
 if (!CanMove(guy, foreground, dDown, 16711935)) {
    velY = 0;
    jumping = false;
 }

Ah. Recall that, to start jumping, you had to be on the floor, which
means CanMove(guy, foreground, dDown, 16711935) is still false, since
the guy has not actually moved yet. At least, that’s how I understand
CanMove…

So now we have velY = 0, jumping = false, and moveY still not 0.

 // Gravity.
 if (!jumping && CanMove(guy, foreground, dDown, 16711935)) {
    // You're in the air, so fall.
    velY += true_accel;
    moveY = CanMove(guy, foreground, dDown, 16711935, velY);
 }

Despite the fact that we’re not jumping, the above code is not executed,
since we have not left the ground yet, causing the CanMove(dDown) to
fail. velY and moveY remain unchanged.

 // Apply Movement & Draw Character.
 guyX += moveX;
 guyY += moveY;

This finally moves the guy. Though jumping = false and velY = 0, moveY
has not changed and still propels the guy upwards… for this frame.
It’s free falling from the next frame onward for him!

Thanks for any help and suggestions, and any suggestions to improve
any part of this code are very welcome too.

My suggestion: Use “else if” or similar to structure your code into
several disjunct cases. Once you have determined that the player is
starting a jump, there’s no need to check for free falling gravity,
hitting the floor again etc.

It can be a bit tricky to find out how many states the guy can be in
(not jumping but standing, starting to jump, in mid-jump, in mid-fall,
landing etc.), but I’m sure you’ll do ok.

Good luck!

Ben

Benjamin Deutsch wrote:

Hi,

I’m having trouble applying some physics to my little Mario style
game I’m trying to write with SDL and VC6.

I’ve been working at this for weeks now. I got the falling works
good and the left/right movement works well too, but I just can’t
for the life of me get the jumping working right:

You haven’t said what the problem is. I think I found something, but I
can’t be sure about it. If your character makes just a small hop and
immediately drops down again, I may have found your problem:

My apologies. My problem is I’m trying to make a smooth jump, instead
the guy just makes a quick jump, almost instantly, upward, thne falls
ok. I’ve been trying to tweak it and as is yeah short little hops. On my
system its so fast if space is held it looks like the guy is using a
jack hammer lol.

 // Want to Jump? If you're standing on someting solid, go
 ahead. if (!jumping && keys[SDLK_SPACE] && !CanMove(guy,

foreground,
dDown, 16711935)) {
velY = max_jump_vel * true_accel;
jumping = true;
}

You start jumping here, ok. This, of course, means that the
CanMove(guy, foreground, dDown, 16711935) check returns false.

Yeah, I’m making sure the guy cannot move down, making sure I’m on the
ground or on some sort of a platform.

CanMove(…) :

CanMove opitionally takes the amount you want to move as the last param,
else it uses a default step I’ve set to 8. 16711935 is the transparant
color, magenta - empty space = transparent space. The function returns
the actual amount the guy can move without running something, in the
given direction. Say you want to move left 20 pixels, theres a wall or
the edge of the screen 12 pixels to the left of the guy, the function
will return 12. That way the guy can smack into a wall and not go
through it!

 // Jump.
 if (jumping) {
    velY -= true_accel;
    if (velY >= 0)     // Going Up.

(*) moveY = CanMove(guy, foreground, dUp, 16711935, velY);
else jumping = false;
//else if (velY < 0) // Finished going Up, now Down.
//moveY = CanMove(guy, foreground, dDown, 16711935,
velY); }

This starts jumping, right? The moveY in (*) is the amount the
character should move upwards, as I take it. This seems to involve a
ceiling check, with CanMove again. Let’s assume this passes, and moveY
is still up.

Yeah, moveY and moveX, which default 0 to each iteration, are the amount
to adjust the x and y positions, repsectively, by (offset.)

And yes, (*) makes sure moveY is zero if the guy smacks his head into a
cieling.

 // Stop Jumping, since you've hit a floor.
 if (!CanMove(guy, foreground, dDown, 16711935)) {
    velY = 0;
    jumping = false;
 }

Ah. Recall that, to start jumping, you had to be on the floor, which
means CanMove(guy, foreground, dDown, 16711935) is still false, since
the guy has not actually moved yet. At least, that’s how I understand
CanMove…

So now we have velY = 0, jumping = false, and moveY still not 0.

You seem to have udnerstood CanMove pretty much right. That if statement
is suppost to stop a guy if he lands on something when falling. Noqw
that I think about it, ‘jumping = false’ line sems pretty useles scince
the guy is falling already.

I’ve rewritten that peice of code as:

  // Stop Falling, since you've hit a floor.
  if (!CanMove(guy, foreground, dDown, 16711935)) velY = 0;
 // Gravity.
 if (!jumping && CanMove(guy, foreground, dDown, 16711935)) {
    // You're in the air, so fall.
    velY += true_accel;
    moveY = CanMove(guy, foreground, dDown, 16711935, velY);
 }

Despite the fact that we’re not jumping, the above code is not
executed, since we have not left the ground yet, causing the
CanMove(dDown) to fail. velY and moveY remain unchanged.

What this if statement checks is that the guy is not i nthe process of
jumping (not moving upward), and making sure the guy isn’t already on
the ground. Seems to have bee working.

Just to clarify, this bit is meant to handle gravity / falling in
general.

 // Apply Movement & Draw Character.
 guyX += moveX;
 guyY += moveY;

This finally moves the guy. Though jumping = false and velY = 0, moveY
has not changed and still propels the guy upwards… for this frame.
It’s free falling from the next frame onward for him!

if moveY or moveX are not changed, they are 0. Near the beginning of the
loop is this line, as noted in my code I posted originally:

  int moveX = 0, moveY = 0;

The guy doesn’t move unless something tells him to :slight_smile:

Thanks for any help and suggestions, and any suggestions to improve
any part of this code are very welcome too.

My suggestion: Use “else if” or similar to structure your code into
several disjunct cases. Once you have determined that the player is
starting a jump, there’s no need to check for free falling gravity,
hitting the floor again etc.

It can be a bit tricky to find out how many states the guy can be in
(not jumping but standing, starting to jump, in mid-jump, in mid-fall,
landing etc.), but I’m sure you’ll do ok.

Good luck!

Thank you for the suggestions. Appeciate the time you took to respond.–
Blaza

Hello again,

My problem is I’m trying to make a smooth jump, instead
the guy just makes a quick jump, almost instantly, upward, thne falls
ok. I’ve been trying to tweak it and as is yeah short little hops. On my
system its so fast if space is held it looks like the guy is using a
jack hammer lol.

Yes, and in your changed code, this should still be the case. Perhaps I
wasn’t clear last time what the problem was. If you have found and fixed
this, then my apologies.

Ok. Let’s start again when the guy is standing, there is no ceiling
overhead, and the player presses the jump key. Going through your code
from the original post, after the “// Want to Jump?” block we now have:

  • jumping is true
  • velY is, say +20 pixels per frame (the real value is not important)
  • moveY is 0, as initialized.

The next block “// Jump.” decreases the velocity, say to +19 pixels per
frame, then checks if this is still positive (which it is). moveY is set
accordingly, say to -19 pixels. The guy, at this point, has not moved
yet, unless CanMove does something to the guy’s position. I’m guessing
it doesn’t.

Your next block was originally:

// Stop Jumping, since you've hit a floor.
if (!CanMove(guy, foreground, dDown, 16711935)) {
   velY = 0;
   jumping = false;
}

and is now

I’ve rewritten that peice of code as:

  // Stop Falling, since you've hit a floor.
  if (!CanMove(guy, foreground, dDown, 16711935)) velY = 0;

Not clearing the jumping flag has probably not made much of a
difference. The point is that the guy has not moved yet. So he’s still
standing on solid ground. velY is +19, meaning he’s on his way up, and
moveY is -19, meaning he’ll move upwards at the end of the frame, but
now, he’s still standing.

So !CanMove(guy, foreground, dDown, 16711935) is true, and velY is set
to 0. moveY is still -19, so the guy can get 19 pixels off the floor in
this frame, but your overall, global guy speed, namely velY, is now 0.
So in the next frame, the “// Jump.” block sets jumping=false. Your guy
begins falling at the next frame, no matter what max velocity you set.

Your problem? You used two state transitions in a single frame. This is
not always problematic, but in your case, they conflict. You probably
should call the ceiling check in the same frame as the start of the
jump, but not the floor check.

The solution? In the rewritten piece, change the condition to
if (!jumping && !CanMove(guy, foreground, dDown, 16711935)) .
In the ceiling check, use
if (jumping && !CanMove(guy, foreground, dUp, 16711935)) .
The latter is probably not necessary in this case, but it’s still cleaner.

Oh, and you may want to change the guy’s velocity (now in the "// Jump."
block) after the guy has moved, so you’ll get the full max_velocity in
the first frame of jumping.

Hope this helps,

Ben

Benjamin Deutsch wrote:

Hello again,

My problem is I’m trying to make a smooth jump, instead
the guy just makes a quick jump, almost instantly, upward, thne falls
ok. I’ve been trying to tweak it and as is yeah short little hops.
On my system its so fast if space is held it looks like the guy is
using a jack hammer lol.

Yes, and in your changed code, this should still be the case. Perhaps
I wasn’t clear last time what the problem was. If you have found and
fixed this, then my apologies.

Thank you.

Ok. Let’s start again when the guy is standing, there is no ceiling
overhead, and the player presses the jump key. Going through your code
from the original post, after the “// Want to Jump?” block we now
have:

  • jumping is true
  • velY is, say +20 pixels per frame (the real value is not important)
  • moveY is 0, as initialized.

The next block “// Jump.” decreases the velocity, say to +19 pixels
per frame, then checks if this is still positive (which it is). moveY
is set accordingly, say to -19 pixels. The guy, at this point, has
not moved yet, unless CanMove does something to the guy’s position.
I’m guessing it doesn’t.

Nope, it just checks how far the guy can move out of the desired amount
of movement.

Your next block was originally:

// Stop Jumping, since you've hit a floor.
if (!CanMove(guy, foreground, dDown, 16711935)) {
   velY = 0;
   jumping = false;
}

and is now

I’ve rewritten that peice of code as:

  // Stop Falling, since you've hit a floor.
  if (!CanMove(guy, foreground, dDown, 16711935)) velY = 0;

Not clearing the jumping flag has probably not made much of a
difference. The point is that the guy has not moved yet. So he’s
still standing on solid ground. velY is +19, meaning he’s on his way
up, and moveY is -19, meaning he’ll move upwards at the end of the
frame, but now, he’s still standing.

So !CanMove(guy, foreground, dDown, 16711935) is true, and velY is set
to 0. moveY is still -19, so the guy can get 19 pixels off the floor
in this frame, but your overall, global guy speed, namely velY, is
now 0.
So in the next frame, the “// Jump.” block sets jumping=false. Your
guy begins falling at the next frame, no matter what max velocity you
set.

Your problem? You used two state transitions in a single frame. This
is not always problematic, but in your case, they conflict. You
probably should call the ceiling check in the same frame as the
start of the jump, but not the floor check.

The solution? In the rewritten piece, change the condition to
if (!jumping && !CanMove(guy, foreground, dDown, 16711935)) .
In the ceiling check, use
if (jumping && !CanMove(guy, foreground, dUp, 16711935)) .
The latter is probably not necessary in this case, but it’s still
cleaner.

I did the changes you mentioned and now the jumping looks pretty good.
Thank you very much!

Now if I may ask of one mor thing, while the jumping is smooth now, I
notice that occasionally when I start jumping it’ll spike a little
higher then resume going a constant hieght. I think this has to do with
the timing I’m trying to impliment (the ‘int true_accel = accel *
tick_delta/10;’ line). I devided by 10, when I oriiginally thought to
use 1000 but that gave me decimal value and ends up being interpreded as
0. And I thought it best to avoid something like ‘while (ticks <
ticks_last + interval) ticks = SDL_GetTicks();’ which would limit the
fame to that much time. Is there any way to remedy this?

Oh, and you may want to change the guy’s velocity (now in the “//
Jump.” block) after the guy has moved, so you’ll get the full
max_velocity in the first frame of jumping.

I’m not sure what you mean here? This doesn’t make sense to me. How can
the guy move before the velocity is set? Perhaps I’m not understanding
what you meant.

Hope this helps,

Ben

Thank you lots.–
Blaza

[…]

Now if I may ask of one mor thing, while the jumping is smooth now,
I notice that occasionally when I start jumping it’ll spike a
little higher then resume going a constant hieght. I think this has
to do with the timing I’m trying to impliment (the ‘int true_accel
= accel * tick_delta/10;’ line). I devided by 10, when I
oriiginally thought to use 1000 but that gave me decimal value and
ends up being interpreded as 0. And I thought it best to avoid
something like ‘while (ticks < ticks_last + interval) ticks =
SDL_GetTicks();’ which would limit the fame to that much time. Is
there any way to remedy this?

The joy of variable logic frame rates. :wink:

Why not just use float for coordinates, velocities, accelerations etc?
Integers/fixed point becomes a major PITA as soon as you need to do
anything but the most trivial calculation, and/or when you need both
accuracy and dynamic range.

Or, to aovid this problem, while getting 100% accurate (or rather 100%
repeatable) game logic, you could try fixed logic frame rate with
interpolation, as demonstrated in Fixed Rate Pig (or pig, for short):

http://olofson.net/examples.html

The PIG_ipoint struct and functions pig_animate() and draw_sprites()
would be the most interesting parts, I think. Those implement the
logic/graphic coordinate interface and the fixed “virtual” logic
frame rate.

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Saturday 15 May 2004 16.53, Blaza wrote:

Hi again,

Now if I may ask of one mor thing, while the jumping is smooth now, I
notice that occasionally when I start jumping it’ll spike a little
higher then resume going a constant hieght. I think this has to do with
the timing I’m trying to impliment (the ‘int true_accel = accel *
tick_delta/10;’ line). I devided by 10, when I oriiginally thought to
use 1000 but that gave me decimal value and ends up being interpreded as
0. And I thought it best to avoid something like ‘while (ticks <
ticks_last + interval) ticks = SDL_GetTicks();’ which would limit the
fame to that much time. Is there any way to remedy this?

I agree with David on this; using floating points is much more accurate.
Your code should calculate how many (fractional) seconds passed since
the last frame, and calculate the movement based on this time delta.
Your velX and velY seem to be fixed on a per-frame basis, but each frame
could be different in length. But if your approach works, keep it that way.

Oh, and you may want to change the guy’s velocity (now in the “//
Jump.” block) after the guy has moved, so you’ll get the full
max_velocity in the first frame of jumping.

I’m not sure what you mean here? This doesn’t make sense to me. How can
the guy move before the velocity is set? Perhaps I’m not understanding
what you meant.

No, not before it is set, before it is adjusted. In your (original)
"// Jump." block, you have a line
velY -= true_accel;
That’s the line I’m talking about. Move this more towards the back,
otherwise you will never use the full maximal velocity, only the
once-diminished form.

Bye,

Ben