CHINGU

Ruby 1.9.2 is recommended. Should also work with 1.8.7+. Chingu development
is mostly conducted using Win7 / Ruby 1.9.2.

DESCRIPTION

OpenGL accelerated 2D game framework for Ruby. Builds on the awesome Gosu
(Ruby/C++) which provides all the core functionality. It adds simple yet
powerful game states, pretty input handling, deployment safe
asset-handling, a basic re-usable game object and automation of common
task.

INSTALL

geminstallchingu

QUICK START (TRY OUT THE EXAMPLES)

Chingu comes with 25+ examples demonstrating various parts of Chingu.
Please browse the examples-directory in the Chingu root directory. The
examples start out very simple. Watch out for instructions in the windows
titlebar. Could be how to move the onscreen player or how to move the
example forward. Usually it's arrowkeys and space. There's also
more complex examples, like a clone of Conways game of life (en.wikipedia.org/wiki/Conway%27s_Game_of_Life)
game_of_life.rb and example21_sidescroller_with_edit.rb where You can
switch between playing and editing the level itself.

… miss your Chingu project? Msg me on github and I'll add it to the
list!

THE STORY

The last years I've dabbled around a lot with game development.
I've developed games in both Rubygame and Gosu. I've looked at
gamebox. Rubygame is a very capable framework with a lot of functionality
(collision detection, very good event system etc). Gosu is way more
minimalistic but also faster with OpenGL -acceleration. Gosu isn't
likely to get much more complex since it does what it should do very well
and fast.

After 10+ game prototypes and some finished smaller games I started to see
patterns each time I started a new game. Making classes with
x/y/image/other-parameters that I called update/draw on in the main loop.
This became the basic Chingu::GameObject which encapsulates Gosus
“Image.draw_rot” and enables automatic updating/drawing through
“game_objects”.

There was always a huge big chunk of checking keyboard-events in the main
loop. Borrowing ideas from Rubygame this has now become
@player.keyboard(:left => :move_left, :space => :fire … etc.

CORE OVERVIEW

Chingu consists of the following core classes / concepts:

Chingu::Window

The main window, use it at you use Gosu::Window now. Calculates the
framerate, takes care of states, handles chingu-formated input, updates
and draws BasicGameObject / GameObjects automatically. Available throughout
your source as $window (Yes, that's the only global Chingu has). You
can also set various global settings. For example, self.factor=3, will make
all fortcomming GameObjects scale 3 times.

Chingu::GameObject

Use this for all your in game objects. The player, the enemies, the
bullets, the powerups, the loot laying around. It's very reusable and
doesn't contain any game-logic (that's up to you!). Only stuff to
put it on screen a certain way. If you do GameObject.create() instead of
new() Chingu will keep save the object in the “game_object”-list for
automatic updates/draws. GameObjects also have the nicer Chingu
input-mapping: @player.input = { :left => :move_left, :right =>
:move_right, :space => :fire} Has either Chingu::Window or a
Chingu::GameState as “parent”.

Chingu::BasicGameObject

For those who think GameObject is a too little fat, there's
BasicGameObject (GameObject inherits from BasicGameObject). BasicGameObject
is just an empty frame (no x,y,image accessors or draw-logic) for you to
build on. It can be extended with Chingus trait-system though. The
new() vs create() behavior of GameObject comes from BasicGameObject.
BasicGameObject#parent points to either $window or a game state and is
automatically set on creation time.

Chingu::GameStateManager

Keeps track of the game states. Implements a stack-based system with
push_game_state and pop_game_state.

Chingu::GameState

A “standalone game loop” that can be activated and deactivated to control
game flow. A game state is very much like a main gosu window. You define
update() and draw() in a gamestate. It comes with 2 extras that main window
doesn't have. #setup (called when activated) and #finalize (called when
deactivated)

If using game states, the flow of draw/update/button_up/button_down is:
Chingu::Window –> Chingu::GameStateManager –> Chingu::GameState. For
example, inside game state Menu you call push_game_state(Level). When Level
exists, it will go back to Menu.

Traits

Traits are extensions (or plugins if you so will) to BasicGameObjects
included on the class-level. The aim is so encapsulate common behavior into
modules for easy inclusion in your game classes. Making a trait is easy,
just an ordinary module with the methods setup_trait(), update_trait()
and/or draw_trait(). It currently has to be namespaced to Chingu::Traits
for “traits” to work inside GameObject-classes.

OTHER CLASSES / HELPERS

Chingu::Text

Makes use of Image#from_text more rubyish and powerful. In it's core,
another Chingu::GameObject + image genning with Image#from_text.

Chingu::Animation

Load and interact with tile-based animations. loop, bounce and access
invidual frame(s) easily. An “@image = @animation.next” in your
Player#update is usually enough to get you started!

Chingu::Parallax

A class for easy parallaxscrolling. Add layers with different damping, move
the camera to generate a new snapshot. See example3.rb for more. NOTE:
Doing Parallax.create when using a trait viewport will give bad results. If
you need parallax together with viewport do Parallax.new and then manually
doing parallax.update/draw.

Chingu::HighScoreList

A class to keep track of high scores, limit the list, automatic sorting on
score, save/load to disc. See example13.rb for more.

Chingu::OnlineHighScoreList

A class to keep/sync online highscores to gamercv.com/. A lot more fun competing with
others for positions then a local list.

Various Helpers

Both $window and game states gets some new graphical helpers, currently
only 3, but quite useful:

fill()# Fills whole window with color 'color'.
fill_rect()# Fills a given Rect 'rect' with Color 'color'
fill_gradient()# Fills window or a given rect with a gradient between two colors.
draw_circle()# Draws a circle
draw_rect()# Draws a rect

If you base your models on GameObject (or BasicGameObject) you get:

Enemy.all# Returns an Array of all Enemy-instances
Enemy.size# Returns the amount of Enemy-instances
Enemy.destroy_all# Destroys all Enemy-instances
Enemy.destroy_if(&block)# Destroy all objects for which &block returns true

BASICS / EXAMPLES

Chingu::Window

With Gosu the main window inherits from Gosu::Window. In Chingu we use
Chingu::Window. It's a basic Gosu::Window with extra cheese on top of
it. keyboard handling, automatic update/draw calls to all gameobjects, fps
counting etc.

You're probably familiar with this very common Gosu pattern:

ROOT_PATH=File.dirname(File.expand_path(__FILE__))classGame<Gosu::Windowdefinitialize@player=Player.newenddefupdateifbutton_down?Button::KbLeft@player.leftelsifbutton_down?Button::KbRight@player.rightend@player.updateenddefdraw@player.drawendendclassPlayerattr_accessor:x,:y,:imagedefinitialize(options)@x=options[:x]@y=options[:y]@image=Image.new(File.join(ROOT_PATH,"media","player.png"))enddefmove_left@x-=1enddefmove_right@x+=1enddefdraw@image.draw(@x,@y,100)endendGame.new.show# Start the Game update/draw loop!

Chingu doesn't change the fundamental concept/flow of Gosu, but it will
make the above code shorter:

#
# We use Chingu::Window instead of Gosu::Window
#
class Game < Chingu::Window
def initialize
super # This is always needed if you override Window#initialize
#
# Player will automatically be updated and drawn since it's a Chingu::GameObject
# You'll need your own Chingu::Window#update and Chingu::Window#draw after a while, but just put #super there and Chingu can do its thing.
#
@player = Player.create
@player.input = {:left => :move_left, :right => :move_right}
end
end
#
# If we create classes from Chingu::GameObject we get stuff for free.
# The accessors image,x,y,zorder,angle,factor_x,factor_y,center_x,center_y,mode,alpha.
# We also get a default #draw which draws the image to screen with the parameters listed above.
# You might recognize those from #draw_rot - http://www.libgosu.org/rdoc/classes/Gosu/Image.html#M000023
# And in it's core, that's what Chingu::GameObject is, an encapsulation of draw_rot with some extras.
# For example, we get automatic calls to draw/update with Chingu::GameObject, which usually is what you want.
# You could stop this by doing: @player = Player.new(:draw => false, :update => false)
#
class Player < Chingu::GameObject
def initialize(options)
super(options.merge(:image => Image["player.png"])
end
def move_left
@x -= 1
end
def move_right
@x += 1
end
end
Game.new.show # Start the Game update/draw loop!

Roughly 50 lines became 26 more powerful lines. (you can do @player.angle =
100 for example)

If you've worked with Gosu for a while you're probably tired of
passing around the window-parameter. Chingu solves this (as has many other
developers) with a global variable $window. Yes, globals are bad, but in
this case it kinda makes sense. It's used under the hood in various
places.

The basic flow of Chingu::Window once show() is called is this (this is
called one game iteration or game loop):

- Chingu::Window#draw() is called
-- draw() is called on game objects belonging to Chingu::Window
-- draw() is called on all game objects belonging to current game state
- Chingu::Window#update() is called
-- Input for Chingu::Window is processed
-- Input for all game objects belonging to Chingu::Window is processed
-- update() is called on all game objects belonging to Chingu::Window
-- Input for current game state is processed
-- Input for game objects belonging to current game state is processed
-- update() is called on all game objects belonging to current game state

… the above is repeatet until game exists.

Chingu::GameObject

This is our basic “game unit”-class, meaning most in game objects (players,
enemies, bullets etc) should be inherited from Chingu::GameObject. The
basic ideas behind it are:

Encapsulate only the very common basics that Most in game objects need

Keep naming close to Gosu, but add smart convenient methods / shortcuts and
a more rubyish feeling

No game logic allowed in GameObject, since that's not likely to be
useful for others.

It's based around Image#draw_rot. So basically all the arguments that
you pass to draw_rot can be passed to GameObject#new when creating a new
object. An example using almost all arguments would be:

#
# You probably recognize the arguments from http://www.libgosu.org/rdoc/classes/Gosu/Image.html#M000023
#
@player=Player.new(:image=>Image["player.png"],:x=>100,:y=>100,:zorder=>100,:angle=>45,:factor_x=>10,:factor_y=>10,:center_x=>0,:center_y=>0)#
# A shortcut for the above line would be
#
@player=Player.new(:image=>"player.png",:x=>100,:y=>100,:zorder=>100,:angle=>45,:factor=>10,:center=>0)#
# I've tried doing sensible defaults:
# x/y = [middle of the screen] for super quick display where it should be easy in sight)
# angle = 0 (no angle by default)
# center_x/center_y = 0.5 (basically the center of the image will be drawn at x/y)
# factor_x/factor_y = 1 (no zoom by default)
#
@player=Player.new#
# By default Chingu::Window calls update & draw on all GameObjects in it's own update/draw.
# If this is not what you want, use :draw and :update
#
@player=Player.new(:draw=>false,:update=>false)

Input

One of the core things I wanted a more natural way of inputhandling. You
can define input -> actions on Chingu::Window, Chingu::GameState and
Chingu::GameObject. Like this:

#
# When left arrow is pressed, call @player.turn_left ... and so on.
#
@player.input={:left=>:turn_left,:right=>:turn_right,:left=>:halt_left,:right=>:halt_right}#
# In Gosu the equivalent would be:
#
defbutton_down(id)@player.turn_leftifid==Button::KbLeft@player.turn_rightifid==Button::KbRightenddefbutton_up(id)@player.halt_leftifid==Button::KbLeft@player.halt_rightifid==Button::KbRightend

Another more complex example:

#
# So what happens here?
#
# Pressing P would create an game state out of class Pause, cache it and activate it.
# Pressing ESC would call Play#close
# Holding down LEFT would call Play#move_left on every game iteration
# Holding down RIGHT would call Play#move_right on every game iteration
# Releasing SPACE would call Play#fire
#
classPlay<Chingu::GameStatedefinitializeself.input={:p=>Pause,:escape=>:close,:holding_left=>:move_left,:holding_right=>:move_right,:released_space=>:fire}endendclassPause<Chingu::GameState# pause logic here
end

In Gosu the above code would include code in button_up(), button_down() and
a check for button_down?() in update().

Every symbol can be prefixed by either “released_” or “holding_” while no
prefix at all defaults to pressed once.

So, why not :up_space or :release_space instead of :released_space?
:up_space doesn't sound like english, :release_space sounds
more like a command then an event.

Or :hold_left or :down_left instead of :holding_left?
:holding_left sounds like something that's happening over a period of
time, not a single trigger, which corresponds well to how it works.

And with the default :space => :something you would imagine that
:something is called once. You press :space once, :something is executed
once.

GameState / GameStateManager

Game states aren't complicated. In Chingu a GameState is a class that
behaves mostly like your default Gosu::Window (or in our case
Chingu::Window) game loop.

# A simple GameState-example
classIntro<Chingu::GameStatedefinitialize(options)# called as usual when class is created, load resources and simular here
enddefupdate# game logic here
enddefdraw# screen manipulation here
end# Called Each time when we enter the game state, use this to reset the gamestate to a "virgin state"
defsetup@player.angle=0# point player upwards
end# Called when we leave the game state
deffinalizepush_game_state(Menu)# switch to game state "Menu"
endend

Looks familiar yet? You can activate the above game state in 2 ways

classGame<Chingu::Windowdefinitialize#
# 1) Create a new Intro-object and activate it (pushing to the top).
# This version makes more sense if you want to pass parameters to the gamestate, for example:
# push_game_state(Level.new(:level_nr => 10))
#
push_game_state(Intro.new)#
# 2) This leaves the actual object-creation to the game state manager.
# Intro#initialize() is called, then Intro#setup()
#
push_game_state(Intro)endend

Another example:

classGame<Chingu::Windowdefinitialize#
# We start by pushing Menu to the game state stack, making it active as it's the only state on stack.
#
# :setup => :false will skip setup() from being called (standard when switching to a new state)
#
push_game_state(Menu,:setup=>false)#
# We push another game state to the stack, Play. We now have 2 states, which active being first / active.
#
# :finalize => false will skip finalize() from being called on game state
# that's being pushed down the stack, in this case Menu.finalize().
#
push_game_state(Play,:finalize=>false)#
# Next, we remove Play state from the stack, going back to the Menu-state. But also:
# .. skipping the standard call to Menu#setup (the new game state)
# .. skipping the standard call to Play#finalize (the current game state)
#
# :setup => false can for example be useful when pop'ing a Pause game state. (see example4.rb)
#
pop_game_state(:setup=>false,:finalize=>:false)#
# Replace the current game state with a new one.
#
# :setup and :finalize options are available here as well but:
# .. setup and finalize are always skipped for Menu (the state under Play and Credits)
# .. the finalize option only affects the popped game state
# .. the setup option only affects the game state you're switching to
#
switch_game_state(Credits)endend

A GameState in Chingu is just a class with the following instance methods:

initialize() - as you might expect, called when GameState is created.

setup() - called each time the game state becomes active.

button_down(id) - called when a button is down.

button_up(id) - called when a button is released.

update() - just as in your normal game loop, put your game logic
here.

Chingus inputhandler will detect that Menu is a GameState-class, create a
new instance and activate it with push_game_state().

GOTCHA: Currently you can't switch to a new game state from Within
GameState#initialize() or GameState#setup()

Premade game states

Chingu comes with some pre-made game states. A simple but usefull one is
GameStates::Pause. Once pushed it will draw the previous game state but not
update it – effectively pausing it. Some others are:

GameStates::EnterName

A gamestate where a gamer can select letters from a A-Z list, contructing
his alias. When he's done he selects “GO!” and a developer-specified
callback will be called with the name/alias as argument.

Combine GameStates::EnterName with class OnlineHighScoreList, a free acount
@ www.gamercv.com and you have a
premade stack to provide your 48h gamecompo entry with online high scores
that adds an extra dimension to your game. See example16 for a full working
example of this.

GameStates::Edit

The biggest and most usable is GameStates::Edit which enables fast 'n
easy level-building with game objects. Start example19 and press
'E' to get a full example.

WorkFlow

(This text is under development)

The setup-method

If a setup() is available in a instance of Chingu::GameObject,
Chingu::Window and Chingu::GameState it will automatically be called. This
is the perfect spot to include various setup/init-tasks like setting colors
or loading animations (if you're not using the animation-trait). You
could also override initialize() for this purpose but it's been proven
prone to errors again and again. Compare the 2 snippets below:

# Easy to mess up, forgetting options or super
definitialize(options={})super@color=Color::WHITEend# Less code, easier to get right and works in GameObject, Window and GameState
# Feel free to call setup() anytime, there's no magic about ut except it's autocalled once on object creation time.
defsetup@color=Color::WHITEend

Traits

Traits (sometimes called behaviors in other frameworks) is a way of adding
logic to any class inheriting from BasicGameObject / GameObject. Chingus
trait-implementation is just ordinary ruby modules with 3 special methods:

-setup_trait-update_trait-draw_trait

Each of those 3 methods must call “super” to continue the trait-chain.

Inside a certian trait-module you can also have a module called
ClassMethods, methods inside that module will be added, yes you guessed it,
as class methods. If initialize_trait is defined inside ClassMethods it
will be called class-evaluation time (basicly on the trait :some_trait
line).

Example of using traits :velocity and :timer. We also use GameObject#setup
which will automtically be called ad the end of GameObject#initialize.
It's often a little bit cleaner to use setup() then to override
initialize().

classOgre<Chingu::GameObjecttraits:velocity,:timerdefsetup@red=Gosu::Color.new(0xFFFF0000)@white=Gosu::Color.new(0xFFFFFFFF)#
# some basic physics provided by the velocity-trait
# These 2 parameters will affect @x and @y every game-iteration
# So if your ogre is standing on the ground, make sure you cancel out the effect of @acceleration_y
#
self.velocity_x=1# move constantly to the right
self.acceleration_y=0.4# gravity is basicly a downwards acceleration
enddefhit_by(object)#
# during() and then() is provided by the timer-trait
# flash red for 300 millisec when hit, then go back to normal
#
during(100){self.color=@red;self.mode=:additive}.then{self.color=@white;self.mode=:default}endend

Trait “velocity”

Adds accessors velocity_x, velocity_y, acceleration_x, acceleration_y,
max_velocity to game object. They modify x, y as you would expect. *speed /
angle will come*

Trait “bounding_box”

Adds accessor 'bounding_box', which returns an instance of class
Rect based on current image size,x,y,factor_x,factor_y,center_x,center_y
You can also scale the calculated rect with trait-options:

# This would return a rect slightly smaller then the image.
# Make player think he's better @ dodging bullets then he really is ;)
trait:bounding_box,:scale=>0.80# Make the bounding box bigger then the image
# :debug => true shows the actual box in red on the screen
trait:bounding_box,:scale=>1.5,:debug=>true

Inside your object you will also get a cache_bounding_box(). After that the
bounding_box will be quicker but it will not longer adapt to size-changes.

Trait “bounding_circle”

Adds accessor 'radius', which returns a Fixnum based on current
image size,factor_x and factor_y You can also scale the calculated radius
with trait-options:

# This would return a radius slightly bigger then what initialize was calculated
trait:bounding_circle,:scale=>1.10# :debug => true shows the actual circle in red on the screen
trait:bounding_circle,:debug=>true

Inside your object you will also get a cache_bounding_circle(). After that
radius() will be quicker but it will not longer adapt to size-changes.

Trait “animation”

Automatically load animations depending on the class-name. Useful when
having a lot of simple classes thats mainpurpose is displaying an
animation. Assuming the below code is included in a class FireBall.

#
# If a fire_ball_10x10.png/bmp exists, it will be loaded as a tileanimation.

# 10x10 would indicate the width and height of each tile so Chingu knows
hows to cut it up into single frames.

# The animation will then be available in animations[:default] as an Animation-instance.
#
# If more then 1 animation exist, they'll will be loaded at the same time, for example:
# fire_ball_10x10_fly.png # Will be available in animations[:fly] as an Animation-instance
# fire_ball_10x10_explode.png # Will be available in animations[:explode] as an Animation-instance
#

# The below example will set the 200ms delay between each frame on all
animations loaded.

#
trait:animation,:delay=>200

Trait “effect”

Adds accessors rotation_rate, fade_rate and scale_rate to game object. They
modify angle, alpha and factor_x/factor_y each update. Since this is pretty
easy to do yourself this trait might be up for deprecation.

Trait “viewport”

A game state trait. Adds accessor viewport. Set viewport.x and
viewport.y to. Basically what viewport.x = 10 will do is draw all game
objects 10 pixels to the left of their ordinary position. Since the
viewport has moved 10 pixels to the right, the game objects will be seen
“moving” 10 pixels to the left. This is great for scrolling games. You also
have:

viewport.game_area=[0,0,1000,400]# Set scrolling limits, the effective game world if you so will
viewport.center_around(object)# Center viweport around an object which responds to x() and y()
viewport.lag=0.95# Set a lag-factor to use in combination with x_target / y_target
viewport.x_target=100# This will move viewport towards X-coordinate 100, the speed is determined by the lag-parameter.

NOTE: Doing Parallax.create when using a trait viewport will give bad
results. If you need parallax together with viewport do Parallax.new and
then manually doing parallax.update/draw.

Trait “collision_detection”

Adds class and instance methods for basic collision detection.

# Class method example
# This will collide all Enemy-instances with all Bullet-instances using the attribute #radius from each object.
Enemy.each_bounding_circle_collision(Bullet)do|enemy,bullet|end# You can also use the instance methods. This will use the Rect bounding_box from @player and each EnemyRocket-object.
@player.each_bounding_box_collision(EnemyRocket)do|player,enemyrocket|player.die!end#
# each_collision automatically tries to access #radius and #bounding_box to see what a certain game object provides
# It knows how to collide radius/radius, bounding_box/bounding_box and radius/bounding_box !
# Since You're not explicity telling what collision type to use it might be slighty slower.
#
[Player,PlayerBullet].each_collision(Enemy,EnemyBullet)do|friend,foe|# do something
end#
# You can also give each_collision() an array of objects.
#
Ball.each_collsion(@array_of_ground_items)do|ball,ground|# do something
end

Trait “asynchronous”

Allows your code to specify a GameObject's behavior asynchronously,
including tweening, movement and even method calls. Tasks are added to a
queue to be processed in order; the task at the front of the queue is
updated each tick and removed when it has finished.

# Simple one-trick example
# This will cause an object to move from its current location to 64,64.
@guy.async.tween:x=>64,:y=>64# Block syntax example
# This will cause a line of text to fade out and vanish.
Chingu::Text.trait:asynchronousmessage=Chingu::Text.new'Goodbye, World!'message.asyncdo|q|q.wait500q.tween2000,:alpha=>0,:scale=>2q.call:destroyend

For a more complete example of how to use this trait, see
examples/example_async.rb.

(IN DEVELOPMENT) Trait “retrofy”

Providing easier handling of the “retrofy” effect (non-blurry zoom) Aims to
help out when using zoom-factor to create a retrofeeling with big pixels.
Provides screen_x and screen_y which takes the zoom into account Also
provides new code for draw() which uses screen_x / screen_y instead of x /
y

Assets / Paths

It enables you to start your game from any directory and it will still find
your assets (pictures, samples, fonts etc..) correctly. For a local
development version this might not be important, you're likely to start
the game from the games root-dir. But as soon as you try to deploy (for
example to windows with OCRA - github.com/larsch/ocra/tree/master)
you'll run into trouble of you don't do it like that.

Chingu solves this problem behind the scenes for the most common assets.
The 2 lines above can be replaced with:

Image["player.png"]

You also have:

Sound["shot.wav"]Song["intromusic.ogg"]Font["arial"]Font["verdana",16]# 16 is the size of the font

@text.draw is usually not needed as Text is a GameObject and therefore
automatically updated/drawn (it #create is used instead of #new) It's
not only that the second example is readable by ppl now even familiar with
Gosu, @text comes with a number of changeable properties,
x,y,zorder,angle,factor_x,color,mode etc. Set a new x or angle or color
and it will instantly update on screen.

DEPRECATIONS

Chingu (as all libraries) will sometimes break an old API. Naturally we try
to not do this, but sometimes it's nessesary to take the library
forward. If your old game stops working with a new chingu it could depend
on some of the following:

Listing game objects:

classEnemy<GameObject;end;classTroll<Enemy;end;classWitch<Enemy;end;

Chingu 0.7

Enemy.all# Will list objects created with Enemy.create, Troll.create, Witch.create

Chingu ~0.8+

Enemy.all# list only list objects created with Enemy.create

We gained a lot of speed breaking that API.

MISC / FAQ

How do I access my main-window easily?

Chingu keeps a global variable, $window, which contains the Chingu::Window
instance. Since Chingu::Window is just Gosu::Window + some cheese you can
do your $window.button_down?, $window.draw_line() etc from anywhere. See www.libgosu.org/rdoc/classes/Gosu/Window.html
for a full set of methods.

How did you decide on naming of methods / classes?

There's 1 zillion ways of naming stuff. As a general guideline I've
tried to follow Gosus naming. If Gosu didn't have a good name for a
certain thing/method I've checked Ruby itself and then Rails since alot
of Ruby-devs are familiar with Rails. GameObject.all is naming straight
from rails for example. Most stuff in GameObject follow the naming from
Gosus Image#draw_rot.

As far as possible, use correct rubyfied english game_objects, not
gameobjects. class HighScore, not Highscore.

WHY?

Plain Gosu is very minimalistic, perfect to build some higher level logic
on!

Deployment and asset handling should be simple

Managing game states/scenes (intros, menus, levels etc) should be simple

Old History, now deprecated:

0.6 / 2009-11-21

0.5.7 / 2009-10-15

See github commithistory.

0.5 / 2009-10-7

Big refactor of GameObject. Now has BasicGameObject as base. A first basic
“trait”-system where GameObject “has_traits :visual, :velocity” etc. Tons
of enhancements and fixes. Speed optimization. More examples.

0.4.5 / 2009-08-27

Tons of small fixes across the board. Started on GFX Helpers (fill,
fill_rect, fill_gradient so far). A basic particle system (see example7.rb)

0.4.0 / 2009-08-19

Alot of game state love. Now also works stand alone with pure gosu.

0.3.0 / 2009-08-14

Too much to list. remade inputsystem. gamestates are better. window.rb is
cleaner. lots of small bugfixes. Bigger readme.