DEV Community

DevGraph
DevGraph

Posted on • Edited on

The Ruby Unbundled Series: Creating Games with Gosu

By Darren Broemmer

There are literally so many treasures in Ruby (specifically avoiding the cliche pun on ‘gem’ here), that it is sometimes hard to choose where to go next for each article. When I started writing this last Friday, I felt like switching gears to something fun, games. This is a topic that likely sparked interest in computers for many of you in the first place.

As a kid, I wrote simple games in BASIC on my Tandy TRS-80. It was great fun and yes, I know, I am dating myself here a bit. Nevertheless, the fact that I could type in some commands and create these interactive realities on the screen was astounding to me. Thirty-five years later, I am still astonished by the things we can do with computers.

However, we often get bogged down in the day-to-day grind of tasks and meetings. This can cause us to lose sight momentarily of the enjoyment of the craft itself. Thus, let’s get back to the pure joy and simplicity of creating something where there once was nothing. The reason I enjoy Ruby so much is that it makes putting together those creations enjoyable, a primary goal of the language’s creator. Mission accomplished!

The Gosu Gem

Many games use graphics of some kind, and the Gosu gem provides a nice wrapper around OpenGL capabilities for Ruby. It describes itself as a 2D Game Developer library, so let’s look at the basics and create a few games. You likely would want to use Chipmunk as well for advanced gaming. It is a game physics engine that easily integrates with Gosu.

I found Gosu to be quite performant on my 2.3 GHz Dual-Core Intel Core i5 iMac. You can quickly create some useful and interesting applications. And why use anything else when you can use Ruby?

All of the code referenced in this article can be found on GitHub. The shell.rb file shown below contains an empty starting point for a Gosu-based application. The update and draw callbacks are invoked 60 times/second, although that is not guaranteed if performance conditions prohibit it. For our games here, we can safely assume we will see 60 invocations each second.

Alt Text

Gosu has APIs to draw images, text, and basic shapes. It uses a top-left coordinate system, meaning that {x, y} = {0, 0} in the top-left corner of the window. Each element has a z-index to provide layering of graphics elements.

Here are the three games we will build. Each progressively uses a few more features of Gosu.

  1. Reaction Time Game
  2. Drawing (technically this isn’t a game, I just use it to practice my digital signature)
  3. Guess the Price of Bitcoin (now we are talking)

Reaction Time Game
This is a topic which has always fascinated me, and the reason for this originates in professional baseball. The time duration between the ball leaving the pitcher's hand to it reaching the plate is approximately 500ms. The average human’s simple reaction time is 284ms. That leaves 216 ms to swing the bat and hopefully make contact with the ball. Sounds almost impossible right?

Malcolm Gladwell in his book Outliers proposes the theory of 10,000 hours is the reason why professional baseball players are still able to make contact and get hits. They have seen the various patterns so many times over hours and hours of practice that they can make these split second decisions and react accordingly. These patterns include the ball leaving the pitcher's hand, the rotation of the ball, and the few points along the flight path that the human eye can see at that velocity. I certainly can’t do it, but I am impressed by those who can hit at that level.

It would be a much longer article if we were to write an actual baseball game, but we can readily implement a simple reaction time test. We will use stoplight images and progress through the colors at random time intervals. The user is asked to hit the spacebar when the light switches to green. We mark the time it switches and calculate the difference to arrive at the user’s response time. For additional feedback, we calculate the percentage above or below the human average. The screen capture belows shows one of the attempts where I was actually faster than average.

Alt Text

The code for this game is only 84 lines. All of the images used in the game are constructed in initialize method, and then rendered in the draw method. Remember that the draw method renders the entire window, as opposed to drawing only delta changes.The initialize code is shown below.

Alt Text

We determine which of the three stoplight images to use at any given time In the update method. This is based on a progression of the @traffic_light_color variable which increases at random time intervals so the user can’t simply time the light.

Alt Text

The update method also determines what messages to display based on the game state. Once these determinations have been made, the draw method is fairly straightforward. The @font.draw_text method on line 40 shows how to add text to your apps.

Alt Text

One thing that surprised me after playing the game a number of times is how often I actually hit the average human speed. Try it and see what your reaction time is.

Drawing App
This is not a game but it does concisely illustrate what you can do with Gosu in 60 lines of code. If the user presses the left mouse button, a new collection of points is captured that tracks the mouse movement. Once the button is released, that set is finished and a new set can be started. Each set has a specified color, and the current color can be selected using a few keys (R for Red, G for green, etc.).

This code uses the Gosu draw_line method, which I must show you the disclaimer the documentation provides. If a pixel or two will make the difference, this might not be your best bet.

Alt Text

Nonetheless, we’ll take our chances. The core of the drawing code is shown here which leverages the Ruby inject method on a collection, one of my personal favorites.

Alt Text

A nice extension idea here is to place a background image underneath the drawing, and then the user can touch up or add detail to an existing image. To do this, you can follow a similar pattern to that used in the reaction time code. You would also add a final z-index parameter to the draw_line invocation on line 23. This ensures your lines appear on top of the image.

Price of Bitcoin Game
I must admit, this is my favorite app of the group. The often highly volatile nature of cryptocurrency prices make this game somewhat interesting. This game required just over 200 lines of code, and primarily uses draw_line to render the graph representing the price over time.

The user is asked to click on the graph to make a prediction of the price at that time. A Bitcoin image is rendered at that spot and code checks for a win/loss condition once that time is reached. Below is a screenshot of one of the many times that I lost, except that is for when I made a prediction a minute after the current time. You might want to force the user to guess at least a few minutes out in your version.

Alt Text

There is a fair amount of math used for the scaling and conversions between prices, time, and pixels. I’ll let you read the code if you are interested, but try the game out and see how accurate your predictions are.

Have fun creating your games! Don’t forget to follow me on Twitter at @DarrenBroemmer so you don't miss any Ruby Unbundled!

Related topics:
Coding, Software Development, Developers


originally published on engineyard.com

Top comments (0)