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

Drawing orbits and movement paths

P

peceecar

Guest
Hello, I'm working on a Kerbal space program inspired project and I've pretty much got most of the mechanics done but since my math knowledge is limited (especially geometry) I'm having trouble writing the draw code for the following:

I have a ship object (obj_player) and would like to draw a line/ orbit/ vector on the screen that shows the future movement of the object, similar to the one shown on the picture from kerbal space program (the blue curve with the AP tag above it or the purple one). The curve would have to be able to shift and adjust depending on how much thrust the player gives the ship. The gravity mechanics of the player around the planet, docking, lift off physics are all done. But I have no idea how to even begin coding this part. Does anyone have any ideas or some helpful tutorials?

The game is in 2D btw, so there's no need to calculate a z axis, just x,y points where to draw the curve.

Thank you :)

 

Tthecreator

Your Creator!
Well.... Do you have your movement figured out already? The first thing you should do is make your spaceship move without drawing the line.
To do this you need to find out how big the gravity on your object is.
You can use F = (G*m1*m2)/(r*r).
G here is a constant, you can look up what it is in the real world, or you can play with it to find something that looks good.
m1 is the mass of your planet
m2 is the mass of your spaceship
r is the distance between your spaceship and the planet. You can use the Pythagoras theorem to get the distance.

If there were no gravity at all, your spaceship would move in a straight line. However, the gravity curls the path of your spaceship into the shape you see.
If you were standing inside the spaceship, you would notice you would move to the right or the left. The amount you move depends on the gravity force.
Because your room's x and y coordinates aren't relative to the direction of the spaceship, you need to calculate the new angle of your spaceship using some math.
This is done using:
angle += arctan(sideways_force/forward_speed)
Perhaps you need to change the arctan function if you use degrees instead of radians.

I will admit I had to give myself a refresher on high school math, so I hope I didn't make any mistakes.
I also you understand (most) of what I've explained in this post.
 
This is not my code, just something that I found looking this up :)

Code:
///draw_bezier_quad(x-origo,y-origo,x1,y1,x2,y2,precision)

//Define points
p0x=argument0;
p0y=argument1;

p1x=argument2;
p1y=argument3;

p2x=argument4;
p2y=argument5;

//Define number of lines in curve
prec=argument6;

//Define lines
l1=point_distance(p0x,p0y,p1x,p1y);    //Length between P0 and P1
l2=point_distance(p1x,p1y,p2x,p2y);    //Lenght between P1 and P2

a1=point_direction(p0x,p0y,p1x,p1y);    //Angle between P0 and P1
a2=point_direction(p1x,p1y,p2x,p2y);    //Angle between P1 and P2

//Calculate bezier points
var t=0;
repeat(prec)
{
    //Define Q1
    q0x=p0x+lengthdir_x(l1*(t/prec),a1);  
    q0y=p0y+lengthdir_y(l1*(t/prec),a1);

    //Define Q2
    q1x=p1x+lengthdir_x(l2*(t/prec),a2);
    q1y=p1y+lengthdir_y(l2*(t/prec),a2);

    ql=point_distance(q0x,q0y,q1x,q1y);
    qa=point_direction(q0x,q0y,q1x,q1y);

    //Calculate B(t) using polar coordinates
    bx[t]=q0x+lengthdir_x(ql*(t/prec),qa);
    by[t]=q0y+lengthdir_y(ql*(t/prec),qa);

    t+=1;
}

//Draw bezier curve
var i=0;
repeat(prec-1)
{
    draw_line(bx[i],by[i],bx[i+1],by[i+1]);
    i+=1;
}

draw_line(bx[i],by[i],p2x,p2y);
EDIT:
Hmmm.....the project that I found this for doesn't work, at least in the sense it won't draw anything when I test it. I won't pretend to understand the maths behind this, and I could be missing something in the setup.
 
Last edited:
P

peceecar

Guest
Well.... Do you have your movement figured out already? The first thing you should do is make your spaceship move without drawing the line.
To do this you need to find out how big the gravity on your object is.
You can use F = (G*m1*m2)/(r*r).
G here is a constant, you can look up what it is in the real world, or you can play with it to find something that looks good.
m1 is the mass of your planet
m2 is the mass of your spaceship
r is the distance between your spaceship and the planet. You can use the Pythagoras theorem to get the distance.

If there were no gravity at all, your spaceship would move in a straight line. However, the gravity curls the path of your spaceship into the shape you see.
If you were standing inside the spaceship, you would notice you would move to the right or the left. The amount you move depends on the gravity force.
Because your room's x and y coordinates aren't relative to the direction of the spaceship, you need to calculate the new angle of your spaceship using some math.
This is done using:
angle += arctan(sideways_force/forward_speed)
Perhaps you need to change the arctan function if you use degrees instead of radians.

I will admit I had to give myself a refresher on high school math, so I hope I didn't make any mistakes.
I also you understand (most) of what I've explained in this post.
Ok, so brainstorming here.

The way the ship orbits is very basic, I just set a constant force (gravity) that's constantly adding speed (motion_add(pointing the planet, 0.2)).

The way the ship moves is by using the left and right arrow keys to rotate it's image angle, and then using the up arrow to add a force (motion_add(pointing in direction of image_angle),0.25)).
The issue with that solution would be mass is not used anywhere in my game currently and all the planet objects would have the same gravitational force(0.2)
The ship only escapes the planet during take off because the force applied from the engines is only 0.05 bigger than the drag the planet creates.
As I said I'm not very math or physichs savy so I'm trying to stick to basics when coding the physics in my projects. I've found the "arctan" help file from the game maker manual but unfortunately it's not very descriptive.
Could you go a bit into detail as to how it works? I'm gonna try figuring it out with a test.
Thank you.

The force moves the ship towards the planet and the added force from the up arrow key widens the orbit just as expected, it works a bit clunky but it works well so far
as shown in this screenshot:
upload_2019-8-31_11-50-1.png
 

Attachments

P

peceecar

Guest
This is not my code, just something that I found looking this up :)

Code:
///draw_bezier_quad(x-origo,y-origo,x1,y1,x2,y2,precision)

//Define points
p0x=argument0;
p0y=argument1;

p1x=argument2;
p1y=argument3;

p2x=argument4;
p2y=argument5;

//Define number of lines in curve
prec=argument6;

//Define lines
l1=point_distance(p0x,p0y,p1x,p1y);    //Length between P0 and P1
l2=point_distance(p1x,p1y,p2x,p2y);    //Lenght between P1 and P2

a1=point_direction(p0x,p0y,p1x,p1y);    //Angle between P0 and P1
a2=point_direction(p1x,p1y,p2x,p2y);    //Angle between P1 and P2

//Calculate bezier points
var t=0;
repeat(prec)
{
    //Define Q1
    q0x=p0x+lengthdir_x(l1*(t/prec),a1); 
    q0y=p0y+lengthdir_y(l1*(t/prec),a1);

    //Define Q2
    q1x=p1x+lengthdir_x(l2*(t/prec),a2);
    q1y=p1y+lengthdir_y(l2*(t/prec),a2);

    ql=point_distance(q0x,q0y,q1x,q1y);
    qa=point_direction(q0x,q0y,q1x,q1y);

    //Calculate B(t) using polar coordinates
    bx[t]=q0x+lengthdir_x(ql*(t/prec),qa);
    by[t]=q0y+lengthdir_y(ql*(t/prec),qa);

    t+=1;
}

//Draw bezier curve
var i=0;
repeat(prec-1)
{
    draw_line(bx[i],by[i],bx[i+1],by[i+1]);
    i+=1;
}

draw_line(bx[i],by[i],p2x,p2y);
EDIT:
Hmmm.....the project that I found this for doesn't work, at least in the sense it won't draw anything when I test it. I won't pretend to understand the maths behind this, and I could be missing something in the setup.
Hmm this is actually a start, well at least now I know it's called a bezier curve and can look up more stuff on youtube about it :D .
I'll delve in this code a bit and tell you if I've had any results by the end of today. Any other help would be appreciated. Thanks
 

NightFrost

Member
You can use F = (G*m1*m2)/(r*r).
And, since the difference between pull of a planet and a ship is so large, ship mass can be set to zero, it makes no difference at the fidelity a game is operating on. Gravity and stellar masses can be precalculated since the planets (and stars) are likely the only things exerting gravity. So the final formula can just be a planet's (or star's) pull value divided by distance squared, where the value part is adjusted until it delivers an effect that feels good.
 
P

peceecar

Guest
And, since the difference between pull of a planet and a ship is so large, ship mass can be set to zero, it makes no difference at the fidelity a game is operating on. Gravity and stellar masses can be precalculated since the planets (and stars) are likely the only things exerting gravity. So the final formula can just be a planet's (or star's) pull value divided by distance squared, where the value part is adjusted until it delivers an effect that feels good.
Yes, but here is where the bigger issue occurs, I managed to find a way of making the physics using only 2 lines that add constant forces, one pulling the player towards a planet, another that lets the player add momentum in a certain direction and thus being able to create a stable orbit around a planet. There's 2 pros that really help out here: planets won't have air or atmospheric friction and I'm desperately trying to avoid using physics elements like mass and instead relying just on math since that's my stronger ( read: almost non existant but still better than physics :D ) side. Most of the games I've made up until now feature very little real life physics and this was my first go at it. But I see how it can work if I tweak the variables a little and just store all the calculated values from the forces in a "mass" var. I'll do a few tests. If anyone else has any faster easier suggestions it would be much appreciated. Thank you all
 

Tthecreator

Your Creator!
Also you are making a game, it doesn't have to be realistic.
If you already have a way of making the spaceship move on it's own (if the player were to not touch any keys), you can easily hack this functionality in.
You can simply start draw a linestrip, and while drawing simulate your spaceship moving. Each step of movement you add another vertex to the simulated position. After drawing you make sure the spaceship is back at it's old position.
Code:
var nSteps = 100; //how many vertices your line should have
draw_primitive_begin(pr_linestrip)
temp_x = x;
temp_y = y;
for(var i=0;i<nSteps;++i){
[INDENT]temp_x = move_x(temp_x);//you will somehow have to change the values of temp_x accordingly
temp_y = move_y(temp_y);//also replace / implement this line

draw_vertex(temp_x,temp_y);//draw piece of line[/INDENT]
}
draw_primitive_end()
 

Yal

šŸ§ *penguin noises*
GMC Elder
The way KSP does it might be like this:
  • run the movement logic like 100 times but not updating your REAL position (also using this fake position to compute gravity from planets, etc)
  • store the Fake Position at each of those steps in an array
  • Finally, draw a line between each Fake Position in that array
 
Top