About This Page
This document illustrates basic mechanisms and conventions in the game framework for RubyCocoa applications. This document is still under construction so be patient.
Assumption
I assume that you have some knowledge about Ruby, RubyCocoa, and some basic things about creating Mac OS X applications. You don't have to know a lot about Objective-C or C.
Note
This document was written for 0.3.8 so there are some difference from the current version (0.4.0). Major changes that you should know are:
- deprecated RubyCocoa syntax (see RubyCocoa Deprecated Stuff for more info)
- Fixed method names (centerized -> centered)
Table of Contents
- What is The Game Framework
- Structure of a Game
- States in a Game
- Event Handling
- Models and Views
- Mapping States, Models, and Views
- Utility Classes and Modules
- Class references
Download
Xcode 2.4 project template is available.
The game framework is an easy game-creating environment that is intended to help developers make small games that run on MiniKidsGames in a short time. The game framework provides frequently used code such as creating the main window, switching between full screen mode and windowed mode, scanning multiple key statuses, and lots more.
Most part of the framework is written in Ruby as it uses RubyCocoa. This enables you to write a game in Ruby, which eases creating a game compared to doing so in Objective-C.
How does the game framework help you
Out in the box
The game framework provides an Xcode project template and a Ruby file template. You don't have to create a new Xcode project from scratch. Once you create a new Xcode project with the template, you already get a ready-to-make-your-game running application. You can create your own game right after creating a new project.
Hard work is done
The game framework provides a lifecycle of a simple game. The game framework itself is a running application, which means that most of the basic code for an application is already written. You don't have to write any lines of code for creating a window, switching to full-screen mode, etc. This enables you to concentrate on writing only the code for your games.
Game Template - halfway done
The framework comes with a game template as an Xcode file template. This template contains about 100 lines of ruby code that is a skeleton of a game. It runs as a game that does nothing but shows a message. All you have to do is: 1) Add a new file with the Xcode file template, and 2) write what you want by modifying the file.
Simple and Organized structure
The game framework gives you the basic structure of a game, which is based on both the MVC pattern and the State pattern. These patterns help you write some code in a consistent fashion. Are these patterns beyond your knowledge? Don't worry. The basic part of these patterns is already implemented in the template.
Game Tutorial - your good friend to tell you how
The game framework also provides a tutorial for making a simple game. This tutorial illustrates how to create a simple game by using the game framework. See Mini Game Tutorial for more details.
If you are not familiar with RubyCocoa, read the tutorial, and get some knowledge in writing a game on your Mac. It is a good starting point. Then, you may come back here to elaborate your game.
What the game framework provides
The game framework itself is a running application. it contains:
- Xcode project files (for Xcode version 2.4)
- framework source (*.rb)
- The main window routine (MiniGameWindow.rb)
- The main view routine (MiniGameView.rb)
- Controller (MiniGameController.rb)
- Window, View, and Menu (MainMenu.nib)
It also contains a variety of classes that eases developing a game, which includes:
- Event handling (Event.rb, TimerEvent.rb, KeyEvent.rb, MouseEvent.rb)
- Abstract View class (View.rb)
- Game State (State.rb)
- Preference access (Preferences.rb)
- Utility classes (Utility.rb)
What the framework does not provide
Unfortunately, the game framework does not provide any of sound files or graphic images that are essential for games. However, there is a lot of tools available on your Mac - GarageBand, Gimp, and lots more. Most of these tools are either bundled on your Mac or available for free. By using these tools, you can create sounds, music loops, and images that you want.
The basic structure of a game is based on both MVC pattern and State pattern. First, this chapter illustrates the patterns used in the framework. Second, it shows the basic structures and behaviors of a game.
Patterns in the game framework
MVC pattern
The MVC pattern is a classic architecture pattern that is frequently used for separating data from their presentation. MVC stands for Model, View, and Controller. The basic concept of the MVC pattern is to separate roles of your application into three different categories - Model, View, and Controller. See Pattern Oriented Software Architecture for more details. You can also see on-line resources such as http://www.enode.com/x/markup/tutorial/mvc.html and http://ootips.org/mvc-pattern.html.
Differences between pure MVC and the one in the game framework
As the game framework actively separates Model and View, there is no means for Models to know their relevant Views. The Controller in MVC automatically requests an update to a View when a model manipulates its data.

State pattern
The State pattern, introduced in [[Design Patterns>]] by GoF, changes a behavior of a model for the same event or method call, depending on a situation.
In a game, for example, pressing the space key in different situations makes different results. It may fires a cannon while playing, and it may change the user preferences while changing configuration. When a certain condition becomes true, the current state transits to another state so the game can change its behavior.
In the game framework, there are one or more states in your game. The Controller in MVC, which is hidden in the framework, delegates events to the current state. The current state, then, manipulates a Model. When the current state finishes its process, the Controller updates a View that is relevant to the Model.

The structure of a game
The game template provides a subclass of a View, a State, and a Model. The subclass of Game contains the sets of these three classes just like a game package for mapping these classes. The Controller is already implemented in the game framework so you don't have to implement it. This chapter explains the structures and behaviors of State, Model, and View in this order.

Typical Scenario in a game
The typical scenario in a game is shown as the figure below. When an event occurs, the Controller delegates it to the current state. The current state, then, manipulates a Model by invoking a method related to the event. After the manipulation is finished, the Controller requests a View to update the drawing rectangle by invoking View.drawRect(). The View asks its relevant Model to obtain the data for drawing the world of the game.

See also State class and View class for more detail information about these classes.
State at a glance - a context based Model manipulator
Typical scenario
As stated in the previous section, the current state class receives an event from the Controller. It, then, invokes a method in a Model to manipulate data inside the Model. When a certain condition becomes true, the state transit to another.
Roles
As a bridge between the Controller and a Model, the State class has five basic roles:
- Registers event handlers
- for the events that you want to receive
- Generates timers
- if needed
- Manipulates its relevant Model object
- when an event occurs
- Transits to another state
- when a certain condition becomes true
- Cleans up event handlers and timers
- before it transits to another state
Important Methods in State
There are two important methods in State - enter and leave. The enter method is invoked when entering a state, and the leave method is invoked at the time the current state is being changed. The enter method implements the first two roles of State, which are shown above, and the leave method implements the last one. Other roles of State should be implemented in event handlers or in the methods that are invoked from the event handlers.
Implementation
The subclass of State in the game template is implemented as shown below.
class NewGamePlayingState < State
# define your timer IDs here
NEWGAME_TIMER = 1000
def enter()
super()
@model.init()
# Define context dependent event handlers (event context)
# Each context is defined in a form of [EventType, Content, Proc object]
# See KeyEvent.rb, MouseEvent.rb and TimerEvent.rb for event specific info.
# Other game's source code would also help you
contexts = [[TimerEvent::Fired, NEWGAME_TIMER, proc {|id| tick() }]]
contexts.each {|context| EventContext.addContext(*context) }
@timer = TimerEvent.new(0.1, true, NEWGAME_TIMER)
end
# Timer event handler
def tick()
# do something when a timer event occurs
return true
end
end
Behaviors of State
This section illustrates the basic behaviors of State.
Entering a state
When the current state is changed from one state to another, State.enter is invoked. Each subclass of State needs to initialize the state at the method. Typical initialization process is:
- call super.enter()
to register common event handlers - add event handlers
by using EventContext.addContexts (See EventContext class reference) - generate timers if needed
- call @model.init if needed
State.enter is defined as follows:
def enter()
contexts = [[OSX::NSKeyDown, [KeyEvent::KEY_Q, KeyEvent::WITH_CONTROL], proc{|event| quit(); true}]]
EventContext.setContexts(contexts)
end
This method registers the common event handler (called the common event context) among all the states in a game. See Event Handlings? for farther information about event contexts.
Manipulating a Model
A State object manipulates its relevant Model when it receives an event through its event handlers and / or event contexts. The following event handlers are defined in State (actually in its mix-in EventHandler module):
- Key Event Handlers
- keyDown
- keyUp
- Mouse Event Handlers
- leftMouseDown
- leftMouseUp
- rightMouseDown
- rightMouseUp
- mouseMoved
- leftMouseDragged
- rightMouseDragged
- mouseEntered
- mouseExited
- Timer Event Handler
- tick
These methods do nothing but return false. You need to override some of these methods to handle the events that you need. Each event handler must return either true or false. The return value of these methods means the necessity of updating its relevant View. View.drawRect will be called if an event handler returns true.
Another way to receive events is using event context, a pair of a concrete event and an action for the event. See Event Handlings? for farther information about handling events.
An event handler, including an action in an event context, manipulates its relevant Model object by invoking some methods that are defined in the Model class. Each State object can access its relevant Model object by referring to its instance variable @model that is set by the game framework.
Transiting to another state
When a certain condition becomes true as a result of manipulating a Model in an event handler, a state transits to another. A state transition is triggered by invoking changeState(klass). The argument "klass" is a subclass of State. Invoking changeState(TankGamePlayingState), for example, at one of the event handlers in TankGamePlaingState makes a transition to TankGamePlayingState.
Leaving a state
When a state is about to transit, State.leave is called. This method cleans up all event handlers and event contexts, as well as invalidating timers if needed. Fortunately, State.leave does most of this clean-up for you. This means that you don't have to write leave methods in most of State's subclasses. You need to write a leave method only if you want to do something more than that is written in State.leave as shown below.
def leave()
if (defined?(@timer) && @timer && defined?(@timer.invalidate))
@timer.invalidate()
@timer = nil
end
EventContext.setContexts([])
end
Quitting a game
When a user attempts to quit a game by pressing Ctrl-Q, the current state must be set to TitleSelectingState, which means it returns to the main title. As the event context for this event and the quit method are already implemented in State, you don't have to write the same code in your game. It's enough to call super.enter() at the beginning of enter methods in a subclass of State.
State transition among games
When you launch an application, the current state is set to TitleSelectingState in MainTitle.rb. Selecting a game by pressing the space key changes the current state to the initial state of the selected game. The initial state is defined in a subclass of Game. Take a look at the definition of TypinToddler class.
class TypinToddler < Game
def initialize()
@bindings = [[TypinToddlerReadyState, TypinToddlerModel, TypinToddlerView],
[TypinToddlerPlayingState, TypinToddlerModel, TypinToddlerView],
[TypinToddlerWaitingState, TypinToddlerModel, TypinToddlerView]]
@initialState = TypinToddlerReadyState
end
def self.title() "Typin' Toddler" end
def self.titleImage() "TypinToddler" end
end
There is an instance variable @initialState. When Typin' Toddler game is selected at main title, MainTitle requests the initial state from the TypinToddler class. the TitleSelectingState object in MainTitle, then, invokes changeState(@initialState).
Technically, MainTitle is a kind of game, but no games other than MainTitle are allowed to transit into a state in other games. To quit a game, simply invoke quit() at a subclass of State.
There are three kinds of events in the game framework - KeyEvent, MouseEvent, and TimerEvent. These classes encapsulate events that are defined in Cocoa so that the game framework can delegate these events to the current state if required. This chapter illustrates how to handle these events in your game, as well as registering and unregistering event handlers.
Event handing in the game framework
As mentioned in the previous chapter, a game receives events in subclasses of State. There are two different ways to handle events in these classes: 1) by using default event handlers, and 2) by using EventContext.
Using Default Event Handlers
As same as Cocoa applications, there are default event handlers as listed below.
- Key Event Handlers
- keyDown(event)
- keyUp(event)
- Mouse Event Handlers
- leftMouseDown(event)
- leftMouseUp(event)
- rightMouseDown(event)
- rightMouseUp(event)
- mouseMoved(event)
- leftMouseDragged(event)
- rightMouseDragged(event)
- mouseEntered(event)
- mouseExited(event)
- Timer Event Handler
- tick(object)
All the handlers except tick take an NSEvent object as an argument (tick takes a timer ID).
To receive an event in a subclass of State, overrides the default event handlers in the subclass. Unlike writing a subclass of NSView in Ruby, you don't have to write ns_overrides for these methods since State is a pure ruby class (FYI, RubyCocoa in cvs doesn't require ns_overrides any more as of Sep/10/2006). You also don't have to be worried about NSResponder related stuff. The game framework does these things for you.
To Receive the NSKeyDown events where its key code is either KeyEvent::SPACE or KeyEvent::KEY_A, for example, you may write the code like this in a subclass of State:
def enter()
super.enter() # registers some common event handlers
# do some other initialization if any
end
def keyDown(event)
if (event.keyCode == KeyEvent::SPACE)
# do something
elsif (event.keyCode == KeyEvent::KEY_A)
# do something
end
return false # return true if it needs to update a View
end
For your convenience, KeyEvent defines all the key codes (such as KeyEvent::SPACE and KeyEvent::KEY_A). See KeyEvent class reference for available key code constants.
Receiving an event through the default event handlers is similar to that in Cocoa applications. See NSEvent and NSTimer class references for more details about these events. You can also refer to the following class references of the game framework.
Using Event Context
The event context, another kind of event handler, is a pair of a concrete event that you want to receive, and an action for the event. To receive a concrete event through the game framework, you need to register an event context by using either EventContext.setContexts or EventContext.addContext, typically at the enter method in a subclass of State.
If you want to receive a space key event, for example, to launch a missile, write the following code at the enter method of a subclass of State:
EventContext.addContext(NSKeyDown,
KeyEvent::SPACE,
proc { |event| @model.launch(); false })
The first two arguments, NSKeyDown and KeyEvent::SPACE, specify a concrete event that you want to receive. The third argument, a Ruby Proc object { |event| @model.launch(); false }, specifies an action for the event. (this is like an unnamed method that takes event as an argument.) The false at the end of the Ruby proc returns false to the game framework, which means there is no need to update the relevant view. Returning true here makes the framework invoke View.drawRect.
There are some default event contexts (such as Ctrl-Q key to quit the game) that are defined in State.enter (super class's method). If you want to use the default event contexts, use EventContext.addContext to add one or more contexts besides the common event contexts. If you want to use only your event contexts, use EventContext.setContexts. This method overrides all predefined event contexts.
Priority between EventContext and Default Event Handlers
When an event occurs, an Event object (e.g. KeyEvent) asks EventContext if there is a registered event context that matches the event. If matched, the Event object invokes the Ruby proc that is designated in the matched event context. If there is no matched context, the Event object tries to invoke its default event handler (e.g. keyDown for key events, or tick for timer events).
EventContext vs. Default Event Handlers
Though both EventContext and Default Event Handlers do similar things, there are some differences between these. I show you pros and cons of those two different means of handling events so that you can choose the right one depending on a situation.
Pros of EventContext
No need to write if - else / switch statements in an event handler
As EventContext directly maps a specific event to an action, you don't have to write "if - else" or "switch" statements only to find which specific event is received(e.g. which key is pressed). Take a look at the code:
contexts =
[[NSKeyDown, KeyEvent::SPACE, proc {|event| @model.launchMissile(); false}],
[NSKeyDown, KeyEvent::LEFT_ARROW, proc {|event| @model.moveLeft(); false}],
[NSKeyDown, KeyEvent::RIGHT_ARROW, proc {|event| @model.moveRight(); false}],
[NSKeyDown, KeyEvent::UP_ARROW, proc {|event| @model.moveUp(); false}],
[NSKeyDown, KeyEvent::DOWN_ARROW, proc {|event| @model.moveDown(); false}]]
contexts.each {|context| EventContext.addContext(*context)}
This technique can get rid of "if - else" statements out of an event handler. Unlike using EventContext, a default event handler receives all events that are related to it. The keyDown handler for the events at the example above will be like this:
def keyDown(event)
if (event.keyCode == KeyEvent::SPACE)
@model.fire()
elsif (event.keyCode == KeyEvent::LEFT_ARROW)
@model.moveLeft()
elsif (event.keyCode == KeyEvent::RIGHT_ARROW)
@model.moveRight()
elsif (event.keyCode == KeyEvent::UP_ARROW)
@model.moveUp()
elsif (event.keyCode == KeyEvent::DOWN_ARROW)
@model.moveDown()
end
return false
end
No need to write an event handler in some cases
In the code above, you don't have to write an event handler because the Proc object in the event context directly manipulates a Model. This improves the performance a little bit compared to using keyDown method since the game framework invokes @model.xxxxx directly whereas keyDown indirectly invokes @model.xxxxx from the handler (the framework invokes keyDown, and then, keyDown invokes @model.xxxx ).
Easier to write a common action among states for a certain event
If there is more than one state in your game, these might have some common actions for a specific event. TankGame in Mini Game Tutorial, for example, has three states - TankGamePlayingState, TankGameStartState, and TankGameOverState.
These three states share a common action quit in respond to a "Control-Q" key event. In this case, their super class (State) registers the event context that specifies the action for the event. This prevents developers from writing the same code at these three classes.
In TankGame, this common event context is registered at State.enter as it is shared among all the states in MiniKidsGames. To share such a common event context other than quit within your game, make a subclass of State, say SharedActionHolder, to register a common event context at its enter method. Each subclass of SharedActionHolder calls super.enter() to register the common event context. And then, add state specific event contexts by using EventContext.addContext at the enter methods in those classes respectively.
Cons of EventContext
- Need to add or set event contexts before you use these
- Incompatible with other Cocoa applications
- A little overkill for mouse events
- since mouse event handlers are very concrete. (e.g. you don't have to check what button is pressed.)
Pros of Default Event Handlers
- No need to register event handlers.
- Easier to handle different key events in the same way
e.g. drawing a character on a window for key events - Compatible with other Cocoa applications
Cons of Default Event Handlers
Cons of default event handlers are the reflection of Pros of EventContext.
- Need to write "if - else" or "switch" statements for handling different key events in different ways
- A common action for a certain event among states might be embedded in all the states.
Which way should you use?
It totally depends on a situation. As a matter of fact, mixing these two methods sometimes makes your code simpler and efficient. Here are some criteria to help you choose one of these.
- Prefer using EventContext:
- when there are some common actions for a certain event among states
- when you use more than one timer at a state
- if you don't want to write "if - else" or "switch" statements for keyDown events
- Prefer using Default Event Handlers:
- for mouse events
- for sharing an action among event handlers
- Use alias :rightMouseDown :leftMouseDown when an action for leftMouseDown and rightMouseDown are the same
Differences between the game framework and Cocoa
There are three differences between these in terms of handling events.
Model - The world of a game
A Model represents the data that are needed to play a game. A shooting game, for example, may have a fighter, enemies, missiles, and maps of stages. It may also contain the number of fighters, difficulties (level), and rules of the game. These data are stored in a Model.
While a user is playing a game, the characters in the world of your game should move. A fighter and the enemies move around the window. The user will fire some missiles to attack his enemies. A fighter will be destroyed when an enemy hits it. One or a few Models in a game represent all these movements and actions.
Roles of Model
- Creates and delete the characters in a game (fighters, enemies, etc..)
- Manipulates the characters (moves, launches, etc)
- Possesses all the characters in a game
- Provides the data for the characters (or the objects of characters)
- so a View can draw these objects
How a State manipulates a Model
When the current State object receives an event such as a key event and a timer, it manipulates a Model by invoking some method. This means that a Model must provide the methods so the State object can manipulate it. Possible method names for a shooting game are:
- moveFighter (for key events)
- launch (for a key event)
- moveEnemies (for timer events)
Unlike methods in a State, you should not use tick or keyDown for the names of the methods in a Model since these names are very unclear for data manipulation methods. It's always good to use concrete names for method names so that other developers can easily understand what a model does in those methods.
Only several rules
There is no super class for a model. However, a Model needs to have a method named init. This method is invoked:
- when a game is selected at the main window
- when a State needs to initialize the Model at its enter method.
Other than this method, you may write whatever you want in a Model as long as you keep the following rules:
- Do not draw anything
- Do not play sounds
- Do not call methods in a View
- Do not call methods in a State
- Do not quit a game
That's it. You might have many questions about writing your own Model classes, take a look at the code of the games that are included in MiniKidsGames.
View - Present the world
A View draws all the worlds in a Model, depending on a situation. When a user is playing a game, a View draws a fighter, enemies and background images. It obtains the data from its relevant Model through the methods that the Model provides.
Roles of View
The roles of View are very obvious, it:
- Present the data in one or more Models
- by drawing something on the window
- Play sounds
- Approve a state transition
- A view can delay a state transition if it needs to do something before the transition
such as drawing an animation
- A view can delay a state transition if it needs to do something before the transition
Important methods in a View class
Though some methods are defined in View, the super class of all View classes, all you have to care is the following three methods:
- drawRect()
- notifyStateWillChange(state)
- notifyStateDidChange()
The drawRect method, which is invoked after every event process, draws the world of your game. In the drawRect method, you will draw the window by requesting the data from its relevant Model. The relevant Model object is assigned as an instance variable @model.
The notifyStateWillChange method is invoked when the current state attempts to make a state transition. View.notifyStateWillChange invokes state.approveStateChange so that the state can actually make a transition. Overriding this method in a subclass enables the class to clean up some data in it.
Leaving this method without invoking state.approveStateChange can delay a state transition. Typical use of this delay is drawing some animation in between the state transition. When a View finishes animation, it invokes state.approveStateChange at drawRect method.
The notifyStateDidChange is invoked when a state is changed. Overriding this method enables a subclass of View to initialize some data. It also gives a subclass to detect the state transition when it is related to more than one subclass of State. Typical uses of this method are:
- creating and/or playing sound objects
- creating image objects
- initializing other objects that help in drawing.
- switching drawing routines depending on the current state.
See View class reference for more detail.
This section illustrates the mappings among Views, Models, and States.
Mapping in a Game class
A subclass of the Game class possesses Views, Models, and States. It also maps these classes. The following code in the game template shows how these classes are mapped in the class.
class NewGame < Game
def initialize()
@bindings = [[NewGamePlayingState, NewGameModel, NewGameView]]
@initialState = NewGamePlayingState
end
def self.title() "NewGame" end
def self.titleImage() nil end
end
The instance variable @bindings has a double Array object. Each content of the Array object contains a State class, a Model class, and a View class in this order. When a game is selected at the main title, the framework sets a Model object to both a View object and a State object. For example, both an object of NewGameState and an object of NewGameView have an instance variable @model that represents an objects of NewGameModel.
Mappings for a game that has multiple states
If there are more than one State classes that are related to the same pair of a Model object and a View object, @binding would be as follows:
@bindings = [[FirstState, MyGameModel, MyGameView],
[SecondState, MyGameModel, MyGameView],
[ThirdState, MyGameModel, MyGameView]]
The framework will create a MyGameModel object, a MyGameView object, and three State objects. It, then, maps each State object to the MyGameModel. It also maps the MyGameView objects to the MyGameModel object. As a result, each @model in the subclasses of State has the MyGameModel object. The @model in the MyGameView object is also set to the MyGameModel.
Utility classes and modules for Views
BGM class
eases playing music loops without a little gap between loops by using QTMovie. See BGM class reference.
SimpleSpeech module
provides speech capability. This module uses Speech Synthesizer to speak a given text string. See SimpleSpeech module reference.
ShadowMaker module
eases making drop shadows beneath drawing objects in the window. See ShadowMaker module reference. Though drawing shadow makes your game look richer, it might become a performance bottleneck. Be aware when you make a performance-aware game.
TextMaker module
eases drawing a text string by using the default font. See TextMaker module reference.
Utility classes for Views and Models
Field class
eases to calculate the points and size for the characters in a Model. Even though a Model doesn’t draw anything on the window, it must set the position of the characters in a game. Therefore, this class provides the size of the window without accessing View classes.
It provides a method bounds that returns an NSRect object. There are some more useful methods that help both Models and Views to calculate the position of an drawing object. See Field class reference for more information.
Essential Classes
- Event class
- EventContext class
- Game class
- View class
- KeyEvent class
- MouseEvent class
- Preferences class
- State class
- TimerEvent class
Utility Classes
For View
For both View and Model
Utility Modules for View
These modules are included in View.
Description
The Event class is a super class of KeyEvent, MouseEvent, and TimerEvent. This class implements the common routine among sub classes. Game developers must not instantiate this class directly.
Methods
Instance Methods
deliver
delegates an event to the current State object.
Description
The EventContext class connects a specific event to an action.
Methods
Class methods
setContexts
Registers maps between concrete events and their actions respectively. Registered maps so far will be removed.
- contexts
- An Array object that contains a set of event type, event content, and an Proc object that represents an action for the event. See Note for a content of the Array object. specifying an empty array object removes all contexts that are defined so far.
[ [eventType, content, action], [eventType, content, action], ... ]
See addContext for more details about each element in a content of the array object.
addContext
Add a map between concrete events and their actions respectively. Registered maps are not removed.
- eventType
- One of the event type. See Note for available event types
- content
- A concrete content of an event (e.g. KeyEvent::SPACE). See KeyEvent class, MouseEvent class, TimerEvent class for available contents.
- action
- A ruby Proc object that represents an action for the event that are specified by eventType and content.
- NSKeyDown
- NSKeyUp
- NSLeftMouseDown
- NSLeftMouseUp
- NSRightMouseDown
- NSRightMouseUp
- NSMouseMoved
- NSLeftMouseDragged
- NSRightMouseDragged
- NSMouseEntered
- NSMouseExited
- TimerEvent::Fired
Example usage of this method would be:
addContext(NSKeyDown, KeyEvent::SPACE, {|event| fire(); }
This means when a space key event occurs, fire() in the subclass of State, which invoked this method, is called. For timer event, an NSObject is being passed as an argument of a ruby proc object.
Constants
| name | meaning | how to use |
| ANY_CONTENT | shows the action receives any content for a given eventType | specify it as a content for addContext or setContexts |
Description
The Game class provides the basic information about a game. It also contains a binding information among State, Model, and View classes in a game.
Method list
Class Methods
title
Returns a string that represents the title of a game.
&aname(titleImage)
titleImage
returns a text that represents the path for the title image of a game.
Instance Methods
initialize
Initializes an Game object
@bindings = [[TypinToddlerPlayingState, TypinToddlerModel, TypinToddlerView]]
Each subclass must also set the initial state class to @initialState at its initialize method. See initialState for more details.
initialState
returns the initial state of a game.
Description
View class is an abstract class for View classes in all the games. Each game has at least one subclass of this class. Instantiating this class by a game is forbidden.
- Derived from: NSObject
Method list
Class Methods
instance
returns an instance for View.
class MyView < View # do something end MyView.instance
Game developers, however, must not use this method to obtain the unique instance of these classes because all instances of View and its subclasses are possessed by the game framework.
The game framework instantiates these classes either by invoking this method or by invoking alloc.init (Remember, this class is derived from NSObject). This means that obtaining an instance via this method does not always guarantee that you will get the same instance the game framework possesses.
Instance Methods
drawRect
invoked after an event is processed by an event handler. A subclass of View must implement this method to draw the window to present the content of a Model.
The following code will show a text message that is obtained by invoking @model.message at the point (100, 100) with given size and color.
def drawRect NSColor.blackColor.set NSRectFill(@bounds) drawText(@model.message, @model.size, color, NSPoint.new(100, 100)) end
notifyStateDidChange
invoked when a state attempts to change the current state by calling State.changeState.
notifyStateWillChange
invoked when a state attempts to change the current state by calling State.changeState.
- state
- An State object that represents the current state
This method give a View object a chance to delay a state transition until State.approveStateChange() is called. It enables game developers to do something before the state transition (e.g. cleaning up data in a View object, making animation before the transition).
As this method invokes state.approveStateChange() by default, a subclass of View should override this method to do something before a state transition. In this case, the subclass must invoke state.approveStateChange() to make the transition occurs.
See MainTitle.rb for more information about the usage of this method, as well as State.approveStateChange.
setModel
invoked by the game framework to set a Model object that is related to a View object.
- model
- A Model object
class MyView < View
def setModel(model)
super(model)
# do something
end
...
end
Description
The KeyEvent class encapsulates key related portion of Cocoa's NSEvent. The game framework generates an object of this class when a user presses or releases a key. The framework, then, invokes deliver() to send an event to the current state.
- Derived from: Event class
Method list
Class Methods
initWithEvent
initializes a KeyEvent object with a given NSEvent object.
- event
- an NSEvent object
keyStatus
# within a subclass of State def tick(object = nil) keyStatus = KeyEvent.getStatus() @model.moveLeft() if (keyStatus.include?(KeyEvent::LEFT_ARROW)) @model.moveRight() if (keyStatus.include?(KeyEvent::RIGHT_ARROW)) @model.moveUp() if (keyStatus.include?(KeyEvent::UP_ARROW)) @model.moveDown() if (keyStatus.include?(KeyEvent::DOWN_ARROW)) @model.launch() if (keyStatus.include?(KeyEvent::SPACE)) end
If you invoke this method from a key event handler (e.g. keyDown) in a State object, you may experience that sometimes a drawing object in a game doesn't move for about a second even you keep pressing a key. This happens because keyStatus is checked only when a key is pressed (or key-repeat event occurs). This is why you should call this method from a timer handler instead of key event handlers.
Instance Methods
deliver
delivers an key event to either key event handler or an action that is designated by an event context.
Constants
Key Codes
Available key codes are listed below:
- ANY_KEY - used only by EventContext to specify an action will receive any key events
- BACKSLASH
- CHILDER
- COLON
- COMMA
- DELETE
- DOWN_ARROW
- ENTER
- EQUAL
- ESCAPE
- KEY_[0-9]
- KEY_[A-Z]
- KEY_F[0-12]
- LEFT_ARROW
- LEFT_BRACE
- PERIOD
- RETURN
- RIGHT_ARROW
- RIGHT_BRACE
- SEMICOLON
- SLASH
- SPACE
- UNDERSCORE
- UP_ARROW
Key Modifiers
Available key modifiers are listed below.
- WITH_COMMAND
- WITH_CONTROL
- WITH_OPTION
- WITH_SHIFT
Description
The MouseEvent class encapsulates mouse related portion of Cocoa's NSEvent. The game framework generates an object of this class when a user takes a certain mouse action. The framework, then, invokes deliver() to send an event to the current state.
- Derived from: Event
Method list
Class Methods
initWithEvent
initializes a MouseEvent object with a given NSEvent object.
- event
- an NSEvent object
Instance Methods
deliver
delivers a mouse event to either mouse event handler or an action that is designated by an event context. This method is invoked by the framework when a user takes a certain mouse action.
Description
The Preferences class encapsulates Cocoa's NSUserDefaults to ease accessing the preference information (e.g. ~/Library/Preferences/MiniKidsGames.plist). As the Preference automatically creates and select a dictionary (pairs of a key and a value) for the current game, game developers can access any preference data for the current game without creating or selecting a dictionary.
- Includes: Singleton
Method list
Class Methods
setValue
adds a given pair to the dictionary that contains the preference data for the current game.
- key
- A String object that contains the key for value
- value
- The value for key. Available classes for the value are one of String, Integer, Bool, Float, or Array of NSDictionary objects.
You may use setGlobalValue to add a shared pair among all games.
valueForKey
returns the value associated with a given key in the dictionary for the current game.
- key
- A String object that contains the key for which to return the corresponding value.
- to_i (Integer and Boolean)
- to_f (Float)
- to_a (Array)
- to_s (String)
This method invokes NSDictionary.valueForKey. This method can properly obtain a value that is associated by setValue even if flush is not invoked.
There is no means of obtaining a value for other games than the current game because this method access only the dictionary for the current running game. You may use globalValueForKey and setGlobalValue to access the shared preference data among all games.
Instance Methods
flush
Write the data into the preference file (e.g. MiniKidsGames.plist)
globalValueForKey
returns the value associated with a given key in the dictionary for the application.
- key
- A String object that contains the key for which to return the corresponding value.
- to_i (Integer and Boolean)
- to_f (Float)
- to_a (Array)
- to_s (String)
This method invokes NSDictionary.valueForKey. This method can properly obtain a value that is associated by setGlobalValue even if flush is not invoked.
You should use valueForKey to obtain per-game preference data.
init
invoked when the application is launched. This method initializes the preference data by reading the preference data from the preference file for your application.
setCurrentGame
- game
- An object of Game's subclass.
setGlobalValue
- key
- A String object that contains the key for value
- value
- The value for key. Available classes for the value are one of String, Integer, Bool, Float, or Array of NSDictionary objects.
You should use setValue to add a per-game pair.
Description
The State class is an abstract class of state classes in all the games. Each game has at least one subclass of this class. Instantiating this class by a game is forbidden.
- Includes: EventHandler module
Method list
Class Methods
finalize
invoked by the framework when a user attempts to quit the application. This method calls the leave method of the current state.
getState
returns an object of the current state
setState
sets a given state class as the current state
- state
- A subclass of State that is to be the current state
Instance Methods
approveStateChange
approves the scheduled state transition.
changeState
- state
- A subclass of State. It must be a class, not an object.
setModel
invoked by the game framework to set a Model object that is related to a State object.
- model
- A Model object
Description
The TimerEvent class encapsulates Cocoa's NSTimer. Unlike KeyEvent or MouseEvent, an object of this class is instantiated by a game (typically by a State object). When a timer fires, TimerEvent.deliver is invoked by Cocoa. A TimerEvent object, then, invokes either an action that is registered in an event context or the timer event handler (State.tick) of the current state.
- Derived from: Event class
Method list
Class Methods
initialize
initializes a new TimerEvent object with a given parameters.
- interval
- A Float value that represents a time interval before firing a timer event (in seconds)
- repeated
- true for periodical timer, otherwise false
- id
- an integer that represents the unique ID within a game
releaseOldTimers
invalidates NSTimer objects that are not used any more.
- timer
- An NSTimer object that a TimerEvent contains. Specify nil when invoking this method at the time a user attempts to quit the application.
Instance Methods
deliver
invoked by NSTimer when designated time interval elapsed.
- timer
- An NSTimer object
- an action (ruby Proc object) in the event context if timer ID matches.
- the tick method of the current state if defined. Unlike other Event objects in the game framework, TimerEvent.deliver passes its timer ID to these event handlers.
invalidate
delivers a timer event to either timer event handler or an action that is designated by an event context. This method is invoked by an NSTimer object.
When a timer event other than marked one occurs after invoking this method, the deliver method in this class invokes releaseOldTimers? to invalidate the marked timers.
Constants
- Fired - used by EventContext.setContexts / addContext to specify an event type (TimerEvent::Fired)
Description
The BGM class encapsulates QTMovie class to provide an easy way to play sound loops. Though NSSound is a powerful class to play various sounds, it doesn't play sound loops without a gap between loops. The BGM class provides a solution for this problem. it can play sound loops without gaps (not perfectly but way much better than NSSound).
Method List
Instance Methods
initWithFile
initializes an BGM object with a given file name.
- file
- An String object that represents a full-path to a sound file. Available sound format are AAC, AIFF, MP3, WAV, and any other format that QuickTime can handle.
@sound = BGM.alloc.initWithFile("/User/me/somesound.m4a");
initWithName
initializes an BGM object with a given file that is stored in an application's resource folder.
- name
- An String object that represents a filename of a sound file. The filename should be a base name of a file (e.g. somesound.aiff).
isPlaying
returns if a sound is playing.
@sound.stop if (@sound.isPlaying.to_i == 1)
pause
pauses a playing sound
play
plays a sound from the beginning.
resume
resume playing a sound.