orbiting planet simulation gets stuck?

So, just screwing around as I like to do I wanted to create a planet orbiting simulation. Not simply going in a circle I know how to do that (x(t)=di*cos(t), y(t)=di*sin(t)) I wanted to see if I could make the planets follow an ellipse path by simply using direction and speed as a function of distance from sun. Here's what I have:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include <cstdlib>
#include <stdlib.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_primitives.h>
#include <math.h>
#include <stdio.h>
#define GFACTOR 2.1
#define abs(x) (((x)<0) ? -(x) : (x))
#define PI 3.14159265

const float FPS = 60;
const int SCREEN_W = 640;
const int SCREEN_H = 480;

struct planet {
float x,y,mass;
ALLEGRO_COLOR c;
};

struct focal {
float x,y,mass;
ALLEGRO_COLOR c;
};

void getdxdy(planet a, focal b, float& dx, float& dy);
float getspeed(planet a,focal b);
float recip(float a);
void move(planet& a, focal b);
int inbounds(planet a);

void getdxdy(planet a, focal b, float& dx, float& dy)
{
	float theta=0;
	float speed=0;
	speed=getspeed(a,b);
	if(abs(a.x-b.x)>5)
	{
	theta=(a.y-b.y)/(a.x-b.x);
	theta = atan(theta);
	theta=recip(theta);
	dx = (speed * cos(theta));
	dy = (speed * sin(theta));
	}
	else {
		dx = -speed;
		dy = 0;
	}
}
float getspeed(planet a,focal b)
{
	float c;
	float dist = sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
	c = (GFACTOR*(a.mass*b.mass))/(dist*dist);
	//fprintf(stdout,"getspeed, c: %f\n",c);
	return c;
}
float recip(float a)
{
	float b = a+(PI/2);
	if(b>(2*PI))
	{
		b-=2*PI;
		fprintf(stdout,"\n\n\n\n\nangle adjustment happened\n\n\n\n\n");
	}
	fprintf(stdout,"recip, b: %f\n",b);
	return b;
}
void move(planet& a, focal b)
{
	float dx,dy;
	dx=dy=0;
	getdxdy(a,b,dx,dy);
	a.x+=dx;
	a.y+=dy;
}
int inbounds(planet a)
{
	return (!(((a.x-a.mass)>SCREEN_W)||((a.x-a.mass)<0)||((a.y-a.mass)>SCREEN_H)||((a.y-a.mass)<0)));
}
int main(int argc, char **argv)
{
   ALLEGRO_DISPLAY *display = NULL;
   ALLEGRO_EVENT_QUEUE *event_queue = NULL;
   ALLEGRO_TIMER *timer = NULL;
   ALLEGRO_BITMAP *bouncer = NULL;
   bool redraw = true;
 
   if(!al_init()) {
      fprintf(stderr, "failed to initialize allegro!\n");
      return -1;
   }
 
   if(!al_install_mouse()) {
      fprintf(stderr, "failed to initialize the mouse!\n");
      return -2;
   }
   timer = al_create_timer(1.0 / FPS);
   if(!timer) {
      fprintf(stderr, "failed to create timer!\n");
      return -3;
   }
   display = al_create_display(SCREEN_W, SCREEN_H);
   if(!display) {
      fprintf(stderr, "failed to create display!\n");
      al_destroy_timer(timer);
      return -4;
   }
   if(!al_init_primitives_addon())
   {
	   fprintf(stderr,"primitives didn't load\n");
	   return -5;
   }
   al_set_target_bitmap(al_get_backbuffer(display));
   event_queue = al_create_event_queue();
   if(!event_queue) {
      fprintf(stderr, "failed to create event_queue!\n");
      al_destroy_display(display);
      al_destroy_timer(timer);
      return -1;
   }

	planet a,b,c;
	focal sun, other;
	sun.x=330;
	sun.y=240;
	sun.mass=50;
	sun.c=al_map_rgb_f(255.0,255.0,0.0);
	other.x=330;
	other.y=240;
	other.mass=0;
	a.x=250;
	a.y=240;
	a.mass=10;
	a.c=al_map_rgb_f(255.0,0.0,0.0);
	b.x=190;
	b.y=240;
	b.mass=15;
	b.c=al_map_rgb_f(0.0,255.0,0.0);
	c.x=110;
	c.y=240;
	c.mass=22;
	c.c=al_map_rgb_f(0.0,0.0,255.0);


   al_register_event_source(event_queue, al_get_display_event_source(display));
   al_register_event_source(event_queue, al_get_timer_event_source(timer));
   al_register_event_source(event_queue, al_get_mouse_event_source());
   al_clear_to_color(al_map_rgb(0,0,0));
   al_flip_display();
   al_start_timer(timer);
 
   while(1)
   {
      ALLEGRO_EVENT ev;
      al_wait_for_event(event_queue, &ev);
 
      if(ev.type == ALLEGRO_EVENT_TIMER) {
         redraw = true;
      }
      else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
         break;
      }
      else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
          break;
      }
      if(redraw && al_is_event_queue_empty(event_queue)) {
         redraw = false;
         al_clear_to_color(al_map_rgb(0,0,0));
	 al_draw_filled_circle((sun.x-(sun.mass/2)),(sun.y-(sun.mass/2)),sun.mass,sun.c);
	if(inbounds(a))
	{
	 al_draw_filled_circle((a.x-(a.mass/2)),(a.y-(a.mass/2)),a.mass,a.c);
	}
	if(inbounds(b))
	{
	 al_draw_filled_circle((b.x-(b.mass/2)),(b.y-(b.mass/2)),b.mass,b.c);
	}
	if(inbounds(c))
	{
	 al_draw_filled_circle((c.x-(c.mass/2)),(c.y-(c.mass/2)),c.mass,c.c);
	}
	 move(a,sun);
	 move(b,sun);
	 move(c,sun);
         al_flip_display();
      }
   }
   al_destroy_timer(timer);
   al_destroy_display(display);
   al_destroy_event_queue(event_queue);
 
   return 0;
}


I'd also would be interested in a solution that uses physics equations to simulate planet orbit.
Or just... the parameters of an ellipse path

oh yeah the problem is it gets stuck directly under the sun, I can't get it to figure out how to move past dx<some value (so essentially all stuck in a vertical line down the screen) They start at the left side of the screen and move clockwise.
Last edited on
@line 38: might this be division by zero at times? Makes sense it would be during vertical alignment, but not so sure why it wouldn't happen with the planets at 12:00.
Last edited on
Whoops. I meant it goes counterclockwise. It starts at 9:00. Also, since its float, its never accurate I figured it would never actually reach 0 so whatever it evaluates to would simply overflow and give me the highest float value available.

I could just calculate distance and evaulate theta = asin(dy/h). I just don't get what would cause it to stick like that (technically it bounces back and forth)
Use atan2() to get the argument of a vector. It bypasses all this nonsense of divisions by zero and so on.
It definitely move farther, its get stuck at 12:00 instead of 6:00. Also the other planets won't show up for some reason. (I changed the coordinates of the planets)
Topic archived. No new replies allowed.