gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Methods of jumping in a platform game

#29116 - identitycrisisuk - Thu Nov 11, 2004 9:07 pm

I have some ideas about how to do this but I'd like some disscussion about it and maybe hear how people have done it. Coming from always having access to floats and/or a relatively large screen size I guess I've been spoilt in that I could model jumping in a physics based manner by giving a character a single, large increase in upward velocity and rely on gravity to bring them down again in a smooth arc. I went to work at implementing something like this for the GBA, with the upward velocity decreasing by one each frame and it looked okay on my emulator which was running at a ridiculously low speed. However, now I've got it running at a better speed it looks ridiculous and would be unplayable as it happens so fast and I still don't think it's running as fast as hardware anyway.

So far most demos I have seen when jumping is involved, the velocity upwards looks like it is completely constant until it reaches its peak and then switches to the opposite direction. Fine for some things I suppose but I can't think of a 'nice' way to do that and it isn't really what I want.

I have also looked at the bouncing particles demo and that seems to use some form of fixed point calculation as the position is shifted right 8 bits before it is used to position the particle on screen (as far as I understand it). I'm just wondering if it can be this simple though and why it looks so smooth when I would think that the sudden changes from moving at 2 pixels per frame to one would make the motion look more like a series of straight lines than a smooth curve. I also wonder what a sensible maximum for the amount of pixels you can move in the y direction per frame is, surely it can't be higher than about 2 or 3?

The idea that I'm trying to do is based around Devil May Cry and the way using the handguns can keep you in the air for longer but taking it a step further. I want to make a scrolling platform shooter like Gunstar Heroes and when you fire while in the air it will increase your velocity in the direction opposite to that you're pointing your guns. I think it's quite a cool way of getting around that problem of having to move towards what you're firing at or having dual joysticks, stuck in one spot while firing etc. I also think it could be used to make puzzles that revolve around jumping and shooting, like being able to leap a chasm you couldn't do with a straight jump or firing down to reach a high platform.

#29118 - poslundc - Thu Nov 11, 2004 9:22 pm

My advice: use fixed-point everywhere involving units of measurement (such as distance and speed). It should be your standard to do so. That way you can fine-tune velocities/accellerations as much or as little as you want. So long as you use a reasonable amount of precision (at least 8 bits; I usually use 16) your animation will be plenty smooth. Remember that the screen updates 60 times per second; human perception of fluid motion is about half that.

Dan.

#29120 - jma - Thu Nov 11, 2004 9:49 pm

For most games I've worked on that required jumping, it was as simple as predefining a "vertical map" for each jump and keeping track of an index:

Code:
#define JUMP_TERMINAL 0xFF
const int v_map[] = { -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, JUMP_TERMINAL };

typedef struct sprite_data {
  // other stuff here...
  int *v_map_ptr;
  bool in_jump_anim;
} sprite_data;

void jump(sprite_data *sprite) {
  assert(!sprite->in_jump_anim);
  sprite->in_jump_anim = true;
  v_map_ptr = &v_map[0];
}

void cont_jump(sprite_data *sprite) {
  assert(sprite->in_jump_anim);
  move_sprite(sprite, sprite->x_velocity, *sprite->v_map_ptr++);
  if (*sprite->v_map_ptr == JUMP_TERMINAL) {
    sprite->in_jump_anim = false;
  }
}


Well, along those lines... you'd be amazed how "pretty" it looks and that no one notices simple integer jumps.

Jeff
_________________
massung@gmail.com
http://www.retrobyte.org

#29122 - ScottLininger - Thu Nov 11, 2004 9:56 pm

I think most platform/jumper games rely on basic gravity simulation using fixed-point coordinates.

For anybody who might be confused about what that means, here's the idea. Keep track of position inside the world using a coordinate system that's 8x bigger than the actual space, then divide by 8 (okay, bit shift by 3) to determine your screen position. That's really all that "fixed point math" means.

Example: If your world is 100 pixels x 100 pixels wide, you keep track of it internally as if it were 800x800. If you want your character to appear at pixel position (10,20), this value would actually be stored in your character variables as position (80,160). At display time, you divide your coordinates by 8 to determine where to draw the sprite.

This allows you to have smooth acceleration and deceleration using integers and not floating point numbers. If your x Acceleration value is +1/frame, then it will take 8 frames before the sprite moves a pixel, but internally the acceleration is nice and smooth, and there's a noticeable difference between an acceleration of +8 and +9.

If you want even finer control, divide by 16 instead of 8, or whatever you like. (The advantage to powers of 2 is that you can use a fast bit-shift to divide instead of a slow division.)

For simple physics simulation, never change the X and Y of your sprites directly. Instead, keep track of their velocity and acceleration. (Every frame your velocityX is changed by your accelerationX, and then your X is changed by your velocityX... same for Y)

For jumping, games like Mario break the laws of physics in a couple of ways:

1. So long as your jump button is held down, your character's YVelocity is an upward constant. Once you let off the button (or you reach a time limit for the maximum jump), then gravity takes over. That's how Mario can make longer jumps by holding the button.

2. You can change (and even reverse!) your X velocity in mid jump, which every 5th grader knows is impossible.


Hope that helps. When I first heard the term "fixed point math" I was stupefied and confused (which isn't that unusual for me.;) But it's really simple in practice.

-Scott

#29123 - expos1994 - Thu Nov 11, 2004 9:59 pm

I once was working on a platform game. And ran into the same problems you are having. At first I tried to base my jump on gravity and velocity. And I got frustrated with the results.

Then I decided that I was going to make my jump the way I wanted my jump to be. With no regards to realism. Because if you think about it, most of the successful 8-bit and 16-bit platform games never had realistic jumps. And when they did, it was very frustrating. Rush'n Attack comes to mind, that game really frustrated me.

Look at Super Mario Bros. and think about how he jumps. In mid-air, Mario can turn around and have his momentum be in the other direction... pretty impressive. Go out on your back porch and try that.

So my suggestion is: get creative.
---------------------
Changing the x coordinate one pixel per frame is probably too fast. He's
going to jump 60 pixels in one second. Or 5 up and 5 down in 1/6th of a second.

So if you want the jump to take between 1-2 seconds, then you'll have to only update the x-coordinate every (n)-number of frames.

Let's say you want him to reach the peak of his jump (10 pixels) in a half second (30 frames) . Then you would move him one pixel every 3 frames. Then he would jump in a uniform way, so you might want to span it out so he starts off quick and then slows near the top.

Of course, there are probably 90 different ways to code a jump. But I've found simple solutions like this to be easy to implement and also easy to modify and tweak. The point is, if it looks and works the way you want it, then it's perfect.

I think a gravity solution is too confining. I've played Devil May Cry, and that dude doesn't pay any attention to gravity. (If I jumped up and fired two shotguns at the ground, the kick wouldn't be near enough force to move my body. Let alone keep me in the air.) Don't let that stop you though, it's a good idea and a good effect so definitely use it.

PS> It's dangerous to jump up and fire two shotguns at the ground, so I've never actually tested my theory.

#29126 - Maxamor - Thu Nov 11, 2004 11:13 pm

I have also wondered the same thing, and I came up with a method I figured would work; I'm pretty sure it's the same as jma's but I'll explain it anyways. Basically, you have an array of vertical values you want to add over the course of the jump, which you add to your sprite's y position each n seconds. The only problem I ran into (which led me to never implement this idea) is that I had to take gravity into account. Either in the values of the jump, or use some type of finite state machine. So when you're jumping up, gravity wont affect you, but when your state changes to falling, gravity pulls you back down. I think this method is fairly simple, and was very effective back in the NES days. I actually recorded the incremental values of Megman when he jumps so I'd be able to duplicate it.

#29129 - identitycrisisuk - Fri Nov 12, 2004 12:34 am

Wow, lots of responses and lots of stuff I want to comment on.

poslundc wrote:
My advice: use fixed-point everywhere involving units of measurement (such as distance and speed). It should be your standard to do so. That way you can fine-tune velocities/accellerations as much or as little as you want. So long as you use a reasonable amount of precision (at least 8 bits; I usually use 16) your animation will be plenty smooth. Remember that the screen updates 60 times per second; human perception of fluid motion is about half that.


Good point on the human perception thing, I also think that this is amplified on the GBA because of the size of the screen. For example, on Advance Guardian Heroes running through an emulator you can see that the shadows are done by flickering a black oval on and off but on hardware it pretty much looks transparent unless it's really hectic or shadows overlap.

I think I'm finally getting the idea of fixed point as well, daft really as we were taught it in first year at uni but never really needed to make practical use of it. I wish I'd done GBA programming a lot earlier, I'm learning loads off it. I just modified a simple input tutorial to use fixed point velocity to update the position, capping the velocity at +/- 3<<8 and it looks really smooth, almost like mouse control. (I slowly reduce the velocity in x and y if those directions are not being held so there is inertia as well)

jma wrote:
For most games I've worked on that required jumping, it was as simple as predefining a "vertical map" for each jump and keeping track of an index:


That's actually a nicer system than I thought it might be, I guess I'm not that good at thinking about how to do things sometimes. However, and I know you say that's just a rough idea, that wouldn't really accomodate jumping where what you land on is at a different level. Easily fixed with collision tests though and detecting when on the last velocity and staying with that one til you actually hit the ground.

expos1994 wrote:
Let's say you want him to reach the peak of his jump (10 pixels) in a half second (30 frames) . Then you would move him one pixel every 3 frames.


I've not actually tried this and may do out of interest but the idea of only moving something every other frame or whatever kinda irks me. I know what poslundc said about human perception but I'm sure that it would seem noticable when something is effectively moving at 20 fps in a 60 fps scene.

expos1994 wrote:
I think a gravity solution is too confining. I've played Devil May Cry, and that dude doesn't pay any attention to gravity.


Yeah, screw gravity ;) I was referring to it in the loosest sense, no game I've ever made has actually had gravity modelled around 9.81m/s or whatever it is, just the idea that the vertical velocity decreases every frame. In DMC even the dual handguns keep him afloat, which is what I want to have and I will have to add a fairly big amount to the velocity to make an impact on his movement. I'm thinking of perhaps even changing the position directly, to give it a more jerky look. It will be a fine tuning thing of seeing how fast you can actually hammer the button on the GBA and adjusting it down so that someone hitting them at a fairly average speed can do what they need to and someone who goes mental might be able to use it to find secrets.

Oh and some people should go and play Super Mario Bros. You can't really adjust your x direction that much, certainly not as much as other games like Sonic (okay you still couldn't do it in real life :D ). It's quite a clever system and you don't see it very often.

#29131 - sajiimori - Fri Nov 12, 2004 12:49 am

60fps looks totally different than 30fps, and this has been well-known in the gaming community ever since Voodoo 2 SLI came out several years ago.

#29132 - poslundc - Fri Nov 12, 2004 1:23 am

It has more to do with resolution and timing than it does the actual frame rate the game runs at. A row of lightbulbs on a sign where a single one turns on and off down the line gives the illusion of fluid movement, even though the granularity is big and they're switching at much, much less than 60 Hz (maybe more like 5-10 Hz).

Remember that the object is not moving at 20 FPS in a 60 FPS scene. It's moving at 60 FPS in a 60 FPS scene, it's only moving 0.333 pixels per frame. The difference won't be visible until three frames pass, but this is more than enough for fluid motion of an object. If you don't believe me, try it and see.

Dan.

#29134 - sajiimori - Fri Nov 12, 2004 1:46 am

Quote:
It has more to do with resolution and timing than it does the actual frame rate the game runs at.
Sounds like you're recanting the statement that human perception doesn't exceed ~30fps. If that's not the case, you'll just have to check for yourself, or take the word of thousands of gamers who have had the experience of upgrading their hardware and going from 30 to 60fps.

#29135 - expos1994 - Fri Nov 12, 2004 1:55 am

Here's a little demo I put together a long time ago trying to learn how to move a platform character.

http://home.mchsi.com/~c.goudy/Little_Meeko.gba

Push the A button to make him jump. I looked at the code for this and I only updated his y-position every 5 frames. At the top of the jump it looks like it waits a full 15 frames to update (hard to tell though, the code is so messy. Who wrote this crap ;). )

It looks pretty good on hardware. I don't know about an emulator running < 100% though.
[/url]

#29136 - poslundc - Fri Nov 12, 2004 2:34 am

sajiimori wrote:
Sounds like you're recanting the statement that human perception doesn't exceed ~30fps.


poslundc wrote:
Remember that the screen updates 60 times per second; human perception of fluid motion is about half that.


As in, animation begins to appear fluid at about that point. But it depends on which compiler we're using. You know, so long as we're inventing stuff I said. Get over yourself, sajimori; I've got better things to do than entertain your desire to pick a fight.

Dan.

#29138 - expos1994 - Fri Nov 12, 2004 2:57 am

All right, the amount of frames per second that would be percieved as motion is 12. That is what cartoons are usually filmed at. There comes a point when you no longer even notice the extra frames, and if you are a cartoon animator (or a game animator), that means unnecessary work.

When you are talking about computer game graphics. It is the speed that the screen is drawn. If it doesn't update fast enough it lags and affects gameplay. It looks choppy. Especially in 3d games where the screen changes constantly.

What I think Dan is talking about is animating a 2d sprite. Which is a lot like animating a cartoon. And I think he's right. Anything much higher than 12fps is overkill. And that is true when you are talking about movement across the screen. If I move my character every five frames, that's 12 fps. It will look like smooth motion.

If your player is a big fat ogre that takes 10 seconds to walk across a 240 pixel screen, how are you going to do it if you move him 60 times a second, and the smallest amount you can move him is 1 pixel? In ten seconds moving the guy one pixel you will have moved him 600 pixels.

Also you have to factor in the actual sprite animation cels. It is the animation of the sprite along with the movement of the sprite that creates the illusion of motion. And if you do that at around 12fps, your animations will look fine, I guarantee it.

#29140 - keldon - Fri Nov 12, 2004 3:16 am

expos1994 wrote:
If your player is a big fat ogre that takes 10 seconds to walk across a 240 pixel screen, how are you going to do it if you move him 60 times a second, and the smallest amount you can move him is 1 pixel? In ten seconds moving the guy one pixel you will have moved him 600 pixels.

Animating at 60fps has nothing to do with always moving them by at least one pixel at 60fps =D

If you always update at a lower frame rate then you will always lower your players reaction and they can feel that. So creating an illusion is fine so long as you don't want them to react to it because they'll most likely react to the actual frames themselves because that's what carries the new information.

30fps = a new frame every 33 ms

People can hear when a note is delayed by 33 ms when they press a button; so I doubt we can not feel a difference when playing something that always visually lags by that much.

Of course moving when something is moving slowing than 1 pixel per frame then there is nothing you can do. And of course this is not to say that I'm suggesting 60 animation frames per second either or that all animation is to be done at 60fps =D

#29154 - identitycrisisuk - Fri Nov 12, 2004 1:04 pm

expos1994, your Little Meeko thing doesn't look too bad on my emulator, though I think I can see the jumps a little bit. However with this method I don't really know how you would integrate it nicely with fixed point movement. I suppose if you have a velocity that is less than 1<<8 then it would only result in an actual change to the onscreen position every other frame or even less frequent than that. Then you don't even have to think about setting up some kind of test as to whether you move the object or not that frame, it would just happen automatically.

#29160 - expos1994 - Fri Nov 12, 2004 5:43 pm

The thing about making a character jump is there are probably 1000 different ways to do it. I guess you just find one that suits you for your situation and go with it.

For this particular example I used an acceleration variable that starts out high and slows really fast until it comes to a stop at the top of the jump (a little hangtime) and then a quick descent.

I would say just experiment until you find what's right for you. I know when I go to make another platformer, I'll probably use a completely different method. Maybe do a Contra style jump where your guy starts doing a bunch of flips mid-air.

Devil May Cry style should be fun. Especially with the gun idea. You'll have to let me see it when you get it working.

#29173 - identitycrisisuk - Fri Nov 12, 2004 8:34 pm

If you go here then you can have a look at what I've done so far. Just a stickman for the moment but I was quite pleased with how I got the frames to be selected (still not sure whether the DMA is in the right place so there might possibly be some shearing but I doubt it). I did some calculations to work out good values for jumping, most games seem to do a jump in about a second. So if you make sure that your "gravity" value that you take away each frame is the same as your initial jump velocity divided by 32 (>>5) then the velocity will have become 0 in half a second. It's also not too hard to work out an initial jump velocity that will let you reach any height that you want, mine here gets you under half the screens height (without firing as well). If you hammer B while jumping then you can make quite a difference to your current velocity, pushing the top of stickman off the screen if you point straight down and fire as soon as you start jumping.

I'm not ready to put the source for it on display yet (very nasty at the moment) but if I make something of it I hope to eventually. I've found it very difficult to find demos of platformers with source in C so I think it might be useful to someone else.

#29175 - expos1994 - Fri Nov 12, 2004 9:20 pm

Good job so far. I can see the effect of the guns.

You might make Konami nervous if they think you are moving in on their Castlevania franchise.

#31618 - Piratero - Mon Dec 13, 2004 3:02 am

This may be off topic, but what would be a good and easy way of making a character slide as if he was on ice? also, identitycrisisuk: how did you did you do the collision?

#31622 - DekuTree64 - Mon Dec 13, 2004 4:14 am

For making a character slide on ice, just don't set his speed to 0 when you let go of the walk button. Instead, decrease it by some amount each frame so he'll take a while to get slowed down. The amount depends on how slippery you want the ice to be, just fiddle with it until it looks right.

To get a nice slippery feel when you actually try to walk, add a small value to his speed each frame too so it takes a while to get going. Then play his walking animation really fast so it looks like he's slipping all over the place^^

Careful though, when you're slowly accumulating speed instead of just setting it directly, he could get going way too fast. For that, I'd check if he's already going at his normal walking speed (and in the direction you pressed), and if so, don't add anything. That way he can still get sliding faster down a hill or something, but not by his own legs.

I can't speak for identitycrisisuk's collisions, but he does have another thread going here about diagonal tiles, which has some good info on how to handle walking in general too.
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#31625 - Piratero - Mon Dec 13, 2004 4:25 am

i understand, but what should i set the gravity, speed, etc? only thing close to what i can do is make him run slow then speed up
_________________
http://mrkotfw.ribrdb.com/

#31633 - DekuTree64 - Mon Dec 13, 2004 7:20 am

The exact values for things depend on how you have everything set up. Does your character already have an X/Y velocity that you add to his position each frame to make him move, and are your positions/velocities fixed-point? My solution before pretty much depends on those, and it's generally a good way to do things.

The tricky thing about platformer physics is that they're usually not realistic at all, so there's no set way to do it.
I'd suggest studying other games and see how the characters move for ideas. Like, in Super Mario World, you can hold B longer to jump higher, and as long as you're holding B, you go up at a constant speed (no gravity). Then if you let go of B, or have been going up for a certain amount of time, Mario switches into his 'obey normal physics' state and starts to slow down due to gravity. That's not how real physics work, but it gives you more control and makes it more fun.

Finite state machines are really good for platformers. In the Mario example above, you have 2 states. "Jumping", where you go up at a constant velocity and ignore gravity, and "falling", where gravity increases your downward speed each frame.
There's also the "on the ground" state, where you ignore gravity too. Check sajiimori's reply in that post I linked last time, he gives a good explanation of the 'on the ground' state.

Another way to get a more realistic jump is to skip the 'jumping' state altogether, and just go straight to 'falling', except set your upward velocity a lot higher so it takes longer for the gravity to turn you around.

Collisions are the hardest though, but it's still mostly just state switching (although I've never actually succeeded in making platformer collisions work, but then I haven't tried in a few years either)
_________________
___________
The best optimization is to do nothing at all.
Therefore a fully optimized program doesn't exist.
-Deku

#31639 - identitycrisisuk - Mon Dec 13, 2004 11:47 am

Yup, agree with what Dekutree's been saying. I've been updating that file I linked to as I go on, so it's a bit further on than it was when I posted this thread originally. I actually have a bit of inertia (is that the right word?) when you let go of a direction and the character carries on moving for a bit. This could easily be increased to create the effect of moving on ice, a set of values would be kept for the increase and decrease of speed depending on what surface you are on and then switch to the appropriate set depending on what surface you have detected you are on.

If you haven't already, you may want to look at fixed point to get more precision for the amounts of speed that you are adding. If all you can increase your position by each frame is 0, 1 or 2 then there isn't really enough precision to make slippery ice look good.

Collisions wise I've been using a map created with MapEd, which outputs collision data in the form of a number for each 8x8 tile in the map. I asked a few questions about how to do collision detection here and managed to get collisions with solid tiles pretty much okay and then in that post Dekutree mentioned I've been asking about diagonals, which are a bit trickier but I think I might get there soon.

I kinda wish I'd had a try at a platform game earlier than now, like it's been said there are some tricky things. A lot of what I've done in the past has been top-down or in full blown 3D. Still, at least I think I'm learning about good ways to do things first time, rather than building up bad habits if I'd been stumbling around in the dark trying to do it myself.
_________________
Code:
CanIKickIt(YES_YOU_CAN);

#31704 - tepples - Tue Dec 14, 2004 12:56 am

identitycrisisuk wrote:
Yup, agree with what Dekutree's been saying. I've been updating that file I linked to as I go on, so it's a bit further on than it was when I posted this thread originally. I actually have a bit of inertia (is that the right word?) when you let go of a direction and the character carries on moving for a bit. This could easily be increased to create the effect of moving on ice, a set of values would be kept for the increase and decrease of speed depending on what surface you are on and then switch to the appropriate set depending on what surface you have detected you are on.


Exactly. The value that determines traction between a shoe and the ground is the coefficient of friction, which depends mostly on the adhesion between the materials at the surface and their deformability. For example, dirt is more deformable than ice, which means the treads of a shoe's sole will slightly sink into the dirt. Physicists and mechanical engineers call this value "mu"; there are books of lookup tables of "mu" for pairs of common materials. As mu is typically between 0 and 1, I second the suggestion of fixed point arithmetic.

Quote:
If all you can increase your position by each frame is 0, 1 or 2 then there isn't really enough precision to make slippery ice look good.

Of course you could do it like in Chip's Challenge, where mu = 0 on ice, but natural ice in the polar regions is at least slightly rough.

Quote:
I kinda wish I'd had a try at a platform game earlier than now, like it's been said there are some tricky things. A lot of what I've done in the past has been top-down or in full blown 3D.

Have you made platforms in "full-blown 3D", such as in a Quake clone? You could try adapting the same data structures to do the collision, except ignoring the north-south dimension.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#31709 - identitycrisisuk - Tue Dec 14, 2004 1:12 am

tepples wrote:
Have you made platforms in "full-blown 3D", such as in a Quake clone? You could try adapting the same data structures to do the collision, except ignoring the north-south dimension.

Would complicate things a lot really, though it might be an idea to go back and look at it at least. One thing used a heightmap so collision with the ground is really easy and the other did use quake 3 maps but a lot of the work had already been done in getting ray-polygon collisions. I could just use some nice functions to work out the exact collision points, angle made with the ground etc.

I suppose I'm erring towards the side of premature optimisation in trying to get the best method possible rather than just using something I know but since there's no time limit on the project etc. I kinda like to do it early on when I can.
_________________
Code:
CanIKickIt(YES_YOU_CAN);