• 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!

Legacy GM [SOLVED] Circular movement around a given point

E

Etio

Guest
I wrote this to try and make an object move about a point:

Code:
spd = 1

dir = point_direction(x,y,obj_tether.x,obj_tether.y)+90
    
xchange = cos(degtorad(dir))
ychange = sin(degtorad(dir))
    
x += xchange*spd
y -= ychange*spd
(obj_tether being the point the object should be moving around) It appeared to be working fine, but when I tracked the distance from the object to obj_tether as it moved it was inconsistent, and even worse when it had completed a full revolution it ended up slightly further out than it began.

I can't see any issue with my code, if anyone has any alternatives to it or at least an explanation as to why it isn't working it'd be greatly appreciated.
 

jazzzar

Member
ok I had something like this in my game and that's how I did it :
defined two variables in create event called deltax and deltay :
Code:
deltax = value;
deltay = value;
That value depends on your situation, basically deltax is the difference between the rotating object's x and the stationnary one and deltay is the difference between in y;
Than get two value, angle and distance like so :
Code:
angle = point_direction(0, 0, delta_x, delta_y);
distance = point_distance(0, 0, delta_x, delta_y);
Now update it in step event :
Code:
x = obj_tether.x + lengthdir_x(distance, obj_tether.image_angle + angle);
y = obj_tether.y + lengthdir_y(distance, obj_tether.image_angle + angle);
Hope that helps
 

NightFrost

Member
In purely mathematical sense there's no issue with your code. In the real world though, there is an issue: accruing decimal rounding over time. For your code to work, GM would need to have infinite decimal accuracy. It doesn't, and each step your x and y get a liiiitle bit more out of sync from perfect circular orbit.

What you need to do, is to define the starting point of the orbiting object, and give it a starting angle. Easiest is to place it directly to the right of the center point and have an angle of zero. Then, in step event, you increase the angle by little bit, and always calculate new position from the original starting point coordinates with trig. Now because your starting coordinates will never change, your orbiting object cannot migrate due to decimal rounding accruing into its position. (I ran into this same problem long ago, trying to rotate vector cubes on Amiga.)

If your object has to run the orbit a potentially infinite amount of time, substract 360 from orbital angle each time it crosses that value, or before long you run into the hard integer limit GM variables have.

EDIT - looking at my projects, thanks to lengthdirs, there's even a simpler method to do this:
Code:
CREATE:
Orbit = 200; // Orbit distance
Angle = 0; // Current orbital angle
Speed = 1; // Orbital speed
Center_X = room_width / 2; // x of orbital center
Center_Y = room_height / 2; // y of orbital center

STEP:
// Orbital motion
Angle += Speed;
if(Angle >= 360) Angle -= 360;

// Update position
x = lengthdir_x(Orbit, Angle) + Center_X;
y = lengthdir_y(Orbit, Angle) + Center_Y;
 
Last edited:
E

Etio

Guest
In purely mathematical sense there's no issue with your code. In the real world though, there is an issue: accruing decimal rounding over time. For your code to work, GM would need to have infinite decimal accuracy. It doesn't, and each step your x and y get a liiiitle bit more out of sync from perfect circular orbit.

What you need to do, is to define the starting point of the orbiting object, and give it a starting angle. Easiest is to place it directly to the right of the center point and have an angle of zero. Then, in step event, you increase the angle by little bit, and always calculate new position from the original starting point coordinates with trig. Now because your starting coordinates will never change, your orbiting object cannot migrate due to decimal rounding accruing into its position. (I ran into this same problem long ago, trying to rotate vector cubes on Amiga.)

If your object has to run the orbit a potentially infinite amount of time, substract 360 from orbital angle each time it crosses that value, or before long you run into the hard integer limit GM variables have.

EDIT - looking at my projects, thanks to lengthdirs, there's even a simpler method to do this:
Code:
CREATE:
Orbit = 200; // Orbit distance
Angle = 0; // Current orbital angle
Speed = 1; // Orbital speed
Center_X = room_width / 2; // x of orbital center
Center_Y = room_height / 2; // y of orbital center

STEP:
// Orbital motion
Angle += Speed;
if(Angle >= 360) Angle -= 360;

// Update position
x = lengthdir_x(Orbit, Angle) + Center_X;
y = lengthdir_y(Orbit, Angle) + Center_Y;
Thank you! I'm messing around with the code a bit to fit my project, but it looks like it should work out perfectly. I knew the original code wasn't working because of an accuracy issue, but I'd assumed it was my own error, really annoying when computers get in the way of maths :(
 
E

Etio

Guest
ok I had something like this in my game and that's how I did it :
defined two variables in create event called deltax and deltay :
Code:
deltax = value;
deltay = value;
That value depends on your situation, basically deltax is the difference between the rotating object's x and the stationnary one and deltay is the difference between in y;
Than get two value, angle and distance like so :
Code:
angle = point_direction(0, 0, delta_x, delta_y);
distance = point_distance(0, 0, delta_x, delta_y);
Now update it in step event :
Code:
x = obj_tether.x + lengthdir_x(distance, obj_tether.image_angle + angle);
y = obj_tether.y + lengthdir_y(distance, obj_tether.image_angle + angle);
Hope that helps
Thank you too! This code is essentially identical to the other which worked perfectly! Sorry I didn't see your answer initially, I was too absorbed in watching my point fail to make a circle over and over...
 

jazzzar

Member
Thank you too! This code is essentially identical to the other which worked perfectly! Sorry I didn't see your answer initially, I was too absorbed in watching my point fail to make a circle over and over...
No problem at all
 
Top