Creating Games in Ruby (Part 2)by Andrea O. K. Wright
Part One of this two-part series begins with the question: Can playing games written in Ruby be as much fun as writing them, or do they run too slowly, with too many breaks in the action at inopportune times? I go over some reasons why it makes sense to ask that question, and I begin to answer by way of kicking off a survey of the Ruby game development landscape. I start with lower-level libraries and progress through higher-level frameworks. The tour continues in Part Two. I will conclude by revisiting the question I posed at the beginning of the series.
Co-Creators: Julian Raschke & Jan Lucker
Lead Developer: Julian Raschke
Gosu was written in C++, and a tool called SWIG (Simplified Wrapper and Interface Generator) is used to generate the C++ extension for Ruby. But just because the primary development language for Gosu is C++, it does not mean that the Ruby version is given short shrift. Anything that doesn't have a native Ruby feel is adjusted with custom SWIG directives.
Gosu is polished and compact. Its development team aims to include everything you need to create a game, but nothing more. Every feature it supports was needed for and tested in an existing application. Nothing was added because someone might find it useful in theory.
In keeping with the design rationale behind the code, Gosu is packaged with a well-thought-out tutorial that provides everything you need to get started with Gosu, but nothing more. It takes less than an hour to complete, but at the end of that hour you're ready to start developing games.
Here's what the finished tutorial looks like. When you steer the ship into a star, the star vanishes and you get points.
Figure 1. Tutorial packaged with Gosu
Even experienced Gosu developers start out by subclassing Gosu's Window class and taking advantage of its built-in services. Here's a skeletal main window:
class MainWindow < Gosu::Window def initialize(width, height, fullscreen) super end def update # Change display attributes, if necessary. end def draw # Display calls go here. end def button_down(id) # Buttons are keys, mouse buttons, and # game pad controls. end end
You don't need to start a main game loop or set up an event queue in your application-level code because Gosu handles that behind the scenes. Gosu will call the main window's
update method and then its
draw method, every frame. When the user presses a key on the keyboard or a mouse button, the
button_down callback is invoked.
Because Gosu is so streamlined, many developers have found that it's well-suited for timed game development competitions. Below is a video clip of a game that was created for a competition by a team of developers, including Florian Gross, Alexander Post, and Gosu co-creator and lead developer Julian Raschke (click on the screenshot to view the video clip). It was created in 72 hours. The version shown here was polished a little after the competition ended.
The object of this game is to lure the sleepwalking witch back to bed, primarily using chocolate as bait. The fairy is actually the mouse cursor, and if you click on the chocolate bar, a tiny chocolate bar will appear in her hands. If you feed her a hot chili pepper and scare her with a plush orc toy in her sleep, she becomes red-tinted and infused with firepower that enables her to zap anything the gets in her way. You can feed her an ice cream cone when she needs to throw ice bolts to neutralize fiery cauldrons or turn pools of water into bridges of ice. On some levels you need to scare her with a spider so she will hit a light switch when she tries to swat the spider away. If lights are left on, they could potentially wake her up.
Gosu was built to be easily integrated with external libraries. It is packaged with a tutorial that shows how Gosu can be integrated with Scott Lembcke's 2D physics library, Chipmunk. Chipmunk is written in C, but it is distributed with its own Ruby bindings. Chipmunk enables you to imbue your sprites with virtual mass so that when they collide, they behave according to the laws of natural physics. The tutorial not only shows how to use Chipmunk to handle collision detection, it shows how nicely Gosu plays with others.
The Gosu/Chipmunk integration tutorial, which was written by Dirk Johnson, uses the standard Gosu spaceship tutorial as a starting point. There are numerous changes to the internals of the original Gosu tutorial in the Chipmunk-enhanced version. But when you run the application, it looks almost exactly like the original version. The stars disappear before you can see the impact of the collision. I think the most magical thing about Chipmunk is watching the stylized 2D sprites move in a natural way. So I modified the Gosu/Chipmunk integration tutorial by commenting out the code that removes the stars when the spaceship steers into them. That way you could see what happens when the spaceship hits the Chipmunk-enhanced stars. I also made the star field more dense and added a couple of Chipmunk logos. The video clip below shows the sort of thing that can happen when you mix Gosu and Chipmunk (click on the screenshot to view the video clip):
Integration points for RMagick were recently built into Gosu after users requested the ability to dynamically modify the landscape during a game. The video clip below shows a sample app that uses special effects that are not possible without RMagick. RMagick comprises the Ruby bindings for the ImageMagick libraries, which can be used to transform or combine images and apply dozens of special effects, like mirroring, flipping and even emulating a watermark or Polaroid instant picture. In the video clip below (click on the screenshot to view the video clip), the two toy soldiers take turns blasting holes in the landscape, revealing more of the sky in the background.