Rubygame 2.5.2 Released

Rubygame 2.5.2 fixes a single, somewhat major bug:

  • Fixed: HasEventHandler#handle (and other methods) dealt with NoMethodError exceptions in a stupid way.

Thanks to Kiba for reporting this bug.

Full docs are online at docs.rubygame.org. Source tarball and gem are available for download at Rubyforge and download.rubygame.org, or you can install with gem install rubygame.

Enjoy!

Rubygame 2.5.1 Released

I've just released Rubygame 2.5.1. This version fixes two bugs, one potentially serious, and one minor.

  • Fixed: Clock.delay would delay forever if the delay time and granularity were very small.
  • Fixed: Clock.delay would always be "nice" to other Ruby threads during the final part of the delay, even if nice = false.

Thanks to shawn42 (Shawn Anderson) for discovering and telling me about the first bug.

Full docs are online at docs.rubygame.org. Source tarball and gem are available for download at Rubyforge and download.rubygame.org, or you can install with gem install rubygame.

Enjoy!

Ah, Vacation!

Ah, I finally get to kick back and relax: it's vacation time! I'm avoiding real work as much as possible for the next 2 weeks to a month, and just slacking off and tending to fun things.

Now that Rubygame 2.5.0 is out, the next order of business is to clean up the web sites! Rubygame has moved a few times in its 4+ year history, and has left a bit of a slime trail as it went. (Note: many of the following links will become redirects within a few days of posting this.) Rubygame was first hosted on SEUL.org, then added an Infogami wiki to augment the static site. Then it moved to Sourceforge, and then added a wiki on SF. Then I added this blog to augment the SF site, and then mostly abandoned SF, hosting the source on Github, releases on RubyForge, and docs here at rubygame.org. Phew!

Now I'm getting around to making this an actual coherent site, instead of just a blog, forums, and other random things scattered around. I'm also cleaning up as many of the old sites as I can. I accidently permanently borked the Infogami site a couple days ago by deleting the site template (oops), so now it's just... nothing. The SEUL and SF sites will become transparent redirects to the new site, which will start off as an updated version of the current SF site (since I'm still happy with my work on that).

After that's taken care of, I'm going to try to convert this blog and the one over at blog.jacius.info to WordPress, since Mephisto is kinda clunky, plus I'm kinda tired of having to restart Mongrel when something goes wrong on the server. Finally, I'll probably set up MediaWiki to have a modern, community-editable Rubygame wiki. (Yes, the blog, wiki, and forums for Rubygame will all be running on PHP, and no, I don't see any irony there. Call me when there's a Ruby-based blog, wiki, or forum app in the same league as the PHP ones.)

I should also come up with a Rubygame logo. I've got a new concept in mind (my motivation for finishing up this one is getting stale), so I'll be experimenting with that on the side.

This next one is a bit of a stretch, since there are other things I'd like to do, too, but I'd also like to take another stab at the API Documentation app I tried to write last year. I detest having to work with (or against, as it were) RDoc for the Rubygame documentation. Every Rubygame release involves me fiddling for hours trying to get RDoc to format output the way I want, and the final result is mediocre, even when it's working perfectly.

So, I was thinking of writing a web app to manage documentation. But I made the mistake of trying to do it in Rails (hah, hah, silly me), so the project crashed into a smoking heap of garbage and nils-where-I-didn't-expect-them. (I guess that's what happens when you try to ride Rails to someplace it doesn't feel like going.)

I had been thinking about retrying it with Merb, to see if that was any better, until I heard it would be merging with Rails in the future. I might try Ramaze instead. Or heck, even Sinatra would be better than Rails. A bit more code to write, maybe, but fewer headaches and stomach ulcers. (If I wanted headaches and ulcers during my vacation, I'd go back to work early.)

But, I'm not sure I'll take on that project yet. After all, I could use the time I'd spend on that, to work on Rubygame 3.0, Rebirth, a game, or some other fun thing!

We'll see.

Oh, I forgot to mention the most important thing to do during my vacation: have lots and lots of afternoon naps in the sunshine with a cat on my lap.

Rubygame 2.5.0 released

Rubygame 2.5.0 is now ready to go!

The main focus of this release is improving the Clock class. Clock now has a more responsive and accurate algorithm for measuring framerate, better support for multithreaded games (set Clock#nice = true), a new ClockTicked event class (for use with EventHandler), and a way to calibrate the Clock to minimize wasted CPU power.

I've also written an in-depth tutorial about using Clock, entitled Managing Framerate. It covers several aspects of using Clock, including:

  • framerate monitoring (finding out how fast your game is running)
  • framerate limiting (setting the maximum framerate, to avoid wasting CPU power)
  • calibrating Clock (to reduce CPU usage even more)
  • framerate independence (so characters don't move slower if the framerate drops)

In addition to the Clock improvements, I've also added the Screen.get_resolution method to retrieve the user's desktop resolution (useful for automatically deciding how large to make the Screen). Thanks to Stephen Paul Weber (singpolyma) for the suggestion and for the initial patch!

There are also a few other smaller changes, so you may want to have a look at the NEWS for the full release notes.

Full docs are online at docs.rubygame.org. Source tarball and gem are available for download at Rubyforge and download.rubygame.org, or you can install with gem install rubygame.

Enjoy!

Rubygame 2.5 Tomorrow

I ended up having to do some not-so-minor changes to Clock today (to satisfy my OCD rigorous Quality Assurance procedures), so I didn't quite have enough time to prep the Rubygame 2.5 release tonight. The code is done (pending further review in the morning), it's just a matter of packaging it up and posting to various sites and mailing lists. I'll take care of that in the morning.

Rubygame News (2.5 & 3.0)

Alright, in typically me-ish fashion, "coming soon" has turned out to be over a month. A rushed and stressful work project that was supposed to last 4 weeks, has dragged on for 8 due to technical troubles, but it's finally coming to a close, and I'm taking a much-needed vacation from that, and tending to other things that I have neglected in that time. That means:

  • Rubygame 2.5 this weekend. The code is finished, but I'm still finishing up the Clock tutorial.
  • Tending to the web site and forums, fixing and cleaning stuff up, and adding more information. Possibly adding a wiki?
  • Writing more tutorials.
  • Possibly finishing the Rubygame mascot.
  • Releasing a few new micro-versions of Rebirth.
  • Planning and working on Rubygame 3.0.

Rubygame 3.0? Whuzzah huh?

I've been feeling inspired to hammer out Rubygame 3.0, which would be the first break in backwards compatibility in almost exactly 2 years. This will involve cleaning out a lot of cruft and warts that have been revealed over the years.

It will also, most likely, involve finally ditching SDL_gfx for SPriG. I recently stumbled upon SPriG, which seems to be an updated and trimmed down fork of SGE. Overall, it looks like a much nicer library, containing a great many useful features that SDL_gfx has been missing, and I'm looking forward to testing it out.

Assuming it works out alright, you can expect some sweeping improvements to the Rubygame drawing system.

Poll: What Rubygame Tutorials Should I Write?

I'm considering about writing some guides/tutorials about specific aspects or features of Rubygame, to help people understand how best to use them.

To help me get an idea of what topics I should write about, I'd like to know which topics you'd most like a guide for. In other words, which topics would you benefit most from, either clearing up confusion or improving your skills?

Vote in the forums, or leave a comment here!

Rubygame 2.5 Coming Soon

The improved Clock code is more or less done now (it's currently in my next branch on Github, if you're curious). The changes so far:

  • Clock.wait and Clock.delay work better in multithreaded apps (when given a yield value).
  • Added Clock#granularity and Clock#yield attributes to tweak the delay used in Clock#tick.
  • Added Clock#calibrate_granularity (whee, long English method names) to calculate a good granularity for the current system. This reduces unnecessary CPU usage a lot on systems with accurate timers, especially Linux and Mac.
  • The framerate monitoring code for Clock#framerate is much improved, giving more accurate and responsive results.
  • Added the ClockTicked event class. Use Clock#enable_tick_events to make Clock#tick return events instead of raw millisecond times. ClockTicked has methods for getting the tick time as milliseconds or seconds.
  • Added a new TickTrigger event trigger class. You can use it in your event hooks to detect ClockTicked events.
  • You can use the symbol :tick as a trigger in HasEventHandler#make_magic_hooks to easily create a TickTrigger.

One further improvement I'm considering is caching ClockTicked events in Clock#tick. So, basically, Clock would keep a hash of ClockTicked events for each distinct value (integer milliseconds) and just return references to the existing one instead of creating a new one. That should help keep Ruby's garbage collector happy.

I should probably create some specs/regression tests for Clock, too.

I also need to look at other changes to possibly include in 2.5:

  • shawn42 created a cool method for drawing thick lines that might be worth including, possibly ported to C.
  • singpolyma made a function to get the resolution of the user's display, but due to the sillyness of the underlying SDL function, it only works the way we want it to if there's not a Screen open. I'm not sure how I'll manage to impose consistency on it. Maybe have it return nil or raise an error when there's an open Screen?
  • I've had a couple event hook/handler improvements floating around in my head, like named hooks and make_magic_hooks_for (which works like make_magic_hooks, but with a hook owner other than self).
  • I might write a brief guide to using Clock most effectively.

Anyway, I have some free time this weekend, so Rubygame 2.5 should be out Saturday or Sunday evening.

Tick Tock, A Better Clock

Things have been ominously quiet here on the blog the past two weeks! I've been busy with work lately (shocking, I know), but I set aside some time the past few evenings to work on Rubygame.

Yes, working on Rubygame. And if that isn't enough to shock you, what if I told you there'd be a release coming in the next few weeks, featuring some nice improvements to the Clock class?

It started out as Rebirth work, actually. I had been working on a new clock class, with numerous improvements: less stupid framerate calculation, compatibility with multithreaded ruby apps, and returning ClockTicked events when you called #tick, instead of raw milliseconds. Most of this was actually done months and months ago, as part of the "long lost Rubygame 3.0". Just as I dug up EventHandler and polished it up, I've been doing the same with the improved Clock.

Since I wanted the new Clock to be safe for multithreaded ruby apps, I couldn't just use the SDL_Delay C function any more, since that stops all ruby threads, not just the current. (This was pointed out to me a long long time ago, actually.) So instead of SDL_Delay, I figured I'd use Ruby's sleep method. Although it only returns integers, sleep will accept and function properly for floating point numbers, even small ones like 0.1. In those cases, sleep will return 0, which isn't very useful, but you can get the actual time difference quite simply:

def float_sleep( t )
  start = Time.now
  sleep t
  return Time.now - start
end

And in fact, this method can be quite accurate on certain systems, like mine:

>> float_sleep( 0.01 )
=> 0.010077

Not bad, eh? Unfortunately, that accuracy is not universal; it varies with CPU and operating system. Values on some systems can be several milliseconds off. For example, sleeping for 0.01s might actually sleep for 0.013, or 0.016, or even 0.02.

Being a few milliseconds off probably wouldn't be a problem for certain types of apps, but in a game the delays themselves are measured in milliseconds, and happen many times per second, every second. (An inaccuracy of 4ms per frame can mean the difference between 60 frames per second and 50.) Even worse, it's not a constant amount that you can compensate for, it's different each time you sleep, and that means the game framerate would be fluctuating all the time.

SDL_Delay has the same problem, actually, which is why Clock.delay uses a brief spinlock (empty loop constantly checking the time) at the end to get more accuracy. But, trying the same approach in ruby code actually makes the accuracy worse, perhaps due to some overhead with loops, or time checking, or both.

So, ruby sleep was not an option, but I still wanted to find a way to make Clock.delay work with multithreaded apps. Fortunately, Julian Raschke, author of the excellent Gosu game library, suggested an approach: use a loop to break up the SDL_Delay into smaller pieces, and call rb_thread_schedule between each chunk to let ruby keep running the other threads.

Hats off to Julian, because it has worked like a charm! Starting in Rubygame 2.5, Clock.wait and Clock.delay will take an additional optional argument to specify the number of milliseconds between each call to rb_thread_schedule (so smaller values run the other threads more often). It can also be false, the default value, to make them behave as they do in 2.4 and earlier (pausing all threads).

There will also be some other improvements to Clock:

  • A better algorithm for calculating framerate. (The current way is very stupid.)
  • More options for balancing CPU usage and accuracy, including the option to use Clock.wait instead of Clock.delay for framerate limiting, and an automatic calibration method to find the ideal granularity for the current system.
  • An option to have #tick return a ClockTicked event instance, which will have methods for retrieving the tick time as either milliseconds or seconds. There will also be a new event trigger, TickTrigger, to go along with the ClockTicked event.

As mentioned, the new version should be released within the next few weeks, and will be backwards-compatible with previous versions.

Rebirth 0.6

I finished Rebirth 0.6 tonight. This version adds the GameObject class, which is the base class for objects in the game and on the screen, such as characters, items, missiles, and so on.

In addition to adding the new class, I also did some more refactoring, and made a new mixin module, Drawable, which handles the OpenGL transformation voodoo for GameObject and Shape.

The demo for this version looks the same as before in a screenshot, but you can now control the box with the numeric keypad! The keypad's arrow keys (2, 4, 6, and 8) move the box (down, left, right, and up, respectively). Keypad 7 and 9 rotate the box counterclockwise and clockwise. Keypad + (plus) and - (minus) make the box larger or smaller.

It's not the most impressive demo in the world, but it's nice to be far enough along that I can control objects on the screen. At this point, it would be possible to recreate Pong with Rebirth. How exciting! ;-D

Regarding the depth issue I blogged about last time, I decided to go with the lazy way. Not because it's lazy, but because it's consistent with software like Inkscape / SVG and Flash. After thinking about it, I realized that I've been half-subconsciously modelling the graphics system of Rebirth after SVG. Rebirth's GameObjects correspond to SVG's groups, and Shapes correspond to the various SVG shapes.

Inkscape and SVG have also influenced my plans for shape styles. Shapes will have "fill" and "outline" styles, which can (eventually) be solid colors, images/textures, and perhaps gradients (depending on how confident I'm feeling about my OpenGL skills). You'll be able to control how thick the outlines are, of course, and maybe line stippling (dotted/dashed lines).

I do have two small concerns about Chipmunk integration. The first is that Chipmunk has support for circles, but not for ellipses (ovals). Since Shapes and GameObjects can be squished and squashed and sheared, I'll need to be able to approximate all shapes as polygons, with the transformations applied (glUnproject might help with that). The second is that Chipmunk doesn't support hierarchical objects, so I'll need to figure out how I'm going to handle that. Perhaps just make so that all shapes and children of a physics-enabled GameObject form one body.

Anyway. The next version is supposed to be adding the Circle class, but I might do some rearranging and update the plans, since I've noticed Rebirth is missing a central class to hold the game together as a cohesive unit. Long ago, I called that class Game, and it held a clock, event manager, camera, and world filled with sprites. I'll probably come up with a different class name (to avoid confusion with the GameObject class), but the general idea is the same.