Gemini dev update #1
Some of my previous posts regarding Gemini seemed to have garnered some attention thanks to someone posting one of them to DZone (thanks whoever that was). So, since there’s no official home page with nice docs and tutorials and such I decided I would just keep a more public journal of the development progress of Gemini until those things are actually warranted.
Gemini’s secret sauce is the idea that your game logic should not be in a big monolithic while loop. Of course your game needs the basic game loop ingredients of checking for input, updating the game state and redrawing the scene but is a big while loop really the best place for all that? So we started with the idea of game objects as the basic “thing” that exists in the world. Game objects in reality are really just empty containers for you to attach behaviors to, without any behaviors they aren’t really much of a “thing”. So, game objects via behaviors become the centerpoint of the game development effort. To that end game objects support the idea of adding and removing behaviors and behaviors understand the idea of dependencies. With that in place, you can create a game object that has a sprite, can move around and collide with other things and has callbacks for all its events in just a few lines.
class Ball < Gemini::GameObject
Now, this doesn't tell the Ball object, what sprite to use, what to do on updates, what sorts of things to collide with, etc. Behaviors add methods to the game object they are attached to; methods that we can use in the load method to set up all our properties.
# the x= and y= methods are added by BoundingBoxCollidable which depends on
# Movable2D which depends on Spatial which provides the x= and y= (phew!)
self.image = "ball.png"
self.updates_per_second = 30
self.x = rand(640 - width)
self.y = rand(480 - height)
@vector = [rand(5) - 3, rand(5) - 3]
Those self.= calls are there to force the method to be invoked instead of creating and assigning to a local variable. So with that done, the only pieces left to get a bunch of balls bouncing around on the screen is to say what happens on each updated (the tick method gets called by the UpdatesAtConsistantRate behavior) and to say what happens when the ball runs into a wall (defined by anything with a :wall tag).
# The on_ callback system is instance level and thus would be added to the load method
on_collided do |event, continue|
vector = -1 if x > (640 – width)
vector = 1 if x < 0 vector = -1 if y > (480 – height)
vector = 1 if y < 0 end # The move method was added by BoundingBoxCollidable which depends on Movable2D def tick move(x + @vector, y + @vector) end [/sourcecode] So, plenty of hard coded stuff that we plan to swap out for a relational positioning system (0 = left side of screen, 1 = right side of screen) and the collision handler could probably be a bit prettier but it's a start. So where is Gemini today? Well, certainly not in a position to make an actual game with. There's infrastructure for our concepts of behaviors and game objects, there's an internal message queue which allows game objects to communicate asynchronously and in a totally decoupled manner (it's also going to be used for stuff like input handling). The next two components to start hacking on are the input system and a basic GUI system which my associate Logan Barnett will be heading up. Beyond that there are lots of places to hit up for performance improvements including but no limited to moving various parts over into Java based libs. Certainly something computationally heavy like a physics engine would be a great candidate for Java, and thankfully there are several to choose from (plus all the C based ones that have simply been wrapped in Java). So the future is bright, we can already move a good number of sprites around doing collision detection with zero optimizations and the behavior based system appears to have long legs in terms of allowing us to implement everything from keyboard input to playing sounds to moving as part of a cutscene as part of a behavior.