game.ss provides some useful types and functions that remove much of the design work needed to create real-time games. Normally these games follow the same basic structure: execute a function to update the universe, draw the universe. The mechanism to do this is what game-loop gives you, but game.ss takes this a step further by providing the universe as well. All you must do is populate the universe with objects and you will have an instant game.

Of course with any framework game.ss forces you to follow one design. If you feel that this design is not what you need then roll your own. Once you understand how game.ss works its not terribly difficult to write a different version.

Look at "examples/simple.ss" in allegro.plt for a concrete example of how to use the game framework.

Basic is the root object of all objects in the game universe. Technically it is a class as defined by class* in class.ss but for the most part you can ignore this if you are just using whats in game.ss. Basic has the following methods

Fieldsphase - Affects the order of drawing. Lower numbers are drawn first and higher numbers are drawn later. This defaults to 0.x - The x coordinate of this object. This is used for collision detection so do not provide your own x coordinate in your own objects.y - The y coordinate, with the same restrictions as x.

Functions

procedure: (can-collideobj) ::boolean

Returns #t if this object can collide with obj.

procedure: (shapes) ::list-ofshape

Returns a list of shapes used for collision detection. An empty list means this object can't collide with anything and its can-collide method should probably return #f for all objects.

procedure: (keyworldkeys) ::void

This procedure is run when the user presses a key. keys is a list of currently pressed keys and world is the current universe.

procedure: (touchworldobj) ::void

This object collided with obj and can now perform any side-affects.

procedure: (tickworld) ::void

The main update procedure. This procedure is run by the universe when a logic cycle is occuring. Moving around the universe should be done here.

procedure: (drawworldbuffer) ::void

This procedure is run when the object is allowed to draw itself. buffer is a a plain image( not the screen ).

World is a special class that represents the universe. It derives from Basic. Normally you don't need to know about much of the internals of World but you would if you aren't using the predefined game-loop that is part of game.ss.

Functions

procedure: (get-width) ::number

Returns the current viewable width of the world.

procedure: (get-height) ::number

Returns the current viewable height of the world.

procedure: (get-depth) ::number

Returns the current bits per pixel used to display the world.

procedure: (get-mode) ::symbol

Returns either 'WINDOWED or 'FULLSCREEN representing what sort of graphics mode the world is using to be displayed.

procedure: (keykeys) ::void

Let all the objects know about keys through the key method.

procedure: (addobj) ::void

Add an object to the internal list of objects.

procedure: (tick) ::void

Call tick on all the objects.

procedure: (drawbuffer) ::void

Call draw on all the objects.

procedure: (removeobj) ::void

Remove obj from the internal list of objects. All other objects in the list will receive the death message if they have it defined.

procedure: (remove-all) ::void

Clear the list of internal objects.

procedure: (get-objects) ::list-ofBasic

Returns the internal list of objects.

procedure: (get-objectpred) ::Basicor#f

pred:: (lambda (obj) ..)Return the first object that statisfies pred.

procedure: (reset-collision) ::void

Reset the collision detection objects.

procedure: (collide) ::void

Tests all objects for collisions using a binary space partition. Only objects that live in the same binary space partition and both return #t from can-collide will be tested for collisions.

shape^ is an interface that all shapes should implement. It has the following functions

procedure: (min-x) ::int - The left most x coordinate of this shape.procedure: (max-x) ::int - The right most x coordinate of this shape.procedure: (min-y) ::int - The top most y coordinate of this shape.procedure: (max-y) ::int - The bottom most y coordinate of this shape.procedure: (collidexyshapesxsy) ::boolean - Returns #t if this shape collides with shape. The middle coordinates of this shape are x and y. The middle coordinates of shape are sx and sy.procedure: (insidexysxsy) ::boolean - Returns #t if the coordinates sx, sy lies inside this shape centered at x, y.

Rectangle derives from Shape and represents a rectangular area in space. Its fields are width and height.

;; a rectangle with a width of 5 and a height of 10
(makeRectangle (width5) (height10))
;; a rectangle with a width of 5 and a height of 10 offset by 2, -3
(makeRectangle (width5) (height10) (center-x2) (center-y-3))

Create a new world. You can optionally give width, height, depth, and mode.

width - Width of the screen. Default is 640.height - Height of the screen. Default is 480.depth - Bits per pixel. Default is 16mode - 'WINDOWED or 'FULLSCREEN. Make a window or use the entire screen. Defaults to 'WINDOWED.

;; create a regular world
(defineworld (make-world))
;; use a window size of 800x600
(defineworld (make-world800600))

Define a new object that derives from Basic. You can use this syntax if you do not want to create a class by hand. (inherits ...) is a list of variables to inherit from Basic( x, y, and/or phase ). (vars ...) is a list of variables private to this object. body ... is any normal scheme expression.

To define methods use define. Methods that should override methods in Basic will be handled automatically as long as they are declared in the form (define (name ...) ...).

define-generator defines an object that derives from Basic like define-object except a generator's sole purpose in life is to execute a function every time a certain amount of time has passed by. This is useful for adding objects to the universe in descrete steps.

Ask obj to perform a method and pass args to it. This works like normal method invocation except if obj does not have a method named method or accepts a different number of args then no function will be called. This can be a source of confusion as no warning or error will be printed, the method will just be silently ignored.

Given a world object this method will create the graphics context and start the game. If given before is executed immediately before the main game loop is executed and after is executed after the game ends. These methods allow you to perform arbitrary initialization that you could not otherwise do before the start method is called. I.e, you cannot call an image related function before start becuase the graphics context does not exist yet.

;; define blue, but set it in the before method when it is ok to do so
(defineworld (make-world))
(defineblue#f)
(startworld (lambda (w) (set!blue (color00255))))