A look at the first Rebirth demo game

(May 29, 2008 @ 11:44 PM)

I finished a demo game yesterday, as an aid in designing the still-imaginary Rebirth API. I actually meant to post this last night, but I ended up staying up until past 2AM trying to find a way to do syntax highlighting on Mephisto, to no avail.

The game is a simple one: bounce a ball in the air by clicking it, and don’t let it fall to the ground. You get a point for each time you click it, but lose a point for each time it hits the ground. If you get up to 15 points, you win. Not the most challenging thing in the world, but it has all the elements of a complete game.

The code for the entire game is about 100 lines long. Rather than cop out and just post the whole file, I’ll show and explain a few highlights. Keep in mind that the code to support this doesn’t exist yet; I’m just threshing it out, and imagining how it might be used. As I explained in my previous post, once I’ve got some sample games written, I’ll codify the API in specs, and then implement it.

First up, is the class for the Ball object. Here’s the entire class definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Represents a bouncing ball.
class Ball < GameObject
  # Set up the physical and visual properties of the ball.
  def initialize( params = {} )
    base_params = { 
      :center  => v(0,0),
      :radius  => 15.0,
      :density => 5.0,
      :elast   => 0.9,
      :color   => :red
    }
    
    add_shape Circle.new( base_params.merge(params) )
  end
end

As you can see, it just creates a Circle instance with certain parameters, and adds the Circle as a shape. The hash of base parameters defines what the default ball is like, but you can override / augment them by passing a hash to the initializer. There will be other possible parameters besides just the ones shown there, but these are the ones that are important to the ball (Circle will use defaults for the rest).

Circle will be one of a handful of built-in shape classes, which provide a visual appearance and a physical behavior for game objects (i.e. for collision detection and physics). By default, objects are both visible and collidable, but you can turn either (or both) off by providing certain parameters. That way, you can have non-collidable objects, or collidable invisible objects. And, yes, all the shape classes will be part of the physics engine, powered by Chipmunk.

So far, it has a ball that we can see, and that acts physically. Later on, it adds a hook to perform a certain action when the player clicks on the ball:

1
2
3
4
5
6
$game[:ball] = Ball.new

$game[:ball].when_clicked do |click|
  $game[:score] += 1
  $game[:ball].shove( :from => click.pos, :strength => 30.0 )
end

Here, it makes an instance of Ball, and stores the instance in a namespace for later use ($game is an instance of Game, which I’ll cover later). Then, it uses the when_clicked method to add a hook which will be triggered when the user clicks on the ball. The block adds one point to the player’s score, and also applies a physical impulse to the ball to shove it away from the cursor, sending the ball back into the air. (By the way, the hook could have just as well been set up in the Ball’s initialize method, for behaviors that you want every instance to have.)

Elsewhere, it sets up a when_collided hook on the floor, to call a block to remove one point from the player’s score. It also creates a when_true hook on $game itself; when_true periodically evaluates a Proc to see if the statement is true, in this case to test if the player has 15 points yet.

There’s other interesting code that I’d show you, but I don’t want this post to get really long. I expect to put this project up on Github eventually, so you’ll be able to get all the code you want. If the demand is there, I might do another post tomorrow to demo another part.

P.S. Rebirth is still strictly theoretical. I’d give it a 50:50 chance that Rebirth sees a release, and only a 1-in-20 chance that it will result in any major functionality removal from core Rubygame.

Rubygame: Rebirth

(May 27, 2008 @ 01:14 AM)

I’m going to try an experiment. A clean slate, a new project, a new library. Shrugging off the baggage and legacy of the Old Rubygame, and starting fresh, as I talked about in the previous post.

I’m going to design a new library from scratch, applying what I’ve learned from the first attempt, but with no thought to compatibility. I’m dubbing the project Rubygame: Rebirth. Rather melodramatic, but it hits the right chord.

I’m going to tinker in a local git repository for a week or so, and then decide the future of the experiment. If it feels right, I’ll put it up on Github, and take it from there. If it pans out, I’ll trash it.

Here’s the ‘plan’:

First, I’m going to write some simple games with the library, before it even exists. Each game will have a different complexity level. At the low end would be something as simple as Pong. At the high end would be a run-and-jump platformer with physics, textures, and sound effects. Obviously, none of the games will run at this point, but they’ll be the sandbox for designing an API that I would want to use.

Once I have a few games written, I’m going to extract the core API requirements from those games, and express them as specs. Again, they won’t pass (they’ll be “not implemented”), but they’ll be a more formal definition of the API-to-be. The API will be categorized by the complexity of the game that requires it, and mapped out as milestones to guide development, with the simplest things first, and the most complex things last. The games and specs will also act as progress indicators – as the library becomes more complete, the games will start to run, and the specs will start to be green-able.

Each new feature would correspond to a milestone, and each milestone would mean a new release. The first release would come when the simplest game (Pong or whatnot) ran successfully. Every new feature would be another release. Some releases would also have a new game that began to run due to the latest feature addition. Bug fixes wouldn’t get their own releases, but just wait until the next feature.

And of course, all of these plans would be subject to change. I know myself too well to think that I can predict how this project will go. Things change, ideas change, people change. Nothing would be carved in stone, just sketched out in pencil as a guide.

I have no idea if anybody will care, or branch it and make changes. The plan doesn’t depend on it, but it does allow for it – by laying out the draft API from early on, other people might help fill in the blanks. I’m not getting my hopes up, though.

What will come of this experiment? I certainly can’t predict. At worst, it’s a false start, and I trash it within a week. At best, it’s the future of a new, reborn Rubygame.

Insert dramatic music here.

Sexy Progress vs Compatibility

(May 26, 2008 @ 05:22 PM)

There are times when I am tempted – so sorely tempted – to break compatibility between Rubygame 2 and Rubygame 3 in a huge way. Wipe the slate clean and rebuild, carrying over only the best ideas from the Old Rubygame. If I were going to do that, here’s what the New Rubygame would be like:

  • No SDL. Certainly no SDL_mixer or SDL_gfx, which have been great annoyances to me – the former for its flakeyness, and the latter for its lack of a precompiled Windows DLL (which I only care about because it significantly raises the barrier for Windows users to try out Rubygame).

  • Instead, OpenGL and OpenAL. Mostly for the robustness and wide cross-platform adoption, but also for the sexy feature factor. “Hardware accelerated” looks good on a résumé.

  • Chipmunk integration from the start. “Real-time physics engine” also looks good on a résumé.

  • Higher level Sprite and other classes, with more controlled APIs, and a well-defined system for extending them. Plugins preferred over inheritance.

  • Hook-based event management.

  • No Rect. No Surface. No draw_* methods.

  • Instead, shapes – for collision/physics, and for drawing. Drawing styles with attributes for fill and border. Images would be textured quads. Inspired by SVG.

  • Total independence from screen resolution. Objects exist and interact in world space, and can be viewed at any size or rotation with no worries about doing rotozooms and storing temporary images.

  • Generally, more focus on objects and behavior, and way, way less focus on managing pixels.

  • Fully specced, BDD all the way, and clear example games demonstrating how to use each feature.

  • Way cooler than Gosu. ; )

So what’s stopping me from doing all this awesome stuff? It’s not the effort or the time involved – new things like this are interesting and motivating, and it would proceed easily and quickly. And certainly, dropping all the baggage from Rubygame would be liberating and motivating in itself.

The problem is, New Rubygame wouldn’t even be remotely compatible with Old Rubygame. The core concepts are fundamentally different. Upgrading old games would practically mean rewriting them. For some games, it wouldn’t even be possible to upgrade, because the feature set would be so different. New Rubygame would be a whole different species, a whole different library from Old Rubygame.

So here are the possible roads forward:

  1. Continue adapting the current Rubygame, adding new things and deprecating older things, slowly and incrementally progressing towards a better Rubygame.
  2. Start over with Rubygame 3 as a whole new creature. Scrap the old library, leave old apps in the dust.
  3. Start a new, separate library to implement this new vision. Rubygame continues on its own.

Food for thought.

New domain, new blog, new awesome

(May 25, 2008 @ 12:58 AM)

Is it a bird? A plane? No, it’s a new blog at a new domain!

Yes indeed, Rubygame now has its own domain – rubygame.org – and a shiny new blog to go with it, powered by the spiffy Mephisto app. All the Rubygame-related posts have been migrated over here from their previous location at my personal blog. (Although, there were some posts that have both Rubygame and non-Rubygame related topics, which I decided case-by-case which blog to put them on.)

In addition to the blog, I’ll be putting up docs, downloads, etc. soon. In fact, the RDoc-generated docs are already up. Eventually, I’m hoping to set up a better documentation system – I’ve been working on a Rails app for that, when I have the time.

Anyway, welcome to rubygame.org!

Rubygame 2.3 released!

(May 21, 2008 @ 06:46 AM)

We’ve got several great announcements to make!

  • Rubygame 2.3.0 released
  • New Rubygame community forum
  • RbWeek game creation contest coming in June

Rubygame 2.3.0 released

Rubygame 2.3.0 is now available! This version adds two improved audio classes and a utility mixin module for automatically loading sounds and images on demand!

You can install the new version with RubyGems (gem install rubygame), or download it from Rubyforge:

In addition to the platform-independent source gem, precompiled binary gems are currently available for Linux and Windows. A Mac binary gem will be offered as soon as someone sends me one. ;)

Documentation and release notes are available online, as usual:

For a good introduction to the new features in this version, check out my blog post:

New Rubygame community forum

Community member Niklas Humlen has set up RubygameForums.com, a forum for developers and community members to discuss and share their tips, ideas, and creations.

I hope to see it growing into a great community resource soon!

RbWeek game creation contest coming in June

Several community members are organizing a week-long game creation contest, tentatively scheduled to begin on Friday, June 13. Participants are not limited to just Rubygame – Gosu, Ruby/SDL, and other Ruby libraries are welcome as well!

I’ll be participating, as will several other community members. Come join us, have a lot of fun, earn glory and the envy of your peers, and develop your own game in one week with Ruby!

Introduction to Rubygame 2.3

(May 21, 2008 @ 06:34 AM)

Rubygame 2.3.0 has been released! This article will introduce you to the new features, and help developers get the most out of the new version!

New Features

Sound and Music classes

Rubygame 2.3.0 adds two new classes, Sound and Music, which offer numerous advantages over the older Mixer::Sample and Mixer::Music classes. Both classes offer a consistent and natural API (e.g. sound.play, sound.volume = 0.5, sound.stop), and will automatically initialize the audio device and allocate audio channels as needed.

Please note that with the addition of these new classes, the older Mixer::Sample and Mixer::Music are deprecated. See the section on deprecations, below.

NamedResource mixin module

In addition to the new classes, Rubygame 2.3.0 adds a new utility mixin module, NamedResource. NamedResource extends classes with a per-class Hash table for storing resources (e.g. images, sounds) by name for future access. Even more excitingly, NamedResource allows resources to be autoloaded on demand, when they are first needed.

NamedResource is included in the new Sound and Music classes, as well as in Surface. To use the autoloading feature in your games, simply add directory paths to the class’s autoload_dirs array (e.g.: Surface.autoload_dirs << "images"). Resources will then be autoloaded from those directories the first time you access them (e.g.: Surface["imagename.bmp"]).

NamedResource is also available to use in your own classes. This can be useful for loading and storing resources like maps, characters, weapon definitions, etc. Please see the documentation for NamedResources for an example of using it in a class.

Deprecations

Mixer

The Mixer module (including the Mixer::Sample and Mixer::Music classes) is deprecated and will be removed in the future (version 3.0). New games should not use the Mixer module, and existing games are strongly encouraged to migrate to the newer classes.

Important module methods from the Mixer, most notably open_audio and close_audio, are now available directly in the Rubygame module. Please note that you only need to use these methods if you don’t want to use the default audio settings. Sound and Music will both automatically open the audio device as needed, and it will be closed when Rubygame.quit is called. Also note that Rubygame.open_audio takes arguments as a Hash, whereas Rubygame::Mixer.open_audio has taken a series of optional arguments.

Surface.load_image

The Surface.load method should now be used in favor of Surface.load_image. This is simply a new name, for consistency with the new Sound and Music classes. It functions identically with Surface.load_image. Surface.load_image is deprecated and will be removed in the future.

Enabling deprecation warnings

In order to test whether your game is using deprecated features, run ruby with the “-w” flag, or set “$_v = true” inside your application. This will cause Rubygame to emit a warning (with file and line number) whenever a deprecated method or class is used, like so:

chimp.rb:205: warning: Rubygame::Mixer is DEPRECATED and will be removed in Rubygame 3.0! Please see the docs for more information.

You should use this as a guide to help you ensure that your game will be compatible with Rubygame 3.0, when it is released.

Versions between now and then (e.g. 2.4, 2.5) will contain more deprecated modules and methods, so you should be sure to check for deprecation warnings with each new version. Of course, the release notes for those versions will describe what has become deprecated, as well.

Rubygame 2.3 ready for download

(May 17, 2008 @ 07:22 PM)

I’ve decided to release the source tarball and gem for Rubygame 2.3. You can download the new version from Rubyforge, or install it with gem install rubygame. As usual, you’ll need the SDL libraries installed first, or the compile will fail!

I’ll wait a couple days for Windows and Mac binary gems to come in, then release all the binary gems simultaneously. That’s when I’ll do the regular release announcement dance.

Rubygame 2.3 will be released this weekend

(May 16, 2008 @ 01:28 PM)

Phew, the past week has been busy busy busy with work. But I got through a big deadline last night, and things will be a lot less hectic for a while. And you know what that means – more time to work on Rubygame!

All the features for 2.3 are already complete, so I’m just preparing everything this evening. Then I’ll be packaging it up in a tarball and gem. The source and precompiled Linux gems should be ready tonight or tomorrow. The precompiled Win32 and Mac versions will be ready whenever my lovely compiling assistants have it. I might delay release of the source/Linux gems for a few days to see if I can manage a simultaneous release on all platforms. Y’know, so Win32 and Mac users won’t feel left out of the Rubygame goodness.

NamedResource included in Music, Sound, and Surface

(May 10, 2008 @ 07:55 PM)

Tonight I finished up the process of including the new NamedResource mixin into the Music, Sound, and Surface classes. It was actually a really simple process. Once I had figured out the proper way to require and include the NamedResource module from the C code, it was just a matter of defining an “autoload” class method for each of the three classes. Even written in C, those methods were less than 10 lines each.

From that standpoint, I’d say that NamedResource has succeeded in being insanely simple to use. You really only have to do two things to use it in a class: 1) include the mixin, 2) define an “autoload” method that returns an instance or nil. For convenience, there’s an autoload_dirs class instance variable (an array of directories), and a find_file method that you can use in autoload, to search those directories for a file with a certain name.

So, you could say I’m quite proud of it, and certainly glad that I sat down and created it. It’ll make a nice addition to Rubygame 2.3. Speaking of which, all the features for Rubygame 2.3 are done now! I’m going to copy over the features to the 2.3 branch, tweak the demo programs to show off the new features, update the NEWS file, check one last time that everything looks right, and package it up for release.

Pretty exciting times, eh?

NamedResource complete

(May 07, 2008 @ 10:03 AM)

I’ve been working in my spare moments on designing and implementing the NamedResource class. It’s now pretty much complete, and I’m quite happy with the result. In addition to using it for Music, Sound, and Surface, it’s also a useful mixin for other things. Here’s a snippet from the docs, to give you a taste of how nice it is:

Here’s an example of how you could use this for a class which loads maps from a file:

class Map
  include Rubygame::NamedResource

  Map.autoload_dirs = [ File.join("maps","world_1"),
                        File.join("maps","custom") ]

  def autoload( filename )
    # Searches autoload_dirs for the file
    path = find_file( filename )

    if( path )
      return load_map( path )
    else
      return nil
    end
  end

  def load_map( path )
    # Your code to do the real loading, then return
    # the created instance of Map class.
    # ...
    return map_instance
  end
end

Here’s an example of how you could then use the Map class:

map = Map["level_1.map"]

if( map )
  start_playing( map )
else
  raise "Oops! The map file for Level 1 doesn't exist!"
end

NamedResource will be shipped in Rubygame 2.3. Now I just need to include it in Sound, Music, and Surface classes. Woohoo!

Named Resources

(May 03, 2008 @ 09:32 PM)

I’ve made a scratchpad page where I’m thinking through the design of the NamedResource mix-in module that will be in Rubygame 2.3, if you are interested in reading about that.

Waffles, Names, and Rubygame 2.4

(May 03, 2008 @ 03:45 PM)

Waffles! No, not the crunchy, delicious breakfast food. I’m just poking fun at my own tendency to decide on something, then switch positions a little bit later (this is sometimes called ‘waffling’).

I said last time, that the resource naming functionality wouldn’t be in Rubygame 2.3, but instead by in a later version, because it wasn’t finished yet and I didn’t want to delay 2.3 for an unnecessary feature. But, as I was working on the roadmap for 2.4, which will be about events, I had a change of plans.

I’ll get back to 2.3 later, but here’s a tentative roadmap for 2.4, which is 100% guaranteed to change as time goes on:

  • New hook-based event system. EventHandler, EventHook, etc. Also, magic_hooks and probably some other convenience stuff.
  • New Events module, containing new event classes, which will have new names, mostly to make the names shorter and nicer: e.g. KeyDownEvent –> Events::KeyPress, MouseMotionEvent –> Events::MouseMove. Obviously, you can do “include Rubygame::Events” and get access to them on the toplevel namespace.
  • The old event classes and integer constants will still be around, but deprecated.
  • The new keyboard event classes will use symbols instead of integer constants.
  • Unicode strings for the new key press class.

This is continuing my recent theme of pulling out individual features from the 3.0 branch and adding them in a backwards-compatible way, while simultaneously deprecating the old features that they replace.

Okay, back to the topic of 2.3. As you can see, the resource naming functionality doesn’t really belong in 2.4. (That’s right, the entire basis of my switching position, is that something doesn’t fit in with the other things.) But, it does fit in with 2.3 nicely, and 2.3 needs a minor feature to complement the two new classes. So right now, I’m in favor of adding the resource naming into 2.3, after all.

There are some non-obvious complexities involved in implementing it (e.g. if I put the functionality in a ruby-coded mixin, the mixin will need to be loaded before the C-coded classes that use it), but it’s not a terribly difficult task. Rubygame 2.3 probably won’t be released this weekend, but I’m hoping to have this last feature complete.