----------------------------------------------------------------------- -- 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 -- -- . -- ----------------------------------------------------------------------- with Ada.Real_Time; use Ada.Real_Time; with Mage; use Mage; with Mage.Draw; use Mage.Draw; with Mage.Event; use Mage.Event; --$ line question with Float_Maths; use Float_Maths; --$ begin answer with Solar_System; use Solar_System; with Solar_System.Graphics; use Solar_System.Graphics; --$ end answer procedure Packages_Main is --$ begin question -- define type Bodies_Enum_T as an enumeration of Sun, Earth, Moon, -- and Satellite type Bodies_Enum_T is (Sun, Earth, Moon, Satellite, Comet); -- define a type Body_T to store every information about a body -- X, Y, Distance, Speed, Angle, Color, Radius type Body_T is record X : Float := 0.0; Y : Float := 0.0; Distance : Float; Speed : Float; Angle : Float; Color : RGBA_T; Radius : Float; Turns_Around : Bodies_Enum_T; end record; -- define type Bodies_Array_T as an array of Body_T indexed by bodies -- enumeration type Bodies_Array_T is array (Bodies_Enum_T) of Body_T; --$ end question -- declare variable Bodies which is an array of Body_Type 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 question -- implement a function to compute the X coordinate -- x of the reference + distance * cos(angle) function Compute_X (Body_To_Move : Body_T; Turns_Around : Body_T) return Float; function Compute_X (Body_To_Move : Body_T; Turns_Around : Body_T) return Float is begin return Turns_Around.X + Body_To_Move.Distance * Cos (Body_To_Move.Angle); end Compute_X; -- implement a function to compute the Y coordinate -- y of the reference + distance * sin(angle) function Compute_Y (Body_To_Move : Body_T; Turns_Around : Body_T) return Float; function Compute_Y (Body_To_Move : Body_T; Turns_Around : Body_T) return Float is begin return Turns_Around.Y + Body_To_Move.Distance * Sin (Body_To_Move.Angle); end Compute_Y; procedure Move (Bodies : in out Bodies_Array_T; Body_To_Move_Index : Bodies_Enum_T); procedure Move (Bodies : in out Bodies_Array_T; Body_To_Move_Index : Bodies_Enum_T) is Body_To_Move : Body_T renames Bodies (Body_To_Move_Index); Turns_Around : constant Body_T := Bodies (Body_To_Move.Turns_Around); begin Body_To_Move.X := Compute_X (Body_To_Move, Turns_Around); Body_To_Move.Y := Compute_Y (Body_To_Move, Turns_Around); Body_To_Move.Angle := Body_To_Move.Angle + Body_To_Move.Speed; end Move; procedure Draw_Body (Object : Body_T; Canvas : Canvas_ID) is begin Draw_Sphere (Canvas => Canvas, Position => (Object.X, Object.Y, 0.0), Radius => Object.Radius, Color => Object.Color); end Draw_Body; --$ end question begin -- Create the main window Window := Create_Window (Width => 240, Height => 320, Name => "Solar System"); -- retrieve the graphical canvas associated with the main window Canvas := Get_Canvas (Window); -- initialize Bodies variable with parameters for each body using an -- aggregate Bodies := (Sun => (Distance => 0.0, Speed => 0.0, Radius => 20.0, X => 0.0, Y => 0.0, --$ line answer Visible => True, Angle => 0.0, Color => Yellow, Turns_Around => Sun), Earth => (Distance => 50.0, Speed => 0.02, Radius => 5.0, X => 0.0, Y => 0.0, --$ line answer Visible => True, Angle => 0.0, Color => Blue, Turns_Around => Sun), Moon => (Distance => 15.0, Speed => 0.04, Radius => 2.0, X => 0.0, Y => 0.0, --$ line answer Visible => True, Angle => 0.0, Color => White, Turns_Around => Earth), Satellite => (Distance => 8.0, Speed => 0.1, Radius => 1.0, X => 0.0, Y => 0.0, --$ line answer Visible => True, Angle => 0.0, Color => Red, Turns_Around => Earth), Comet => (Distance => 80.0, Angle => 0.0, Speed => 0.05, Radius => 1.0, X => 0.0, Y => 0.0, --$ line answer Visible => True, Color => Yellow, --$ line question Turns_Around => Sun)); --$ begin answer Turns_Around => Sun), Black_Hole => (Distance => 75.0, Angle => 0.0, Speed => 0.02, Turns_Around => Sun, Visible => False, others => <>), Asteroid_1 => (Distance => 5.0, Angle => 0.0, Speed => 0.1, Radius => 1.0, Color => Green, X => 0.0, Y => 0.0, Visible => True, Turns_Around => Black_Hole), Asteroid_2 => (Distance => 5.0, Angle => 3.14, Speed => 0.1, Radius => 1.0, Color => Cyan, X => 0.0, Y => 0.0, Visible => True, Turns_Around => Black_Hole)); --$ end answer -- initialize the Next step time at the current time (Clock) + period Next := Clock + Period; while not Is_Killed loop --$ begin question for B in Bodies_Enum_T loop -- call the move procedure for each body Move (Bodies, B); Draw_Body (Bodies (B), Canvas); end loop; --$ end question --$ begin answer Move_All (Bodies); Draw_All (Bodies, Canvas); --$ end answer Handle_Events (Window); delay until Next; Next := Next + Period; end loop; end Packages_Main;