Saturday, October 25, 2008

Ghosts and Goblins

Since I've been using Ruby to prototype games, I'm starting to find that it is a good idea to build a minimal framework for certain types of game (catch, platformer, driving, etc.) so that I can very easily make simple games out of them. For Halloween, I took my catch game and turned it into a simple platformer about trick or treating. (you can get to the download for it from my portfolio)

To keep this game simple, I imposed a two day limit on development. It wasn't hard since I already made a nice little system for sprite animations and collisions between rectangles so all I needed to do was build up some finite state automata to drive the items, make some images and figure out some simple gameplay mechanics.

To overcome the difficulty of distributing Ruby projects to friends, I used RubyScript2exe to bundle up Ruby, necessary libraries, scripts and media. This works great with the given variables to help give full path when you need to open files at runtime.

Since I can't really draw, I figured I'd use Inkscape to create the artwork. It turned out pretty well. I realized that I can draw using vector programs when I made a tiny vector drawing script on Graal, of course I still can't draw well but it works when the style is relevant.

Next time I might try Flash so that I can build some animations, but we'll see how that works out.

For sound, I used a track from Colugo - Music For People. I've been wanting to use some of his stuff since it all sounds like great game music. Obviously I'll have to get permission if I use it for a larger game.

Thursday, August 28, 2008

prototyping with Ruby and Gosu

Now that summer is over and classes are starting again (except now I'm in graduate school) I've decided to become productive again. Go figure.

I'm using Ruby with Gosu to quickly develop prototypes to test out gameplay mechanics.  The first image above is a simple catch game using my boxman character I used in a TGEA game.  Nothing special, just some sprite animation and makeshift rectangle intersection stuff really.  I recently finished developing a cellular automata engine for the Ruby programming language.  You can find the project on GitHub here (I'm still more of an SVN kind of guy, but we'll see how this turns out).  I made this for two reasons: for one I haven't written a C.A. engine before, and two I needed something to test complex rules with for our game idea.  

The game itself is fairly interesting itself in terms of design.  Basically you build a "virus" out of cellular patterns to compete in some pairing with another player to see who's pattern spreads the fastest.  If we go with the iPhone or some other mobile device as the platform for this, then we can bring in another level of viral spread.  Battles can occur in some peer to peer fashion based on locality.  I.E. you can battle people at whatever public area you hang out in.  If we add a server to this mix, then we can track different data on people's virii such as wins, longevity (duration of winning record), spread (real-life spatial), whatever and display this in some form.  

In developing this library with Ruby, I ended up learning a few things along the way.  Mostly getting to know the inner workings of Ruby itself, such as how, {|i| i})

only evaluates the inner block once.  Since I took a course last semester that dealt with functional programming, I can now make use of really cool language tools like lambda functions.  It just so happens that Ruby's functional features are quite robust. 

For my graduate research I am developing a simulation to mimic human behavior in an environment with several different types of sensor networks.  This is to help with an eldercare project meant to bring computational intelligense into automated systems that can detect urgent needs or various lifestyle needs of people living in eldercare facilities.  

By providing formal input describing daily behavior, my system will be able to simulate days, months, or even years worth of data collection by the sensor networks used by the eldercare system.  By doing this, other research that attempts to understand that data can use the input for supervised learning.  

At any rate, so far it has allowed me to start using JSON/YAML parsers such as TinyJSON and Ruby's built in YAML parser.  TinyJSON is interesting since it makes use of Boost's Spirit library to provide a lightweight but powerful JSON parser.  Unfortunately there is a slight lack of documentation for the parser, but with a little elbow grease it's not hard to figure out.

level = boost::any_cast<>::object >::object >(*v);
m_iUnits = boost::any_cast<>(*level["unitpixel"]);

Turns out that the json::grammar::object is a std::map which works perfect for JSON data.  v above is a variant type that is used to hold the entire JSON object, which you can see on the given documentation.  The real trick is pulling data out of array types.  Luckily there are iterators provided and you can cast them similarly as the variant type if you're like me and create arrays of objects often.  

Figuring this out was interesting for me since I haven't had a chance to really dive deep into template programming in C++, so debugging my code was a real treat with that incessant type syntax.

Saturday, April 26, 2008

Mark of the 1.0

I am finally prepared to call my current build of "Circle Game" (now "Spherical Prison") version 1. For some reason, I'm a fan of giving the major numbers to the major releases. This release is the one that I will call "done".

After taking the time to fix a few hack solutions with proper solutions (i.e. using a boolean to determine if the player has entered the editor to invalidate scores instead of making the score infinity, using a list to buffer the collision callbacks instead of just using the first, etc.), and committing to a decision on what levels I should include, I'm happy with the result. As far as the level editor goes, it is not viable for community sharing. I found that even with making my scene dynamic, it would still be quite a bit more work to add methods of filtering keys from walls for deleting and rotating objects. There are member data fields inside the box2D objects that fit this need, but even with that I don't feel that the implementation would be clean in the end. The design I chose did not account for sufficient separation of actions pertaining to modification of objects in the scene.

Today I've also completed my configuration for the Xcode project, so I have a fully functional Mac version that is a duplicate of the Windows version. Aside from this, a good friend of mine (who would wish to be reffered to as "Z-Dawg") wrote up a makefile for the project for easy building in Linux. So, fortunately, I'm able to say that using cross-platform libraries has enabled me to build my first totally cross-platform windowed application.

For now, I must begin channeling my game through the library communities (at first) and then see what else I want to do when I get a web page up for it.

Sunday, April 6, 2008

Onward to level design!

Okay, maybe not quite so energetic.
This weekend let me get a number of things done. Now the menus are about 95% complete, and I have the first three levels pretty well set.

The first level gives the player a chance to get a feel for the movement. Just rolling around and letting the physics do the rest.

The second introduces the bounce and sticky walls. By changing your speed you'll hit the wall at a different angle and thus be shot off at different angles. So far everyone that's played the level has figured it out, so I'm definitely keeping the design. The only problem with this one is that hitting the walls just right takes a bit of practice. When you shoot up to the top, you can only get back down by pressing up to shoot your self off of the stage, which adds ten seconds to your score. So the strategy is to get the lower one first.

The third introduces the magnet wall. It's a pretty simple concept, but the design of the level gives a number of options for shortening your time.

Through some testing with my friends, I'm pretty happy with the designs. I'm still not entirely sure of the difficulty of the second, but I think I can overcome this with some sort of message shown to the player during gameplay. Of course, with levels I needed to finish the logic for "winning" the game. So now I have a place for credits and high scores.

The high score list shows the top ten total scores, and lists the player's initials and score per level. This is stored in a binary file (which is just a struct written out and back in) so it will persist.

Something worth mentioning is that I used DropBox to share the executable with my online friends. Doing this introduced an interesting type of concurrency to the game. As the files shared are synchronized across computers, each player was logically using the same files to play. This meant that the scores data file was shared too. Because of this, I could no longer leave a pointer to the file open while the game was running (bad design anyway). After fixing my design, however we still noticed that if enough people were playing, and finishing the levels quick enough, the files may not sync fast enough to prevent overwriting. There's not really much I can do about that, but it was still interesting to try and compete with each other.

Things still left to do are:
build an in-game level editor (extend the lifetime of the game)
finish the rest of the hardcoded levels
animations for the man, and likely the walls

Tuesday, April 1, 2008

Refactoring, and moving towards level design

Even though classes are back in session, right now all I want to do is build my game. It beckons me when away, and teases me when I play... (this is why I don't blab in these things...)

I just finished some refactoring, I had let myself put the world and player management inside the main class instead of the scene. Now they are where they belong, and I have legitimately separated collision callbacks from distance checks for the walls' interactions with the player. As it stands now, every wall type except sticky is near complete. After I take the time to create some animations, they should be good. I'll have to check my color choices to see if they work alright with common color blindness, or if I need worry with the choice of animations. I figure that this project ought to be as polished as possible, since the complexity of it gives me that option.

Shown here is my little test level. The absense of a clear cut or even sensible strategy should be a dead giveaway.

Tuesday, March 25, 2008

Circle Man

Finally, spring break is here and I can devote some time to game development!

This semester has me fairly busy with web development, fuzzy inference output analysis, and so on. Which is why I'm excited to start working with Gosu to build some quick PC games. This project is also going to use Erin Catto's Box2D library. If you are not familiar with either of these, you owe it to yourself to take a look. Myself and Mike Daly (who worked with me on the DS homebrew 2d physics project) are the only ones working on this project.

The premise of this game is that you are this stick man stuck in some sort of bubble. You are able to roll it around, and are for some reason in these environments with wall portions ("interactives") that physically alter your movement. As of now, there are four types of interactives:
Bounce - propels the player away from the wall
Magnet - alters gravity to pull player toward wall while against it
Push - keeps the player from touching it
Sticky - player will stick to these, and be able to swing from them to access certain areas
With these, we hope to create an interesting play experience. The goal of the game is to find all of the "keys" (right now I don't care what they are, just that you collect something) to escape from your spherical prison.

With this project, we finally get to use C++ and test our previously inactive knowledge of the language. So far, I've established a simple class hierarchy for our levels, player, walls, and "key" objects. From a brief standpoint, these classes have four main member functions: the constructor, update, render, and destructor. I'm hoping to keep the high level logic very clean, and keep all the actual play logic inside the classes. This entails that the level objects handle any and all wall object logic (all physical operations that do not operate on callbacks, and rendering). There will likely be some helper functions created, and some variants established during the optimization phase of development.

Tuesday, March 4, 2008

the Web, and its desire to be useful

It turns out that this semester is a busy one, leaving me with no time to persue game development (thus far). In the meantime, I might as well document some of my web development.
Currently, I am working at the Center for eResearch here at Mizzou. I am basically an intern hired to develop a video sharing web application for the University that will soon go beta. So far, I've written Ruby scripts making use of ffmpeg to automate encoding of submitted videos into FLV, MPEG, MP3 and iPod compatable MP4 formats, and a fully functional web application to facilitate sharing. Here is a quick rundown of the requirements for this application:

Students and Faculty are allowed access and can be granted administration to channels for upload of videos. Channels are delegated to schools, departments, student groups, major events, among other things. Only through owning or being a contributor to a channel can you upload video. Anyone can register an account to subscribe to channels. A subscription lets you keep up to date with a channel so you know when new videos are uploaded, new events are scheduled and the like.

As far as technical details, I will briefly discuss those here. This project is a Ruby on Rails project, effectively this means that it is a rapid development, rapid prototyping, web 2.0 eager application. The one problem with the use of "rapid" here is that this is my first Rails project, so it has taken me six months to build it up this far. Albeit, I could not have done so much in PHP given my student work schedule (10 hrs/week). Aside from Rails, we are using MySQL and of course the Prototype and Javascript libraries as these are included in Rails.