1. with Events.Corrals;                    use Events.Corrals; 
  2. with Events.Listeners;                  use Events.Listeners; 
  3. with Game_States;                       use Game_States; 
  4. with Game_Views;                        use Game_Views; 
  5. with Objects;                           use Objects; 
  6. with Processes;                         use Processes; 
  7.  
  8. private with Actors; 
  9. private with Ada.Containers.Indefinite_Doubly_Linked_Lists; 
  10. private with Ada.Containers.Ordered_Maps; 
  11. private with Associations; 
  12. private with Entities; 
  13. private with Events; 
  14. private with Events.World; 
  15. private with Physics.Managers; 
  16. private with Processes.Managers; 
  17. private with Worlds; 
  18.  
  19. package Games is 
  20.  
  21.     -- The Game class is parent object in the Game Logic system, which is 
  22.     -- responsible for managing the game session and all the interactions 
  23.     -- between entities during gameplay. 
  24.     -- 
  25.     -- The Game provides a Process_Manager to run the game logic, a Corral to 
  26.     -- receive events sent to listeners in the game logic, an association of 
  27.     -- modifyable game session variables, and game session persistence. The Game 
  28.     -- object itself is a Process and Event_Listener that is attached to its own 
  29.     -- Process_Manager and Corral facilities. The Game class also provides a 
  30.     -- limited interface, Game_State, which allow objects to reference it and 
  31.     -- access game state information and game session variables without a full 
  32.     -- view of the Game class, which in some cases would cause circular 
  33.     -- dependencies or allow unnecessary exposing of information. 
  34.     type Game is abstract new Limited_Object and 
  35.                               Event_Listener and 
  36.                               Game_State and 
  37.                               Process with private; 
  38.     type A_Game is access all Game'Class; 
  39.  
  40.     -- Creates a new Game object using the registered allocator. If no 
  41.     -- allocator has been registered, an exception will be raised. 
  42.     function Create_Game return A_Game; 
  43.     pragma Postcondition( Create_Game'Result /= null ); 
  44.  
  45.     -- Adds integer 'val' to game session variable 'var'. A Game_Var_Changed 
  46.     -- event is queued. An exception is raised on error. 
  47.     procedure Game_Var_Add( this : not null access Game'Class; 
  48.                             var  : String; 
  49.                             val  : Integer ); 
  50.     pragma Precondition( var'Length > 0 ); 
  51.  
  52.     -- Returns the Game's event Corral. It is created during Game construction. 
  53.     function Get_Corral( this : not null access Game'Class ) return A_Corral; 
  54.     pragma Postcondition( Get_Corral'Result /= null ); 
  55.  
  56.     -- Returns the value of game session var 'var' as an integer. An exception 
  57.     -- will be raised on error. 
  58.     function Get_Game_Var( this : access Game; var  : String ) return Integer; 
  59.  
  60.     -- Sets the game's view. 'view' is consumed and then owned by the Game 
  61.     -- object. If the view has already been set, a Constraint_Error will be 
  62.     -- raised and 'view' will not be modified. 
  63.     procedure Set_View( this : not null access Game'Class; 
  64.                         view : in out A_Game_View ); 
  65.     pragma Precondition( view /= null ); 
  66.     pragma Postcondition( view = null ); 
  67.  
  68.     -- Starts the game logic and attaches it to the framework. If the Game's 
  69.     -- view has not been set, a Constraint_Error will be raised. 
  70.     procedure Start( this : access Game ); 
  71.  
  72.     -- Stops the game logic and detaches it from the framework. 
  73.     procedure Stop( this : not null access Game'Class ); 
  74.  
  75.     -- Deletes the Game. 
  76.     procedure Delete( this : in out A_Game ); 
  77.     pragma Postcondition( this = null ); 
  78.  
  79. private 
  80.  
  81.     use Actors; 
  82.     use Associations; 
  83.     use Entities; 
  84.     use Events; 
  85.     use Events.World; 
  86.     use Physics.Managers; 
  87.     use Processes.Managers; 
  88.     use Worlds; 
  89.  
  90.     package Actor_Lists is new Ada.Containers.Indefinite_Doubly_Linked_Lists( A_Actor, "=" ); 
  91.  
  92.     package Actor_Maps is new Ada.Containers.Ordered_Maps( Entity_Id, A_Actor, "<", "=" ); 
  93.  
  94.     ---------------------------------------------------------------------------- 
  95.  
  96.     type Game is abstract new Limited_Object and 
  97.                               Event_Listener and 
  98.                               Game_State and 
  99.                               Process with 
  100.         record 
  101.             started, 
  102.             stopped     : Boolean := False; 
  103.             view        : A_Game_View := null; 
  104.             corral      : A_Corral := null; 
  105.             physics     : A_Physics := null; 
  106.             pman        : A_Process_Manager := null; 
  107.             sessionVars : A_Association := null; 
  108.             world       : A_World := null; 
  109.             actors      : Actor_Lists.List; 
  110.             actorIndex  : Actor_Maps.Map; 
  111.             playing     : Boolean := False; 
  112.             paused      : Boolean := False; 
  113.         end record; 
  114.  
  115.     -- Adds the Game object as an event listener for a set of events. Override 
  116.     -- this procedure, calling it first, to listen for additional events. 
  117.     procedure Add_Event_Listeners( this : access Game ); 
  118.  
  119.     -- Detaches the current world and attaches 'world' to the game framework. 
  120.     -- 'world' will be consumed. The currently attached world will be deleted. 
  121.     procedure Attach_World( this  : not null access Game'Class; 
  122.                             world : in out A_World ); 
  123.     pragma Postcondition( world = null ); 
  124.  
  125.     -- Detaches the current world and attaches 'newWorld' to the game framework. 
  126.     -- 'newWorld' will be consumed. The currently attached world will be 
  127.     -- returned as 'oldWorld'. It is still referenced by the process manager 
  128.     -- until the next Tick and may not be immediately deleted. 
  129.     procedure Attach_World( this     : not null access Game'Class; 
  130.                             newWorld : in out A_World; 
  131.                             oldWorld : out A_World ); 
  132.     pragma Postcondition( newWorld = null ); 
  133.  
  134.     procedure Construct( this : access Game ); 
  135.  
  136.     procedure Delete( this : in out Game ); 
  137.  
  138.     -- Ends the current game session. Game logic is stopped and a Game_State 
  139.     -- event is sent. 
  140.     procedure End_Game( this : access Game ); 
  141.  
  142.     -- Returns the Process name of the Game object. 
  143.     function Get_Process_Name( this : access Game ) return String; 
  144.     pragma Postcondition( Get_Process_Name'Result'Length > 0 ); 
  145.  
  146.     -- Handles the events that the Game is registered to receive from its Corral. 
  147.     procedure Handle_Event( this : access Game; 
  148.                             evt  : in out A_Event; 
  149.                             resp : out Response_Type ); 
  150.     pragma Precondition( evt /= null ); 
  151.  
  152.     -- Called when the Load_World event is received, to load and attach a world 
  153.     -- to the game framework during a game session. 
  154.     procedure Handle_Load_World( this : access Game; 
  155.                                  evt  : not null A_Load_World_Event; 
  156.                                  resp : out Response_Type ); 
  157.  
  158.     -- Begins a new game session from the start. Override this procedure to 
  159.     -- setup initial game state and load the first game world. An overriding 
  160.     -- implementation must call this first. 
  161.     procedure New_Game( this : access Game ); 
  162.  
  163.     -- Pauses the gameplay. An overriding implementation must call this first. 
  164.     -- It will set the paused field in the Game to 'enabled'. 
  165.     procedure Pause( this : access Game; enabled : Boolean ); 
  166.  
  167.     -- Removes the Game object as an event listener for a set of events. If 
  168.     -- Add_Event_Listener is overridden, then this should be overridden to 
  169.     -- remove the additional specific events. An overriding implementation must 
  170.     -- call this last. 
  171.     procedure Remove_Event_Listeners( this : access Game ); 
  172.  
  173.     -- Sets game session variable 'var' to integer 'val'. A Game_Var_Changed 
  174.     -- event is queued. 
  175.     procedure Set_Game_Var( this : not null access Game'Class; 
  176.                             var  : String; 
  177.                             val  : Integer ); 
  178.     pragma Precondition( var'Length > 0 ); 
  179.  
  180.     -- Sets game session variable 'var' to boolean 'val'. A Game_Var_Changed 
  181.     -- event is queued. 
  182.     procedure Set_Game_Var( this : not null access Game'Class; 
  183.                             var  : String; 
  184.                             val  : Boolean ); 
  185.     pragma Precondition( var'Length > 0 ); 
  186.  
  187.     -- Executes one frame of Game logic. Implement this procedure to perform 
  188.     -- logic at the Game scope. 
  189.     procedure Tick( this : access Game; time : Tick_Time ) is null; 
  190.  
  191.     ---------------------------------------------------------------------------- 
  192.  
  193.     -- A allocator for a concrete Game implementation. 
  194.     type Allocator is access function return A_Game; 
  195.  
  196.     -- Registers the allocator function used by Create_Game to create an 
  197.     -- instance of the appropriate concrete Game subclass. This should be called 
  198.     -- at elaboration time. 
  199.     procedure Register_Allocator( allocate : not null Allocator ); 
  200.  
  201. end Games;