Estoy intentando hacer un simulador de mecánica orbital en 2D. Tomen como referencia a los siguientes juegos:
- Kerbal Space Program (https://store.steampowered.com/app/220200/Kerbal_Space_Program/)
- Spaceflight Simulator (https://play.google.com/store/apps/details?id=com.StefMorojna.SpaceflightSimulator&hl=es)
- Children of a Dead Earth (https://store.steampowered.com/app/476530/Children_of_a_Dead_Earth)/
Así como Angry Birds tiene una forma de predecir sus trayectorias parabólicas, los juegos dichos también predicen las trayectorias elípticas:
(https://i.pinimg.com/originals/b2/24/76/b224767c7aaf07cac2f24ff958946f61.jpg)
(http://kspmods.net/wp-content/uploads/2015/10/screenshot288.jpg)
¿Cómo podría hacer esto último en Game maker? (A partir de mi código)Mi juego, por el momento consiste en un objeto Sol (
oSol) al centro y un objeto player (
oPlayer) que está orbitando a su alrededor.
Evento Create de oPlayer
x=oSol.x;
y=oSol.y-350;
hspeed=0.3;
Evento Step de oPlayer
//Codigo de gravedad hacia el Sol
var g, DirG;
with (oSol){
g = masa/sqr(point_distance(x, y, oPlayer.x, oPlayer.y)); //Ley de gravitacion F=GM/r^2
DirG = point_direction(oPlayer.x, oPlayer.y, x, y); //Direccion de la gravedad
with (oPlayer) {motion_add(DirG, g);} //Aceleracion de la gravedad
}
Evento Create de oSolmasa=25;
Evento Keyboards de oPlayerhspeed -= 0.001; //<Left>
vspeed -= 0.001; //<Up>
hspeed += 0.001; //<Right>
vspeed += 0.001; //<Down>
Lo que necesito saber es qué poner en el evento Draw para lograr hacer algo como lo que dije... Desde ya, muchas gracias!!
(https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Newton_Cannon.svg/240px-Newton_Cannon.svg.png)
Se puede hacer de esta forma, pero no es la más eficiente.
Puedes ver como funciona aquí: Ejemplo en GMLive (https://yal.cc/r/gml/?mode=GL&tabs_lz=NobwRAdghgtgpmAXGA8gJwEYEsAuYA0YAxgPYAmCyA9DQAQDCacUOctAogG5wQ4A6aPhDoAFADZQIcfoIgAPWgF5aaSWRIwA+qogBzOAAoATAAYT+WgGYzASgDcAoQE8lKtRu2T9xsxesn7Rwg0VwBWEztaGlUyLABXAGcg3VcARjNIml1VTlwXFlpYhJxJIjZUoKC6ACE4sTFpIIwFZR11LR1vdPNaABZbB1kMF1b3Dq9Dbot+gMGhDBDlXsyqGLisJNlc1zaPTsMTADpUiyOADnsoqiwIXCwoMVpuMRIiPKDYnbGDSwA2WauNzuD0KWCYRBwWBIEEqsgAxBQAGY3NhkVQAdyuVFoABEMRxuLxYUI6HioJiAA4SKQyIRo8maBLSTSkF5oAxETQYMRxOCBWT09HaOAQrwNHzmUw9fz4GW0HBoXn8ukYllgojiuQWJwWNAWREPJnKmGyUn4jB1Bq0iCCxnM1kkdmcphkY228ElPTiqZTPq+GYWBVKuY21VvNAawzNCzDGN62gGsRGkNVbFkzGO7DW21MnAskhsjmadEAC1wfJDtszuAMWp1uhjWtjuXwsWNH1VrDkOAM5h6fDAADERABlRC0AcAamKaBuugMiIpCRs7dkQQRcGRUloFJINzzRTzCQAjiE6AkiLOKdbUzu97xQcVSmwT3EoC6gkwcHE0BBaCf2XfXQ4ngXgTFoABaWggJAngcCMGxaEnf9TwMGDQJwVJIOgtBgIwyxVyEdckRRQpVWrHArn-S8sGvYlhGxABBXDYN4TYhE4d8dxaHC8LgiIripSRpFoOQgk4kIKRGXjWMwlYhJpWgnHEriKRSZR0Lgox5OpETsigXIcGUtcti45pXE03hLBWC16hEsTTJCYYLJYjDliuWyrSUlSnM4Fy+N4UIViBSEQQSCk4DgMgfNoDAyH82TfmC25QseWIPShE0iMc2LOB4ho9BwEt0s0OQDAwTgY1dEMJNy6SCt0IqSqccrKti6qYowBtYt0MgVn0wz8htWgBryUEMuhBNHViy1GhMlUGQpWcYDubguTgXQbgMJbNDEFEZ1o40mAilgDHCAJaBAIJaBusiGW4NAu3KpsnEuGhPJE3cEjuaFrtu8zJ2UCq5BWGASG4Ga7OtW7YpcQG6pDGGutcNSojvfdNEPRlUIpLUpMbfBhjeqg4gpMgWDYUajL+m6uvi5Rdwx9KRUhaFnsJnVuPwKTidJ8nWBGnIxuZiFMpp3KFHhhqmrBUryu6unebJin-wiqLxYquHlGl4rZZarqY1640AF8O0W5bVrgTQeDIAx7DAY2AF0gA)
[gml]
// Arguments
var px = argument0; //planet x
var py = argument1; //planet y
var pg = argument2; //planet gravity
var bx = argument3; //bullet x
var by = argument4; //bullet y
var bv = argument5; //initial speed
var bd = argument6; //initial direction
var bvx = lengthdir_x(bv, bd);
var bvy = lengthdir_y(bv, bd);
var bg, bgd; //gravity and gravity direction for bullet
draw_primitive_begin(pr_linestrip);
repeat(500) {
draw_vertex(bx,by); //bullet position
bx += bvx; //move bullet
by += bvy;
bg = pg / point_dist_sqr(px,py, bx,by); //update gravity
bgd = point_direction(bx,by, px,py); //update gravity direction
bvx += lengthdir_x(bg, bgd); //update speed
bvy += lengthdir_y(bg, bgd);
}
draw_primitive_end();
[/gml]
Dentro de ese script se usa otro script: point_dist_sqr
[gml]
// point distance squared
return sqr(argument0 - argument2) + sqr(argument1 - argument3);
[/gml]
Es mejor que usar point_distance y después elevar al cuadrado, nos ahorramos 2 operaciones.
Sería más eficiente si la trayectoria no se re-dibujara en cada evento Draw. Se podría dibujar en una surface.
También podría calcularse más rápido si se obtiene una ecuación paramétrica a partir de las condiciones inicales, no lo he investigado, pero debe se posible.
Algo que me parece complicado es hacer líneas punteadas con segmentos de longitud igual.