Rebirth 0.6
(February 26, 2009 @ 02:01 AM)
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.
Deep Thinking about Shapes
(February 24, 2009 @ 02:22 AM)
I’ve been getting into the real meat of the GameObject class today: drawing shapes and children. Unfortunately, I’ve run into a little tangle that I need to sort out before I go much further.
A brief explanation GameObject first. GameObject is analogous to Rubygame’s Sprite class, in that it’s meant to be the base class for space ships, dragons, penguins, and whatever else you can see on the screen. But it has some important differences.
A GameObject itself is not visible, but rather holds Shapes, which are visible and have colors, styles, textures, etc. Shapes are boxes, circles, lines, 2D polygon meshes, and maybe some other things of that nature. In addition to appearance, shapes will be the base for collision and physics, once I integrate Chipmunk.
Also, GameObject is hierarchical, i.e. each object can have child objects (and those can have children, and so on). The children inherit the parent’s transformation, and can add their own local transformation. So if the parent is at position <-3, 0> (global space) and the child is at <-1,0> (local space), the child will appear to the user to be at <-4, 0>, because its position is relative to the parent. So, you can make a character out of multiple objects (maybe one for the head, one for the body, and so on), or make a katamari ball that other objects stick to and rotate with, or whatever else you want. Thanks to OpenGL, it’s all extremely simple to program.
But, as I said, there’s a snag. Shapes all have depths, to decide which shape appears in front of the other. If shape A has a depth of 50, and shape B has a depth of 25, B is closer, so it should be in front. But I hadn’t thought about how shapes in separate GameObjects relate to each other. Do GameObjects have depths? If they do, and object O is in front of object P, but O’s shapes are deeper than P’s shapes, which shapes draw in front of each other? Or what if O and P have multiple shapes, with their depths alternating like two stacks of cards shuffled together?
There are two ways I could go. The lazy way is to just say that Shape’s depths only apply within the GameObject, so all shapes of the nearer object will appear on top of all shapes of the deeper object. In this case, it’s very simple to do: just render each object in the scene by descending depth, and within each object render its shapes also in descending depth. It’d just be a matter of sorting, really.
The less-lazy way is to say that GameObjects don’t have depths, and only the Shapes’ depths matter. But in this case, I have to maintain a list of all shapes in the scene, regardless of which object they belong to, sorted by depth, and then draw those in order by descending depth. (For those of you familiar with graphics rendering and wondering why I don’t just use the depth buffer: I can’t. Shapes can have partially transparent textures, and those wouldn’t render correctly if I relied on the depth buffer.)
The first, lazy way has a disadvantage, which is the snag that caught my attention and started this train of thought: how is an object sorted relative to its children? Do the children go in front? Or behind? Well, really, you’d want to choose on a case-by-case basis, but then I have to think about a relative depth system. (Hrm, actually, it wouldn’t be too hard – parent depth is 0, children can have negative depths to be in front, positive to be in back.)
Also weighing in is an advantage of the second way: shapes exist in a consistent, cohesive world, where depth is absolute. This feels “cleaner” to me, and it would also allow for neat stuff like having a shadow which is part of the object, but will always appear behind other objects. (To do something like this with the lazy system, you’d need to have the shadow as a separate, deeper object that follows the main object around like, well, a shadow.)
Either way would be fine for most games, so it’s just a matter of deciding whether the effort to redesign things and implement the second system is worth the cleanliness.
I’m going to sleep on it. But if I were going to choose right now, I’d go with the first way. It’s simpler, and has a certain hierarchical appear.
Rebirth 0.5
(February 20, 2009 @ 02:45 AM)
I finished up Rebirth 0.5 tonight. There’s not much to say about it that I didn’t say last time: there’s a new Vector class, and Camera and Shape’s position, rotation, and scale attributes can be changed. This version is tagged as release-0.5 on Github.
The demo for this one looks the same as for the last version, although I did try a little test where the box could be moved with the arrow keys. Shapes aren’t meant to be controlled directly like that, though, so I didn’t keep it. I’ll add it back properly next version, once I implement the game object class.
Rebirth Progress
(February 19, 2009 @ 04:22 AM)
The super-charged motivation I’ve had the past few days is starting to dim, but I think I’ll be able to get another one or two versions of Rebirth released before I need to take a mini-vacation from it.
Tonight I was working on the Vector class. It was copied over from my old work on Rubygame, but I took the time to create specs for it, one method at a time, testing along the way. Probably a waste of time since the class was already done and I could have just written all the specs in one go, but oh well.
I’ve decided to insert one more release before the Gob version. This next version will have the Vector class, and the Camera and Shape classes’ position, rotation, and scale will be modifiable, and position will use Vector. The code for Camera and Shape’s pos/rot/scale attributes were identical, and Gob’s would be too once I wrote it, so I decided to refactor it out into a new mixin module (HasTransform) to keep things DRY.
I also implemented some convenience / utility functions, the most interesting of which is need, a clever wrapper for require that takes relative paths. Credit for the cleverness goes to Drew Olson, who made a library with a similar function. I didn’t want to add a dependency just for one simple function, so I wrote my own version (which is probably nearly identical; there aren’t too many unique ways to write it):
1 2 3 4 5 |
def need( &block ) require File.expand_path( block.call, File.dirname( eval( "__FILE__", block.binding ) )) end |
It’s used like this:
need { "vector" } # requires ./vector.rb |
The cleverness is that it uses a block (note the curly braces) to capture the current state at the time the block was created, in the file that called need. This allows you to write the need function in one file, but have it access the __FILE__ variable from the calling file. Crazy!
Anyway, it’s 4AM, and I’m rambling. I expect to finish up Rebirth 0.5 tomorrow (er, today).
Rebirth 0.4
(February 17, 2009 @ 07:14 PM)
I had a burst of inspiration this weekend, so I hammered out Rebirth 0.4, which adds the new Camera class.
Much of the code was borrowed from my earlier forays into OpenGL and higher-level game frameworking. One major different is that, since I’m not attempting SDL support (as I was going to when these features were slated for Rubygame 3.0), I can take advantage of OpenGL’s transformation code, rather than implementing my own Transform and Matrix3 classes to calculate how objects look from the camera’s viewpoint. I might have to borrow them later, to transform mouse clicks into world and object-local coordinates, but gluUnProject seems to do that already, so I’ll have to investigate how to use it in ruby-opengl.
One amusing thing I noticed is that I haven’t added any support for modifying the position, rotation, or scale of shapes or cameras – there are readers, but no writers. Obviously, that’s no good in the long run! I decided to leave it that way for 0.4 to keep the release small, but I’ll be adding that in for 0.5, which will also have the game object class (which I think I’ll call Gob). Game object is analogous to Rubygame’s Sprite class, except that instead of having an image and a rect, it’s made up of Shapes; it will also correspond to Chipmunk’s Body class.
I do need to implement a proper 2D vector class (I’m just using [x,y] Arrays right now). I’ll probably clean up Ftor for it, then later switch it to be based on Chipmunk’s vectors, once I add physics.
I also need to add proper color support (I’m using [r,g,b,a] Arrays now). I’ll probably extend the Rubygame color classes to have a “to_opengl” method that converts them to the format used by OpenGL. I’ll need a general conversion method too, so that I can run any symbol, string, array, or color through the converter and get a valid color back (or else raise an error). I might extend the OpenGL functions that take a color to do that conversion automatically, if I’m feeling particularly peppy. If I do, I’d use a mixin module so that the new methods can just use super. (Isn’t ruby great?)
The demo for 0.4 looks pretty much the same as it did for 0.3, but the camera viewport deliberately doesn’t fill the entire image, to demonstrate that you can make cameras that only draw on part of the screen. This would be useful for having two screens side by side, for example with a 2-player racing game.
This version is tagged as release-0.4 on Github.
Next version is Gob (game object), then Circle, then Color/Style, then Line, then World – after that, nothing’s planned, so I’ll be thinking about what’s after that. Probably the Game class, which manages the flow of the entire game, keeps track of objects in the scene, cameras, the view, global event manager, etc. I’m not sure when Chipmunk will come in.
Rebirth 0.3
(February 15, 2009 @ 06:53 PM)
Finished up Rebirth 0.3 today. This version is quite a bit heavier than the previous two, but still just light enough to be called a micro-release. It adds two new simple classes:
- Shape, which is the base class for all shapes in Rebirth. It implements
@pos,@rot,@scale, and@visibleattributes, and handles the OpenGL matrix stuff for transforming the shape. - Box, which inherits from Shape. It draws as a square or rectangle, depending on whether @scale is the same or different on x and y. It overrides
#_drawto provide the OpenGL calls for rendering the polygons in local space.
I also made a mixin, HasEventHandler, which extends Rubygame’s mixin of the same name to add a new method, #make_magic_hooks_for. It’s just like HasEventHandler#make_magic_hooks, but uses the specified object as the hook owner. I’m planning on adding that method for the next release of Rubygame.
The demo for this version just shows a white rectangle. The background is purple (instead of the promised black) so that I could tell the screen was being cleared. Here’s a commemorative screenshot; it’s not much to look at, but you can click for the full image.
Like the other micro-releases, there’s no download for this, but it’s tagged as release-0.3 on github.
The next version was slated to be GameObject (i.e. Sprite) – not Circle, as I had thought – but while working on this version, I realized I needed a Camera class to see anything on the screen. I implemented a basic camera class in the demo, but I’m going to make the next release Camera, then GameObject, then Circle.
Rebirth 0.2
(February 09, 2009 @ 12:16 PM)
In addition to Rubygame 2.4.1, I finished Rebirth 0.2 yesterday.
I’m continuing with the “micro-releases” concept for Rebirth. This version adds just one feature, and it only took a couple hours to write: the EventManager class. It’s basically an EventHandler with a built-in EventQueue. Nothing too special, just another milestone (or inchstone, maybe) towards a complete game framework.
There’s also an exciting new demo for this version: a black screen that quits when you press Q. The demo for the previous version was a black screen that quit after 10 seconds. The next version will add a white rectangle. Excitement ensues!
There’s no source drop for this release, and there’s nothing interesting enough to warrant downloading it, but it’s tagged for posterity as release-0.2 on Github.
An aside: I’m really glad I had done so much planning back in June, when I was just starting Rebirth. It has been so long since then that I would have had no idea what to do today. Having the plans and roadmap set out already really helped me remember the direction I wanted to go, and let me focus on what to do next. It also lowered the mental barrier to re-entry, since I didn’t have to dread the unpleasant task of trying to remember what was going on back then.
So: Planning. I wholeheartedly endorse it.
What's going on with Rubygame?
(February 05, 2009 @ 12:37 PM)
The answer to that question is: Not much for a long time, but some things soon.
I rather abruptly dropped off the face of the planet immediately after the 2.4 release back in October, at least as far as Rubygame was concerned. I didn’t even stick around to arrange for someone to take over. I was gone. Poof.
Well, not really. I was still around, still reading my email (but rarely responding), and still following a handful of Ruby blogs. I even did a little bit of Rubygame development: Ruby 1.9.1-preview 1 came out less than a week after Rubygame 2.4 (coincidence?! … yes :P), and I made some tweaks to Rubygame to try to make it compatible. I never pushed those revisions, and I can’t remember whether or not I got it completely working. If I recall correctly, I ran into some issues with having 1.8 and 1.9 installed side by side, and things like Rake and Gems not wanting to cooperate.
Aside from that, though, I pretty much avoided anything having to do with Rubygame. I was tired of it, and I had a big, exciting new hobby project to start swimming in. That project is unrelated to Ruby or games, and I won’t be writing about it either here or on my personal blog. It’s still ongoing (and probably will be for years), but it’s getting mature enough that I don’t have to nurture it every day. Plus, I have a project partner to help out and provide support, a luxury I never had with Rubygame. (I did receive patches from time to time, and I did and do appreciate them, but it’s not the same thing.)
But as exciting as the other project is, my calling is to interactive media design (“video games”), and Ruby is still my programming language of choice. (Sadly, I don’t get to use it on the other project, because we’ve inherited a code base written it C++). So I find my thoughts these days drifting back to the desire to write games in Ruby.
The sad irony of Rubygame is that I never got around to actually using it much; my energy was entirely on making it. Well, that’s going to change. I’m retired from being Rubygame’s developer, so I’m going to start being one of its users.
I have decided, though, that I will stay on as Rubygame maintainer. And I really mean strictly maintenance: sweeping away the dust, applying patches, maybe fixing a bug once in a while. I’ll probably finish up the Ruby 1.9 compatibility fixes (since 1.9.1 was released recently). But I won’t be developing new features. (I’d still like to find a developer with the enthusiasm and energy to push Rubygame into new territory, as I wrote back in October.)
Mostly, I’ll be working on two things: a game, and Rebirth (which will probably get a new name). I’ll be developing Rebirth as a support library for my game, so they will grow with each other. When my game needs some new feature, it will either be added to Rebirth as a general library, or else it will start in my game and then, after the feature is done, be extracted and put into Rebirth.
In case you’ve forgotten (or never knew), Rebirth will use OpenGL for graphics, with Rubygame underneath for stuff like event handling and image loading. Eventually, it will have physics support using Chipmunk. I’m toying with the idea of OpenAL audio, but Rubygame’s basic audio support will be fine for starters, and I don’t want to get occupied developing a Ruby OpenAL library, too.
On rare occasion, some of the work on my game or Rebirth might make its way back into Rubygame. For example, I intend to brush off the improved Clock class I developed as part of the mythical Rubygame 3.0 so many moons ago. Once that’s done, I might submit it as a patch to be applied to Rubygame (as crazy as submitting a patch to my own project seems).
For those who are curious about the game I’m planning: it’s going to be an ambient music creation toy, inspired by (but not a clone of) Toshio Iwai’s Electroplankton. I’ve had ideas about this floating in my head for many years, and it’s time to bring it to life. Let’s hope my pessimistic prediction in that old blog post doesn’t come true.
Assuming I actually go through with this, I’ll be blogging about the game over at my personal blog. Rebirth news might be over there too, since it’s not really Rubygame. Although, this blog would get rather lonely. We’ll see which way it goes.
Rebirth & Rubygame, Together Forever
(June 10, 2008 @ 12:32 AM)
I’ve decided on the relationship between Rebirth and Rubygame. Or rather, the relationship came naturally, and it seems agreeable, so it’s the direction I’m going to go.
In Rebirth 0.1, the View class wraps around Rubygame’s Screen class with a different API. As you can see in the source, View just sets the screen mode, then stores the Screen as a class variable. (Right now it doesn’t do anything with it, but it will for setting title, etc.)
This arrangement came out of simple laziness – I did the least amount of work to fulfill the specifications of the View class. And it works really well having Rebirth sitting on top of Rubygame. Rebirth can be pure Ruby, and take advantage of Rubygame’s features – opening a screen, loading images, getting events, etc. Features that Rebirth doesn’t need (Rects, Surface blitting, etc.) it can just ignore.
What this means is that Rubygame will continue to develop on its own, and Rebirth will be a new based on top of it. This is good for both libraries, in fact:
- It keeps my interest and motivation up, because I get to work on something new and fresh.
- It gives me an excuse to use and improve Rubygame as well, adding new features I need for Rebirth.
- It won’t interfere with games that are just using Rubygame (no major backwards compatibility breaking).
So, that is the happy news!
Rebirth 0.1
(June 09, 2008 @ 09:17 PM)
Rebirth 0.1 is done. All it can do is open and close the View (equivalent to Screen in Rubygame – in fact, built on top of Screen). So, you probably don’t want or need to download it. It’s immortalized as tag release-0.1 on Github.
0.2 will be done when keyboard events are done. 0.3 will add a Rectangle class, so there will actually be something to see. You can read the ROADMAP to see the rest of the releases that are currently planned (up to 0.8 so far).
Rebirth News
(June 04, 2008 @ 02:50 PM)
Two bits of news about Rubygame and Rebirth today.
First, I laid out some goals / guiding principles for Rebirth. I don’t know if they’re of interest to anyone else, but here they are:
Ease of use. It should be natural to express game behavior, without needing to jump through hoops. Use of defaults and constraints to suggest a course of action and reduce the “burden of choice” on developers.
Flexibility. Rebirth should be able to handle games of many types and genres; physics or non-physics, action or slow-paced.
Object-oriented. It should focus on game objects and how they behave and interact, not on the mechanics of image blitting and event management.
Examples. Plenty of running example games to help users get started and see how the library can / should be used.
Documentation. Every module, every class, every method documented, plus tutorials with examples about various important concepts and features.
Behavior-driven development. Spec first, then implement. Full spec coverage, master branch is always green.
Small, incremental releases. Every feature should be a release, very release should add or refine a feature. Avoid build-ups.
These goals (especially 3, 4, 6, and 7) reflect what I consider to be Rubygame’s shortcomings.
Second, it’s becoming more clear that Rebirth could be just a layer on top of Rubygame and ruby-opengl. In fact, that’s just what I did last summer, in the original Rubygame 3.0 branch. Really, the work I’m doing now is just another refinement of the ideas that I was thinking last summer. (There’s probably some good code I can lift from that branch.) So, it might be that Rebirth will be an add-on to Rubygame, rather than a replacement.
There’s also the possibility of incremental revisions to Rubygame to bring it closer to my goals with Rebirth. The problem there is that it’s a slow process, and that carries the risk of losing interest. It would also lack the freedom to make radical changes that you get with something new.
Github Project for Rebirth
(June 01, 2008 @ 09:10 PM)
I’ve set up a Github project for Rebirth. There’s not a whole lot to see there yet – the bouncy ball game, a partially complete paddle ball game, and some not-implemented specs for event hooks and shapes. But you might be interested to take a look at the style so far.
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:
- Continue adapting the current Rubygame, adding new things and deprecating older things, slowly and incrementally progressing towards a better Rubygame.
- Start over with Rubygame 3 as a whole new creature. Scrap the old library, leave old apps in the dust.
- Start a new, separate library to implement this new vision. Rubygame continues on its own.
Food for thought.
