Movement Physics In 2d Platformers


hessiess

Member
Joined
Apr 26, 2008
Messages
219
firstly this is not currently running on the gp2x, partly because I don't have one, partly because its programmed using irrlicht and partly because it uses600-700 meg of ram for storing a large number of quite high res sprites :lol:.

I am making a 2D platformer called "(don't) squash the penguin" the main difference between this game and most other platformers is the movement physics. pressing the left or right key causes the character to accelerate until a max speed is reached(acceleration and friction reach equilibrium), if no input is given the character slowly slows down eventually stopping. while jumping you have absolutely no control over the character, how far you jump is completely dependent on how fast you are moving when you jump i.e. jumping when stationery the character will only go strait up. the faster you are moving when jump is pressed the farther you go forwards, but the hight of the jump decreases. should you hit a wall the character will bounce off it at significantly reduced speed.

this can be sort of seen in this video
http://www.vimeo.com/919189

here is a newer video of the game, but with no movement physics
http://www.vimeo.com/1264043

problems:
----you jump way too far
----hight of the jump doesn't decrease with speed
----there are no character animations
----the character never stops moving
---- falling off a platform causes the character to fall at consent speed instead of accselorating downwards like would happen in reality.

here is the movement code for used in that video
CODE

/*
/////////////////////////////////////////////////////////////////////////////////////////////////
@FUNCTION: player acseloration

@COMMENTS: handles acseloration of the player
/////////////////////////////////////////////////////////////////////////////////////////////////
*/

vector3df player_acseloration(vector3df acseloration, int &jumping, float &jump, int floorcolide, int &wallcolide)
{

// friction
if(floorcolide == 1)
{
if(acseloration.X > 0)
acseloration.X -= .0004;
else
acseloration.X += .0004;
}

// gravaty
acseloration.Y = -0.035;

//cap player speed
if(acseloration.X > 0.02)
acseloration.X = 0.02;

if(acseloration.X < -0.02)
acseloration.X = -0.02;

// jump
if(jump > 0)
{
acseloration.Y += jump;
jump = jump - 0.0001;
}

//rebound off walls
if( wallcolide == 1)
{
acseloration.X -= (acseloration.X*2) * .7;
wallcolide = 0;
}

return acseloration;
}
/*
/////////////////////////////////////////////////////////////////////////////////////////////////
@FUNCTION: apply movement
/////////////////////////////////////////////////////////////////////////////////////////////////
*/

vector3df apply_movement(vector3df location, vector3df acseloration)
{
// apply movement to player
location.X += acseloration.X;
location.Y += acseloration.Y;

return location;
}



the main problem with this is that when you start moving and relece the controls the character slows down, but never completely stops. also the jump height remains constant no matter what speed you are traveling at.

any ideas?
 
What about something like that?

CODE
if (acseloration.X < 0.0008 and acseloration.X > -0.0008) acseloration.X = 0;


Provided you also test that no key is pressed at the time so its the phase when the character is slowing down.
 
You have mixed acceleration with speed, aka. velocity. Here's how it works. Velocity is the change of position over time. If you move 1 unit every second then velocity is 1 u/s. Acceleration is the change of the velocity over time. This brings us to the famous formula:

F = ma

Force equals mass times acceleration. If you want to make it simulate physics realistically you should only apply force (and sometimes acceleration) to your character. Friction is a force opposite the character's direction of movement.

Look up Newton's three laws of physics on wikipedia. It should help you :)

Now back to your problem with jumping. Physically realistic, you should only add y velocity to your character once you hit the jump button, and then let gravity bring him down. Right now you are adding

CODE

acseloration.Y += jump;



every iteration while jump is over 0. This will make your character accelerate up, which is something we people are not able to do mid-air ;) Instead i suggest you do something like this to make the character's jump height dependent on the speed:

CODE

if ( isJumping == false && jump == true )
{
asceloration.Y += asceloration.Length() * some_factor; // some_factor you need to adjust to be happy
isJumping = true;
}



Or something like that. Be aware that just because it is physically accurate doesn't mean it will be fun to play. Make sure you test your game to tweak the mechanics just right :)

Good luck.

(Edit: Btw, the reason your character isn't accelerating when he walks of an edge is because your acceleration vector is actually used as speed. Gravity is an acceleration, which would increase speed all the time. Try the -= operator instead on asceloration.Y)
 
I use alot of counters, if its like for gravity I use a counter saying if you hit say the space bar. You jump, and your moving up for 2,3 seconds and then the switch flips turning on gravity and the longer the counter goes before you collide with something below the faster you move. (I code in BB, a dead language :angry: so I don't think any source could help.)
 
Make Character speed x incriment * 0.95 or lower each frame
For gravity do
if (!not_on_floor) speedy+=gravity_inc; else speedy=0;
//also do not forgot check maximum falling speed (constant)

CODE

acseloration.X -= (acseloration.X*2) * .7;


Is the
CODE

acseloration.X -= (acseloration.X*1.4);
 
Yeah as someone else pointed out it seems you're confused between acceleration (not acseloration) and speed.

Acceleration tells how your speed changes, and speed says how your position changes.

So if you're undergoing an acceleration of 9.8 m.s^-2, that means that every second you speed is increasing in the direction of the acceleration by 9.8 m.s^-1. So if your last frame lasted say 16 ms then your speed augmented by 9.8 * 0.016 m.s^-1 in that direction.

As for free fall, here's what you want to do : using that 9.8 m.s^-2 is what you want to do, but you'll quickly realise that it only works correctly for low speeds. The thing is, air drag, which is the force of wind on you as you fall, increases with the square of the speed. And here's an interesting thing : when you fall after a while you reach terminal velocity, that is basically your max speed (unless you get more aerodynamic), and you stop accelerating because the air drag pulls you up as much as gravity pulls you down. That means that at that very speed the airdrag is 9.8 N, and therefore the upwards acceleration is 9.8 m.s^-2.

If your terminal velocity is 60 m.s^-1, you can deduce that if you go at half that speed, i.e. 30 m.s^-1, then the air drag will be 4 times less (since airdrag evolves with the square of speed, increasing the speed twice increases the drag 4 times), and you calculate it by doing 9.8 * current_airspeed / terminal_velocity = 9.8 * 30 / 60 = 4.9 m.s^-2

Of course, to find your total acceleration you add the two accelerations together, -9.8 m.s^-2 for gravity (notice the minus to indicate it's downwards) plus 4.9 m.s^-2 for airdrag (at a speed of 30 m.s^-1 that is), then to find your new speed you do speed_y += acceleration_y_total * frame_duration_in_seconds

Also you have lots of constant values in your code, you'd be better off using #define's for most of them, so you can easily change one value inside the entire program.
 
Back
Top