I've been trying to figure out how I can gradually accelerate a sprite on key pressed and then once the key is released, gradually slow down to a stop, much like the ship in Asteroids. I would like to do this without any game engine if possible. I searched this up on SO and found related questions, but they did not answer my question exactly in my opinion.
What I've thought of so far is:
//while the key is being pressed
//move by increasing y value
//but continue to increase the amount y increases by as you hold this down,
//until it reaches certain maxSpeed
//when the key is released, gradually decelerate to zero
I'm just unsure as to how to properly program this, because I can only think of ways to just increase by the same value and not gradually accelerate while holding.
So here is my goal (Gradually speed up and then gradually slow down):
I am a beginner and am open to all ideas, but the fact that I may not be approaching this problem correctly could be because I do not know as much as others
There are two "concepts" from physics which you need to implement: Speed and friction.
Here is a simple example in 2D. You may also use wrapper classes to combine the x/y variables into a single object and provide handy methods to alter their content.
Each object needs to have a position and a speed variable. We also need friction, which is a constant for each material (as your object probably always travels in the same material, we will just model friction to be constant). In this simple simulation, friction gets weaker, as the value approaches 1. That means at friction=1 you have no friction and at friction=0 your objects will stop immediately:
Notice that your object has an update method. this method needs to be called on all objects in your scene regularly, to apply the movement. In this method you could also process collision detection and enemies could do their AI logic..
Essentially acceleration and deceleration is the change of speed over time.
This assumes a few things.
This example uses a Swing
Timer
as the main "game loop". This is used to continuously update the state of the player object.It uses the key bindings API to change a
GameState
object which carries information about the current inputs into the game, this is used by thePlayer
to make decisions about what deltas should be applied.The example has quite a large maximum speed/rotation, so you can play with these, but if you release all the inputs, the game object will decelerate back to a "neutral" position (of
0
delta inputs).If you apply input in one direction for short period of time, then apply an input into the opposite direction, the player will need to decelerate down through
0
and then accelerate in the opposite direction (to a maximum speed), so it has breakingTake a look at How to Use Key Bindings and How to use Swing Timers for more details
Keep two variables.
Your velocity. This is how far you move the ship each time the game "ticks".
Your acceleration. This is how much you increase the velocity each time the game ticks.
To emulate the ship do something like this.
This only works for a ship going in a single direction along a straight line. You should be able to easily upgrade this to a two dimensional or three dimension space by keeping track of where the ship is pointed, and dividing the velocity amongst x and y and/or z.
You also need to be mindful of clamping values. You'll probably want a
maxAcceleration
, andmaxVelocity
. If the ship cannot go in reverse, then you want to make sure thatcurrentVelocity
never goes less than 0.This also only represents constant acceleration. You get the same amount of change in velocity the first second you put on the gas as you do the last second before you let it go. I'm not a car guy, but I think most vehicles accelerate faster after they've had a moment or so to get started. You could emulate that by using a piecewise function to calculate the acceleration where the function f(x) where you put howManyTicksTheForwardKeyHasBeenPressedFor in for x and get out the acceleration to apply to your velocity. Maybe the first 3 ticks add 1, and the other ticks add 2 to your velocity.
Have fun!
The previous questions have pretty much covered the subject, but if you want perfection, there is one more thing you need to be aware of: non-uniform time slices, that is, ticks of varying durations.
Normally, your tick() method should accept the current time and the duration of the last tick as parameters. (If it does not, then you need to calculate the duration of the last tick by querying the current time and remembering the time at which the last tick occurred, so that you can subtract one from the other.)
So, on each tick, you should not simply add the current speed to your position; what you should do instead on each tick, is add the current speed multiplied by the duration of the last tick to your position.
This way, if one tick happens very fast, and another tick takes a long time to complete, the movement of your spaceship will still be uniform.