SOLVED New, having issues with acceleration and deceleration.

D

Dekadrachm

Guest
movespeed = 0
maxmovespeed = .2



if (keyboard_check(vk_up))
{
if (movespeed < maxmovespeed) {
movespeed += 0.1
motion_add(image_angle, movespeed)
}
else
{
movespeed = maxmovespeed
motion_add(image_angle, movespeed)
}
}
else
{
if (movespeed > 0)
{
movespeed -= .01
motion_add(image_angle, movespeed)
}
}

The object moves in the direction of rotation using the motion_add function, but the script seems to entirely ignore my if statements. the object accelerates above maxspeed and does not slow down upon key release. "if movespeed < maxmovespeed works", but if i don't set the movespeed to the maxmovespeed when im defining the variables that if statement seems to entirely ignore whether or not move speed is greater than max speed, causing acceleration above the max parameters.
 

SoapSud39

Member
Acceleration doesn't stop because motion_add is in itself an acceleration function. So you're basically accelerating the amount by which you're accelerating. You'll want to do something like
GML:
direction = image_angle;
speed = move_speed;
The reason your object didn't seem to slow down is in part because you're doubly accelerating. It is also because your deceleration is 0.01 compared to the acceleration of 0.1.

Also, instead of using movespeed -= deceleration I would recommend using movespeed = max(0, movespeed - deceleration), so that your movespeed variable stops at 0 and you don't go backwards.
 
Last edited:

HayManMarc

Member
I set an "accel" and "decel" variable in the Create event:

accel = 0.1;
decel = 0.01;

When using 'speed' and 'direction', i will use "friction" as a constant deceleration. Also in Create event:

friction = 0.01;

With friction, you can now use decel as a braking mechanism in your code. Friction will always slow your movement eventually to zero.


Then do in Step event:
if (keyboard_check(vk_up))
{
if (movespeed < maxmovespeed) {
movespeed += accel;
}
}
motion_add(image_angle, movespeed);

Now, theres no need to do any slowing down in code, friction is doing that for you. (Unless you implement 'braking', then you'll need to add code for that.)
 
Last edited:
D

Dekadrachm

Guest
Acceleration doesn't stop because motion_add is in itself an acceleration function. So you're basically accelerating the amount by which you're accelerating. You'll want to do something like
GML:
direction = image_angle;
speed = move_speed;
The reason your object didn't seem to slow down is in part because you're doubly accelerating. It is also because your deceleration is 0.01 compared to the acceleration of 0.1.

Also, instead of using movespeed -= deceleration I would recommend using movespeed = max(0, movespeed - deceleration), so that your movespeed variable stops at 0 and you don't go backwards.
I suspected that I was double accelerating by using the add vector. I was able to get my friction to work so it slows down properly, and my braking function works. The issue im still having is the if statement ignoring my check on whether or not the speed is less than the maxspeed. The object still reaches speeds its not supposed to. Also, I want my braking function to double as reverse function while still having friction to counteract the movement. Im essentially trying to make controls for a top-down space game with un-natural friction because moving forever is impractical and annoying.

GML:
movespeed = 0;
maxmovespeed = 2.5;
maxreversespeed = -1;
acceleration = 0.12;
decceleration = -0.1;
direction = image_angle;
naturalfriction = maxmovespeed * 0.01;
friction = naturalfriction;

if (keyboard_check(vk_up))
{
    if (movespeed < maxmovespeed) {
        movespeed = max(0, movespeed + acceleration)
        
    }
}
if (keyboard_check(vk_down))
{
    if (movespeed > maxreversespeed)
    {
        movespeed += decceleration;
    }
}
motion_add(image_angle, movespeed)
if (keyboard_check(vk_right)) image_angle += .7
if (keyboard_check(vk_left)) image_angle -= .7;
 

HayManMarc

Member
Try this:
Code:
movespeed = 0;
maxmovespeed = 2.5;
maxreversespeed = -1;
acceleration = 0.12;
deceleration = -0.1;
direction = image_angle;
naturalfriction = 0.01;
friction = naturalfriction;

if (keyboard_check(vk_up))
{
if (movespeed < maxmovespeed) {
movespeed += acceleration;

}
}
if (keyboard_check(vk_down))
{
if (movespeed > maxreversespeed)
{
movespeed += deceleration;
}
}
motion_add(image_angle, movespeed);
if (keyboard_check(vk_right)) image_angle += 0.7;
if (keyboard_check(vk_left)) image_angle -= 0.7;
 

SoapSud39

Member
what HayManMark gave you should work, but to clarify, your object isn't stopping because you're using movespeed = max(0, movespeed + acceleration) which will use the value that is greater, and so always default to your movespeed if it is anywhere greater than 0. What you would want instead for that part is movespeed = min(maxmovespeed, movespeed + acceleration) which will give you the lesser of your max speed or your speed + acceleration.
 

SoapSud39

Member
also, the way you have your friction set up will, in my experience, really mess with tweaking the values, since it is active at any given point. So if you tried to change your acceleration and deceleration values, they wouldn't necessarily come out as expected because you're also applying the built-in friction to them at any given point. If your current system works for you, then that's fine, but if you want a slightly better time tweaking your numbers, I would recommend doing friction like so:

GML:
friction = 0;

if keyboard_check(vk_up)
{
    etc...
}
else friction = acceleration_friction;

if keyboard_check(vk_down)
{
    etc...
}
else friction = deceleration_friction;
 
D

Dekadrachm

Guest
also, the way you have your friction set up will, in my experience, really mess with tweaking the values, since it is active at any given point. So if you tried to change your acceleration and deceleration values, they wouldn't necessarily come out as expected because you're also applying the built-in friction to them at any given point. If your current system works for you, then that's fine, but if you want a slightly better time tweaking your numbers, I would recommend doing friction like so:

GML:
friction = 0;

if keyboard_check(vk_up)
{
    etc...
}
else friction = acceleration_friction;

if keyboard_check(vk_down)
{
    etc...
}
else friction = deceleration_friction;
If I press the up key, the object starts moving in the right direction, but once again the object ignores the acceleration maximum and now it continues to speed up. The problem im seeing potentially is that the motion_add is in the step event and which from what I've gathered is constantly adding the motion_add over and over again at an expotential rate. So depending on if my speed value is positive or negative, it either starts reversing at insane speeds or accelerating.
GML:
if (keyboard_check(vk_up))
{
if (movespeed < maxmovespeed) {
movespeed = min(maxmovespeed, movespeed + v_acceleration)

}
}
else friction = naturalfriction;
if (keyboard_check(vk_down))
{
if (movespeed > maxreversespeed)
{
    movespeed = min(maxreversespeed, movespeed - v_decceleration)
}
}
motion_add(image_angle, movespeed);

if (keyboard_check(vk_right)) image_angle -= .7
if (keyboard_check(vk_left)) image_angle += .7;
all my variables are defined in creation:
Code:
maxmovespeed = 2.5;
maxreversespeed = -1;
v_acceleration = 0.12;
v_decceleration = -0.1;
movespeed = 0;
direction = image_angle;
naturalfriction = maxmovespeed * 0.01;
friction = naturalfriction;
 
D

Dekadrachm

Guest
from what ive gathered the motion_add is the problem. if movespeed isnt constantly defined as 0 in the step event, then the add_motion function will continue to add the speed to itself expotentially, but if movespeed is defined as 0 constantly ,the expotential move speed stops because even though motion_add is constantly adding to itself, the speed will always be 0 unless modfied when holding the arrow key to accelerate. Motion added using the add_motion command appears to be entirely different than adding speed. The main issue now is that if the player holds the up key motion is endlessly added so long as movespeed is greater than 0. Also once direction is defined, reverse becomes impossible. I think it has to do with the image angle facing the wrong direction relative to motion.
 
Last edited by a moderator:

SoapSud39

Member
As I was about to reply:
That's true, I guess I totally ignored the issue with motion_add(). Correction to my earlier statements: your maxmovespeed doesn't actually affect the speed to which motion_add() takes you, so even if you set that, if you use motion_add() it'll keep accelerating anyway.

In the case that you're using motion_set(), you'll want to keep your movespeed over different steps, so remember to take off the movespeed = 0 at the beginning of step. Also, in the new code you sent, in the vk_down clause, you'll want movespeed = max(etc, etc) so that you don't decelerate forever.
 
D

Dekadrachm

Guest
As I was about to reply:
That's true, I guess I totally ignored the issue with motion_add(). Correction to my earlier statements: your maxmovespeed doesn't actually affect the speed to which motion_add() takes you, so even if you set that, if you use motion_add() it'll keep accelerating anyway.

In the case that you're using motion_set(), you'll want to keep your movespeed over different steps, so remember to take off the movespeed = 0 at the beginning of step. Also, in the new code you sent, in the vk_down clause, you'll want movespeed = max(etc, etc) so that you don't decelerate forever.
Yup, I got it all figured out thanks for your help! One other thing though, I had to define my movespeed variable as speed in order to keep friction working properly. Is there a way i can have the deceleration relative to the objects speed, so regardless of what speed the object is going the deceleration time is the same?
 

SoapSud39

Member
one way would be to take out the "else friction = ..." and instead put "else movespeed = movespeed / 20" (the lower the number, the faster it happens), which should give you a gradual slowdown. The thing is it won't be exactly the same amount of time but it'll be pretty close. Like friction it'll reduce your motion to 0, but unlike friction, it affects movespeed directly so you'd have fewer variables to worry about.

If you want to keep using friction (out of preference) you can try doing
GML:
else
{
    movespeed = 0;
    friction = abs(speed) / 20;
}
after your arrow key checks.
 

HayManMarc

Member
After the motion_add line, you can put a limiter on your speed, in the Step event:
Code:
if speed > maxmovespeed { speed = maxmovespeed;}
if speed < maxreversespeed { speed = maxreversespeed; }
 
Top