Player Acceleration

Started by
5 comments, last by BeerNutts 11 years, 7 months ago
I've been trying to implement a simple acceleration for a character you can control, but for the life of me I cannot quite grasp it. :/

I know the equation, acceleration = velocity/time, gravity = -9.8m/s^2 but how can you implement time?

for vertical movement

int playerY;
int playerYvelocity= gravity * time?
int gravity = -10;

public void update(){
playerY += playerYvelocity;
}

Hmmmmm. Hmmmmm.dry.png
Advertisement
Time is (usually) either a fixed amount each frame (or physics update) or sometimes you actually take into account the real elapsed time (measured by getting the computer's clock at the last update and before updating) and using that as a time delta.

As for the code, that's not quite correct, you should be adding gravity * time to the player's Y velocity - remember it is an acceleration and acceleration is added to velocity as a vector (otherwise there wouldn't be much point in differentiating them). And the usage of time is slightly different but it really depends on what integration method you use, the most basic (and unstable) one is below. So you need to keep track of both the player's position and velocity, and each frame, go:


playerVelocity += gravity * time;
playerPosition += playerVelocity * time; // multiply by time again! google "explicit integration forward Euler" for explanations.


Of course, you need to handle collision with the ground otherwise your character will speed up downwards forever. You may find this useful, too.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

I looked into it, messed around with delta again, and I set the fps to 60 and I could finally got it working, kind of.

Below is the code that I got working.

public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException{
// unit = ms?
counter += delta;

heroYspeed+=gravity*counter;
heroY+=heroYspeed;

if (heroY>=440){
counter=0;
heroYspeed=0;

Input input= gc.getInput();
if(input.isKeyDown(Input.KEY_UP)){
heroY=0;
}

}


I know I didn't use heroY += heroYspeed * time; but the character disappears when I use that code. It made sense that velocity * time would be distance and I wanted it to work, but I'm tired from wrapping my head around a few concepts, ha, ha.... (I spend some time in khan academy, and exercising my brain :P)

I also want to find out about the relationship between delta, fps and update time. It's vague to me right now.
If your FPS is locked at 60, try using a constant delta of 1 / 60 seconds, for debugging purposes. Also, what is the purpose of "counter" in your code? I'm probably not explaining it all too well but the velocity and position increments are per-frame, so they need to be moderated by some time delta to make sense, this is what the multiplication by the delta is for.

If you think you need the "counter" so that the player can actually accelerate, then no, it's not needed - that's the beauty of it: the double effect of acceleration on position (velocity += acceleration, and then position += velocity) results in position depending on acceleration squared, naturally producing the parabola you'd expect from an object subject to gravity.

It would look somewhat like this:

heroYspeed += gravity * (1.0 / 60.0);
heroY += heroYspeed * (1.0 / 60.0);

if (heroY>=440){
heroYspeed=0; // crude ground collision detection :P
}


Does it make more sense now?

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

What are you using for gravity? If you are using 10, realize that in feet for distance, but you are operating in a virtual world, and displaying in pixels. For simplicity, you can use pixels as the distance, and using 10 would mean your player would increase his VELOCITY by 10 pixels/second. You may need to modify that value to get it to what you would like.

Also, be sure you are storing player velocity and position as a float, or else you will lose a lot of precision.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

@Bacterius
I think so.

What you are saying is *time isn't necessary because it's already there as it's updated every set interval, right?

I tested it out, and I'm happy to see it working. :D

@BeerNutts
I wanted to use float but I didn't know how big is 1f in comparison to 1 pixel so, I used integers and doubles, for now. :-P

I plugged this in as gravity:

double gravity=980/360; (converting at 1m=100pixels, and 60 delta = second)


I made the heroYspeed decrease in value when key.space is inputted, so that he jumps with deceleration and falls with acceleration. rolleyes.gif

I want to tweak the values around a bit, but I think I will move on to horizontal movement and friction. Khan academy, maybe?
When I said float, I just meant not an integer. A double is probably better to use than float, when speaking in C/C++ contexts these days.

You should not be using integers anywhere during these computations. 1f is 1, doesn't matter what it's representing. If you have player position as an integer, then, when you add a partial distance, say 1.9 pix, you're only going to be adding 1 to the position, and the next time you add 1.9 pix, it'll be 1 again, for 2 pixels in 2 frames. Whereas, if you use floats, adding 1.9 to the position, the player will be shown on the screen only moving 1 pixel (since pixels are discrete), but the next frame, the player's position will have moved 1.9+1.9 = 3.8 pixels, and be shown as 3 pixels on the screen. it just gets worse after that.

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

This topic is closed to new replies.

Advertisement