with Events.Corrals; use Events.Corrals;
with Events.Listeners; use Events.Listeners;
with Game_States; use Game_States;
with Game_Views; use Game_Views;
with Objects; use Objects;
with Processes; use Processes;
private with Actors;
private with Ada.Containers.Indefinite_Doubly_Linked_Lists;
private with Ada.Containers.Ordered_Maps;
private with Associations;
private with Entities;
private with Events;
private with Events.World;
private with Physics.Managers;
private with Processes.Managers;
private with Worlds;
package Games is
-- The Game class is parent object in the Game Logic system, which is
-- responsible for managing the game session and all the interactions
-- between entities during gameplay.
--
-- The Game provides a Process_Manager to run the game logic, a Corral to
-- receive events sent to listeners in the game logic, an association of
-- modifyable game session variables, and game session persistence. The Game
-- object itself is a Process and Event_Listener that is attached to its own
-- Process_Manager and Corral facilities. The Game class also provides a
-- limited interface, Game_State, which allow objects to reference it and
-- access game state information and game session variables without a full
-- view of the Game class, which in some cases would cause circular
-- dependencies or allow unnecessary exposing of information.
type Game is abstract new Limited_Object and
Event_Listener and
Game_State and
Process with private;
type A_Game is access all Game'Class;
-- Creates a new Game object using the registered allocator. If no
-- allocator has been registered, an exception will be raised.
function Create_Game return A_Game;
pragma Postcondition( Create_Game'Result /= null );
-- Adds integer 'val' to game session variable 'var'. A Game_Var_Changed
-- event is queued. An exception is raised on error.
procedure Game_Var_Add( this : not null access Game'Class;
var : String;
val : Integer );
pragma Precondition( var'Length > 0 );
-- Returns the Game's event Corral. It is created during Game construction.
function Get_Corral( this : not null access Game'Class ) return A_Corral;
pragma Postcondition( Get_Corral'Result /= null );
-- Returns the value of game session var 'var' as an integer. An exception
-- will be raised on error.
function Get_Game_Var( this : access Game; var : String ) return Integer;
-- Sets the game's view. 'view' is consumed and then owned by the Game
-- object. If the view has already been set, a Constraint_Error will be
-- raised and 'view' will not be modified.
procedure Set_View( this : not null access Game'Class;
view : in out A_Game_View );
pragma Precondition( view /= null );
pragma Postcondition( view = null );
-- Starts the game logic and attaches it to the framework. If the Game's
-- view has not been set, a Constraint_Error will be raised.
procedure Start( this : access Game );
-- Stops the game logic and detaches it from the framework.
procedure Stop( this : not null access Game'Class );
-- Deletes the Game.
procedure Delete( this : in out A_Game );
pragma Postcondition( this = null );
private
use Actors;
use Associations;
use Entities;
use Events;
use Events.World;
use Physics.Managers;
use Processes.Managers;
use Worlds;
package Actor_Lists is new Ada.Containers.Indefinite_Doubly_Linked_Lists( A_Actor, "=" );
package Actor_Maps is new Ada.Containers.Ordered_Maps( Entity_Id, A_Actor, "<", "=" );
----------------------------------------------------------------------------
type Game is abstract new Limited_Object and
Event_Listener and
Game_State and
Process with
record
started,
stopped : Boolean := False;
view : A_Game_View := null;
corral : A_Corral := null;
physics : A_Physics := null;
pman : A_Process_Manager := null;
sessionVars : A_Association := null;
world : A_World := null;
actors : Actor_Lists.List;
actorIndex : Actor_Maps.Map;
playing : Boolean := False;
paused : Boolean := False;
end record;
-- Adds the Game object as an event listener for a set of events. Override
-- this procedure, calling it first, to listen for additional events.
procedure Add_Event_Listeners( this : access Game );
-- Detaches the current world and attaches 'world' to the game framework.
-- 'world' will be consumed. The currently attached world will be deleted.
procedure Attach_World( this : not null access Game'Class;
world : in out A_World );
pragma Postcondition( world = null );
-- Detaches the current world and attaches 'newWorld' to the game framework.
-- 'newWorld' will be consumed. The currently attached world will be
-- returned as 'oldWorld'. It is still referenced by the process manager
-- until the next Tick and may not be immediately deleted.
procedure Attach_World( this : not null access Game'Class;
newWorld : in out A_World;
oldWorld : out A_World );
pragma Postcondition( newWorld = null );
procedure Construct( this : access Game );
procedure Delete( this : in out Game );
-- Ends the current game session. Game logic is stopped and a Game_State
-- event is sent.
procedure End_Game( this : access Game );
-- Returns the Process name of the Game object.
function Get_Process_Name( this : access Game ) return String;
pragma Postcondition( Get_Process_Name'Result'Length > 0 );
-- Handles the events that the Game is registered to receive from its Corral.
procedure Handle_Event( this : access Game;
evt : in out A_Event;
resp : out Response_Type );
pragma Precondition( evt /= null );
-- Called when the Load_World event is received, to load and attach a world
-- to the game framework during a game session.
procedure Handle_Load_World( this : access Game;
evt : not null A_Load_World_Event;
resp : out Response_Type );
-- Begins a new game session from the start. Override this procedure to
-- setup initial game state and load the first game world. An overriding
-- implementation must call this first.
procedure New_Game( this : access Game );
-- Pauses the gameplay. An overriding implementation must call this first.
-- It will set the paused field in the Game to 'enabled'.
procedure Pause( this : access Game; enabled : Boolean );
-- Removes the Game object as an event listener for a set of events. If
-- Add_Event_Listener is overridden, then this should be overridden to
-- remove the additional specific events. An overriding implementation must
-- call this last.
procedure Remove_Event_Listeners( this : access Game );
-- Sets game session variable 'var' to integer 'val'. A Game_Var_Changed
-- event is queued.
procedure Set_Game_Var( this : not null access Game'Class;
var : String;
val : Integer );
pragma Precondition( var'Length > 0 );
-- Sets game session variable 'var' to boolean 'val'. A Game_Var_Changed
-- event is queued.
procedure Set_Game_Var( this : not null access Game'Class;
var : String;
val : Boolean );
pragma Precondition( var'Length > 0 );
-- Executes one frame of Game logic. Implement this procedure to perform
-- logic at the Game scope.
procedure Tick( this : access Game; time : Tick_Time ) is null;
----------------------------------------------------------------------------
-- A allocator for a concrete Game implementation.
type Allocator is access function return A_Game;
-- Registers the allocator function used by Create_Game to create an
-- instance of the appropriate concrete Game subclass. This should be called
-- at elaboration time.
procedure Register_Allocator( allocate : not null Allocator );
end Games;