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 | -----------------------------------------------------------------------
-- Ada Labs --
-- --
-- Copyright (C) 2008-2023, AdaCore --
-- --
-- This program is free software: you can redistribute it and/or --
-- modify it under the terms of the GNU General Public License as --
-- published by the Free Software Foundation, either version 3 of --
-- the License, or (at your option) any later version. --
-- --
-- This program is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
-- GNU General Public License for more details. --
-- --
-- You should have received a copy of the GNU General Public License --
-- along with this program. If not, see --
-- <https://www.gnu.org/licenses/>. --
-----------------------------------------------------------------------
with Ada.Real_Time; use Ada.Real_Time;
with Mage; use Mage;
with Mage.Draw; use Mage.Draw;
with Mage.Event; use Mage.Event;
with Float_Maths; use Float_Maths;
procedure Record_Types_Main is
-- define type Bodies_Enum_T as an enumeration of Sun, Earth, Moon,
-- and Satellite
type Bodies_Enum_T is (Sun, Earth, Moon, Satellite);
-- define subtype Rotating_Bodies_T which only contains bodies
-- that rotate
subtype Rotating_Bodies_T is Bodies_Enum_T range Earth .. Satellite;
-- define a type Body_T to store every information about a body
-- X, Y, Distance, Speed, Angle, Color type is RGBA_T, Radius
--$ begin answer
type Body_T (Visible : Boolean := True) is record
X : Float;
Y : Float;
Distance : Float;
Speed : Float;
Angle : Float;
Turns_Around : Bodies_Enum_T;
case Visible is
when True =>
Color : RGBA_T;
Radius : Float;
when others =>
null;
end case;
end record;
--$ end answer
-- define type Bodies_Array_T as an array of Body_T indexed by bodies
type Bodies_Array_T is array (Bodies_Enum_T) of Body_T;
-- declare variable Bodies which is an array of Body_T
Bodies : Bodies_Array_T;
-- declare a variable Next of type Time to store the Next step time
Next : Time;
-- declare a constant Period of 40 milliseconds of type Time_Span defining
-- the loop period
Period : constant Time_Span := Milliseconds (40);
-- reference to the application window
Window : Window_ID;
-- reference to the graphical canvas associated with the application window
Canvas : Canvas_ID;
begin
-- create a window 240x320
Window := Create_Window (Width => 240,
Height => 320,
Name => "Solar System");
-- retrieve the graphical canvas from the window
Canvas := Get_Canvas (Window);
-- initialize Bodies variable with parameters for each body using an
-- aggregate
-- Sun Distance = 0.0, Angle = 0.0, Speed = 0.0, Radius = 20.0,
-- Color = Yellow
-- Earth Distance = 50.0, Angle = 0.0, Speed = 0.02, Radius = 5.0,
-- Color = Blue
-- Moon Distance = 15.0, Angle = 0.0, Speed = 0.04, Radius = 2.0,
-- Color = White
-- Satellite Distance = 8.0, Angle = 0.0, Speed = 0.1, Radius = 1.0,
-- Color = Red
--$ begin answer
Bodies := (Sun => (Visible => True,
Distance => 0.0,
Speed => 0.0,
Radius => 20.0,
X => 0.0,
Y => 0.0,
Angle => 0.0,
Color => Yellow,
Turns_Around => Sun),
Earth => (Visible => False,
Distance => 50.0,
Speed => 0.02,
-- Radius => 5.0,
X => 0.0,
Y => 0.0,
Angle => 0.0,
-- Color => Blue,
Turns_Around => Sun),
Moon => (Visible => True,
Distance => 15.0,
Speed => -0.04,
Radius => 2.0,
X => 0.0,
Y => 0.0,
Angle => 0.0,
Color => White,
Turns_Around => Earth),
Satellite => (Visible => True,
Distance => 8.0,
Speed => 0.1,
Radius => 1.0,
X => 0.0,
Y => 0.0,
Angle => 0.0,
Color => Red,
Turns_Around => Earth));
--$ end answer
-- initialize the Next step time at current time (Clock) + the period
Next := Clock + Period;
while not Is_Killed loop
-- create a loop to update each body position and angles
-- the position of an object around (0,0) at distance d with an angle
-- a is (d*cos(a), d*sin(a))
-- update angle parameter of each body adding speed to the previous
-- angle
--$ begin answer
for B in Rotating_Bodies_T loop
declare
-- rename to clarify indexing
Moving_Body : Body_T renames Bodies (B);
-- constants being used
TA : constant Bodies_Enum_T := Moving_Body.Turns_Around;
Center_Of_Rotation : constant Body_T := Bodies (TA);
A : constant Float := Moving_Body.Angle;
D : constant Float := Moving_Body.Distance;
begin
Moving_Body.X := Center_Of_Rotation.X + D * Cos (A);
Moving_Body.Y := Center_Of_Rotation.Y + D * Sin (A);
Moving_Body.Angle := A + Moving_Body.Speed;
end;
end loop;
--$ end answer
-- create a loop to draw every objects
-- use the Draw_Sphere procedure to do it
--$ begin answer
for B in Bodies_Enum_T loop
declare
-- constant to clarify code
Drawn_Body : constant Body_T := Bodies (B);
begin
if Drawn_Body.Visible then
Draw_Sphere (Canvas => Canvas,
Position => (Drawn_Body.X, Drawn_Body.Y, 0.0),
Radius => Drawn_Body.Radius,
Color => Drawn_Body.Color);
end if;
end;
end loop;
--$ end answer
-- update the screen using procedure Swap_Buffers
Handle_Events (Window);
-- wait until Next
delay until Next;
-- update the Next time adding the period for the next step
Next := Next + Period;
end loop;
end Record_Types_Main;
|