• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Smoothly slowing down an object based on it's distance from a point?

S

Squigglestixx

Guest
I'm programing a point and click adventure game where you can drag items from your inventory on to other objects in order to use them. I want the item object to snap back into it's place in your inventory if it can't be used, moving VERY quickly at first, and then much slower for the last bit of distance till it's back in it's place on your inventory bar. I've got the clicking and dragging parts down pretty well, but nothing I seem to change has any real effect on slowing down the object.

does anyone have any suggestions (with sample code hopefully) that can make this work? i've tried nested if statements that check the distance and lower the speed accordingly, but it seems to not have enough time to slow the object and you don't "see" the slowing effect (or it's just not working at all, i can't tell). i've also tried increasing the friction if the object is close to a point. this also seems to do literally nothing.
 

samspade

Member
You probably want to use something like the following I would scale the velocity (however you're doing that) by distance/scale range. For example:

GML:
spd = spd * min(1, (distance / max_range));
The above won't work without you modifying it to fit your code, but if you plug in some numbers you'll see that if you're farther t han max range then spd will be multiplied by 1 (and thus not be changed) but if you're closer than max range then spd will be scaled linearly to 0.
 
S

Squigglestixx

Guest
You probably want to use something like the following I would scale the velocity (however you're doing that) by distance/scale range. For example:

GML:
spd = spd * min(1, (distance / max_range));
The above won't work without you modifying it to fit your code, but if you plug in some numbers you'll see that if you're farther t han max range then spd will be multiplied by 1 (and thus not be changed) but if you're closer than max range then spd will be scaled linearly to 0.
thanks! i really have no idea how to use this though :(

i'm using
GML:
if point_distance(x, y, 83, 97) >5{
        move_towards_point(83,97,50)}
to move toward the point it came from, but i have no clue how to change that speed when the object gets close to it's target.

thanks for your help but i might just need to give up on this effect. it's easy to just make the object appear back in it's place instantly, even if it doesn't look great.
 

samspade

Member
It would be pretty straight forward to modify my code to work with your code I think, although in looking at my code it should have been spd = max_spd * min(1, (distance/max_range)) and probably max_range should have been named something like slow_down distance. The code I posted uses three variables, spd, distance, and max_range. Most of those concepts are present in your code - which I've re-written replacing your numbers with variable names.

GML:
distance = point_distance(x, y, 83, 97);
if (distance > 5) {
    spd = max_spd * min(1, (distance / max_range));
    move_towards_point(83, 97, spd);
}
 
S

Squigglestixx

Guest
It would be pretty straight forward to modify my code to work with your code I think, although in looking at my code it should have been spd = max_spd * min(1, (distance/max_range)) and probably max_range should have been named something like slow_down distance. The code I posted uses three variables, spd, distance, and max_range. Most of those concepts are present in your code - which I've re-written replacing your numbers with variable names.

GML:
distance = point_distance(x, y, 83, 97);
if (distance > 5) {
    spd = max_spd * min(1, (distance / max_range));
    move_towards_point(83, 97, spd);
}
amazing! thanks so much! this seems to work perfectly! for anyone else who might be reading this thread later, here's how i have the object set up:

Create:
GML:
max_range = 400
max_spd = 100

grab = false

xx = 0
yy = 0
Step:
GML:
if grab = false{
    distance = point_distance(x, y, 83, 97);
if (distance > 5) {
    spd = max_spd * min(1, (distance / max_range));
    move_towards_point(83, 97, spd);
}
else
speed = 0
}

if grab = true{
    x = mouse_x + xx;
    y = mouse_y + yy;
}
Right Mouse Down:
GML:
grab = true

xx = x - mouse_x
yy = y - mouse_y
Right Mouse Released:
GML:
grab = false
I'll probably have to add an alarm for the Mouse Release event since i don't want the player to be able to grab the object again too quickly, as this can interfere with the code and make things kinda wonky.
 
I know you already have an answer, and it's a bit more flexible than this. But there is a built-in function called lerp() which does roughly the same thing. Speed is based off a percentage of the distance remaining (if you are applying it in a sense that speed makes sense, it can be applied to other things as well). So while the distance is large, speed is relatively large as well, but as the distance shrinks, speeds gets conversely smaller (in a technical mathematical sense, it will never reach it's destination because it's basically following Zeno's paradox). It's one of a range of movement modifiers that can be applied to make interesting "juicy" movements (the others are not built-in but you can create your own functions for them if you want), but I'm having a massive brainfart right now and can't remember the name that applies to them all as a group.

Edit: Tweening, lol, that's the name. They're all variations on motion interpolation and can have a variety of interesting effects that can really spice up movement.
 
Last edited:

Tony Brice

Member
GML:
if grab = false{
    distance = point_distance(x, y, 83, 97);
if (distance > 5) {
    spd = max_spd * min(1, (distance / max_range));
    move_towards_point(83, 97, spd);
}
else
speed = 0
}

if grab = true{
    x = mouse_x + xx;
    y = mouse_y + yy;
}
Please don't take this the wrong way as maybe it's a bit of OCD on my part but I'd be careful how you're writing code based on this snippet, for example. Sometimes you're using brackets to do conditional checks and sometimes you're not. Sometimes semi-colons are used to close off a line and sometimes not. Also your variable check lines don't need to use a double == for the check but it's strongly recommended that you do so you get into the habit for other languages won't accept it.

GML:
if (grab == false) {
  distance = point_distance(x,y,83,97);
}
if (distance > 5) {
  spd = max_spd * min(1, (distance / max_range));
} else {
  speed = 0;
}

if (grab == true) {
  x = mouse_x + xx;
  y = mouse_y + yy;
}

[/QUOTE]
 
Top