Jump to content
  • Advertisement
Sign in to follow this  
Puyover

Help with acceleration! :(

This topic is 2906 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

I'm trying to get my spaceship has acceleration and braking but I can not :S

This is the code I have:


// Acceleration
if(key[SDLK_w]) {
ship.AddY(-vel);
vel += INC_ACCEL;
dir[0] = true;
}
else if(key[SDLK_a]) {
ship.AddX(-vel);
vel += INC_ACCEL;
dir[12] = true;
}
else if(key[SDLK_s]) {
ship.AddY(vel);
vel += INC_ACCEL;
dir[8] = true;
}
else if(key[SDLK_d]) {
ship.AddX(vel);
vel += INC_ACCEL;
dir[4] = true;
}
// Braking
else {
if(dir[0]) {
vel -= vel*0.1;
ship.AddY(-vel);
if(vel < 0) {
vel = 0;
dir[0] = false;
}
}
else if(dir[4]) {
vel -= vel*0.1;
ship.AddX(vel);
if(vel < 0) {
vel = 0;
dir[4] = false;
}
}
else if(dir[8]) {
vel -= vel*0.1;
ship.AddY(vel);
if(vel < 0) {
vel = 0;
dir[8] = false;
}
}
else if(dir[12]) {
vel -= vel*0.1;
ship.AddX(-vel);
if(vel < 0) {
vel = 0;
dir[12] = false;
}
}
}

if(vel > MAX_ACCEL) {
vel = MAX_ACCEL;
}




0 -> Up
4 -> Right
8 -> Down
12 -> Left

It works more or less as it actually moves to where he wants...

Let's see if anyone can help
Regards!

Share this post


Link to post
Share on other sites
Advertisement
You don't seem to actually be using the newtonian motion equations which is probably making your life a lot harder.

newtonian motion:
s = 1/2*a*t^2 + v0*t + s0

s: position now
a: acceleration
t: time passed
v0: original velocity
s0: original position

you can track velocity separately:

newVelocity = acceleration*t + lastVelocity;
newPosition = 1/2*acceleration*t*t + lastVelocity*t + lastPosition


where:
t is time since last frame
acceleration is a vector in the direction the ship is currently facing.
<anything>Velocity is a vector
<anything>Position is a 3D point
however:
you can treat x,y,z acceleration/velocity/position separately. In that case the above are just the values per direction so you'd do that calculation 3 times, one for each axis in which you're interested.

Braking:
Need more info about how you want braking to behave. Is it active braking (user presses a button to bleed speed) or is it passive "braking" (the ship will slow down to a stop when you let go of all buttons?

-me

Share this post


Link to post
Share on other sites
Or you can skip the 1/2*acceleration*t*t by using newVelocity when calculating
position.

newVelocity = oldVelocity + acceleration*dt
newPosition = oldPosition + newVelocity*dt

in either case you need a class that encapsulates a 2D or 3D vector (2D in your case i guess) with the proper operator overloads, there are a lot of these available.

I recommend making your ship class something like this:

class Ship {
private:
vector2D speed;
vector2D acceleration;
vector2D postition
public:
void move(float dt)
{
speed+=acceleration*dt;
position+=speed*dt;
}
void setAcceleration(vector2D acc)
{
acceleration=acc;
}
};

all you now need is a appropriate vector2D class as i mentioned before.

Braking in space is nothing else but accelerating in the opposite direction, so for braking you just send -acc when using setAcceleration. If you want a natural breaking (slowing down over time) you need to add a always active negative acceleration (this simulates wind drag), this will also disable your ship to accelerate infinitely.

dragAcceleration = -speed*k;
where k is a constant which indicates how fast will your ship come to a stop.
now you speed eq looks like:
speed+=acceleration*dt + dragAcceleration*dt;

If you dont know how to calculate dt(time between frames) you can just send a small float instead(0.01 for example), this will only work if your frame rate if fairly constant, you will need to manage you frames sooner or later.

Hope this helped.

Share this post


Link to post
Share on other sites
1)

Quote:
0 -> Up
4 -> Right
8 -> Down
12 -> Left


OK; what do all the other elements of 'dir' represent?

2) Don't change the velocity when you process the key. Do it in separate physics-update logic.

3) When you call something "velocity", that means it has an amount and a direction. If you are only storing "how fast", that is called "speed", not "velocity".

4) Think about what happens when you are going in one direction and then you want to brake, by hitting the key for the other direction. Right now, every key INC_ACCEL, which never changes. So you can only ever accelerate. Also, you add vel or -vel depending on the direction key, so you change direction immediately and keep going even faster.

The mistake here is that you have not considered that velocity and acceleration do not have to be in the same direction.




What you have right now is a mess. Please don't try to fix it in steps; instead, understand how it is supposed to work and try again.

Represent acceleration as an X-acceleration and a Y-acceleration. When the user presses a direction key, set the X-acceleration and Y-acceleration immediately, and do not change velocity or position.

Represent velocity with X and Y components, too. Store all of these values - position, velocity and acceleration - within the Ship.

Give the ship two functions: "set_acceleration" (so you can tell it what keys were pressed) and "update". Get rid of AddY and whatever else. That is misunderstanding how objects are supposed to work. The ship is a thing; you don't drag it along and tell it where it should be - you push it (apply acceleration), and it moves (and keeps moving, because there is no friction in space).

In update(), you multiply each component of the acceleration by the elapsed time, and add to the velocity components. Then you do the same with the velocity components and the position components.

That gives you a very simple model. It's still not very realistic, because a spaceship does not really have any reference to X or Y directions - your acceleration should instead be forward, backward or turning. But understanding how to make turning work realistically is a little more complicated, so just try making this much work first.

Share this post


Link to post
Share on other sites
Quote:
Original post by Palidine
You don't seem to actually be using the newtonian motion equations which is probably making your life a lot harder.

newtonian motion:
s = 1/2*a*t^2 + v0*t + s0

s: position now
a: acceleration
t: time passed
v0: original velocity
s0: original position

you can track velocity separately:
*** Source Snippet Removed ***
where:
t is time since last frame
acceleration is a vector in the direction the ship is currently facing.
<anything>Velocity is a vector
<anything>Position is a 3D point
however:
you can treat x,y,z acceleration/velocity/position separately. In that case the above are just the values per direction so you'd do that calculation 3 times, one for each axis in which you're interested.

Braking:
Need more info about how you want braking to behave. Is it active braking (user presses a button to bleed speed) or is it passive "braking" (the ship will slow down to a stop when you let go of all buttons?

-me

Well, about breaking I want to stop pressing the button, the ship starts to slow down so that it moved a few pixels before stopping completely; passive braking like you say.

I'm using SDL and a 2D engine, so I only have X and Y, so what time should I put? SDL_GetTicks()? I control the fps and is constant to 62.5.

@Zahlman tomorrow I answer you; here is very late xD

[Edited by - Puyover on July 7, 2010 8:55:11 PM]

Share this post


Link to post
Share on other sites
this is simple but it's linear deceleration which may "feel" weird. Normally deceleration from air resistance is proportional to the square of the velocity (so rate of slowing is much steeper when you're moving fast).


if ( not accelerating )
velocity -= BREAKING_AMOUNT;



The time is literally the time since the last frame has been run, in seconds for convenience. So however you are calculating time passed since last frame to cap your framerate, use that. If your Frames Per Second is 62.5 you should be able to convert that into seconds per frame pretty easily [smile]

In answer to your other questions, I think you should probably learn some basic linear algebra and basic physics if what I and Zahlman have posted doesn't make much sense.

-me

Share this post


Link to post
Share on other sites
Well, at finish I solved without apply the uniform rectilinear motion equations; I only have to create a new variable (accelX, accelY) which I use to multiply by a constant (1.115) ...

This I have get and work very fine:

if(key[SDLK_w] && key[SDLK_d]) {
accelX *= ACELERACION; accelY *= ACELERACION;
ship.SetVel(accelX, -accelY);
}
else if(key[SDLK_a] && key[SDLK_w]) {
accelX *= ACELERACION; accelY *= ACELERACION;
ship.SetVel(-accelX, -accelY);
}
else if(key[SDLK_d] && key[SDLK_s]) {
accelX *= ACELERACION; accelY *= ACELERACION;
ship.SetVel(accelX, accelY);
}
else if(key[SDLK_s] && key[SDLK_a]) {
accelX *= ACELERACION; accelY *= ACELERACION;
ship.SetVel(-accelX, accelY);
}
else if(key[SDLK_w]) {
accelY *= ACELERACION;
ship.SetVelY(-accelY);
}
else if(key[SDLK_a]) {
accelX *= ACELERACION;
ship.SetVelX(-accelX);
}
else if(key[SDLK_s]) {
accelY *= ACELERACION;
ship.SetVelY(accelY);
}
else if(key[SDLK_d]) {
accelX *= ACELERACION;
ship.SetVelX(accelX);
}
else {
accelX /= ACELERACION; accelY /= ACELERACION;
ship.SetVel(ship.GetVelX()*DECELERACION, ship.GetVelY()*DECELERACION);
}

if(accelX < 1) accelX = 1;
if(accelY < 1) accelY = 1;
if(accelX > 5) accelX = 5;
if(accelY > 5) accelY = 5;

ship.AddPos(ship.GetVelX(), ship.GetVelY());




DECELERACION -> 0.99, I use this to decrease the speed of the ship very slowly (braking).

Thank you all!

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!