Game Development

Writing Games with Ruby

Writing Games with Ruby

by Mike Moore

The video titled 'Writing Games with Ruby' features Mike Moore presenting at LA RubyConf 2014, where he demonstrates how easy and fun game development can be with the Ruby programming language using the Gosu library. The session is aimed at beginners, requiring no previous game development experience, and participants leave with a working game.

Key points covered in the presentation include:

  • Introduction to Gosu: Moore introduces Gosu as a powerful game development library that provides Ruby bindings for a low-level C++ library. The audience learns how to install it via the 'gem install Gosu' command.
  • Basic Concepts of Game Development: He explains fundamental concepts, such as the game loop, which runs continuously to handle events like user input and game updates. This structure is crucial in game programming.
  • Creating a Simple Game: Moore illustrates how to create a basic game using Ruby. He demonstrates writing simple code to set up a window titled 'Hello World'. He introduces methods for handling inputs and drawing text on the screen.
  • Movement and Animation: The presentation includes sections on how to move game objects and create animations using sprites. He covers implementing movements based on keyboard events and how sprites can enhance visual presentations through animation techniques.
  • Sound Implementation: Moore also discusses adding audio to the game—how to use the Gosu library to play sound effects and background music, making the gaming experience immersive.
  • Game Features: Other gaming features like parallax scrolling and jumping mechanics are briefly introduced, showcasing how they can add depth and responsiveness to gameplay.

The session encourages attendees to experiment with Ruby for game development, emphasizing that the effort is rewarding and enjoyable. Moore concludes by inviting participants to collaborate on game development projects and explore his available resources on GitHub to further enhance their skills.

Overall, the takeaway from this session is that game development with Ruby and Gosu is accessible, engaging, and offers a great platform for creativity and learning.

00:00:25.410 Thank you, Koby. I did a workshop the last two days, and my voice is starting to go, so I apologize for that. Let's see, my presentation is 'Writing Games in Ruby'. If we have time, we can go a little bit slower.
00:00:32.190 If you want to follow along, you can gem install Gosu, which is the library that all these examples we'll go through are built upon. You can even visit my GitHub repository if you want to follow along with the examples.
00:00:49.989 So, I have a confession: writing games is fun—you may not have known that, right? It's awesome, but it's even more fun because Ruby is super fun! Writing games is fun; it's fun squared!
00:01:10.840 This is my little Ruby guy. This is one of my claims to fame, and I love this because it reflects how I feel about Ruby—adventurous, awesome, and ready to tackle challenges. I would like to see more fun, and games are a great way to do it.
00:01:48.729 So, let's talk about Gosu. Gosu is a fantastic game library. Show of hands—who is familiar with game programming? Oh cool, maybe about a fifth of the room. Who's familiar with Gosu or has heard of it before? Pretty much the same audience. This is great! It’s new stuff, and that's exciting.
00:02:05.799 So, if you've got internet, which you should because it's great up here (it’s horrible downstairs), gem install Gosu and it will try to compile. You can also go to libgosu.org and look at the documentation. We'll step through some of this documentation during this presentation.
00:02:32.450 Alright, so what can you do with Gosu? I guess we should talk about what Gosu is. Gosu is a low-level game library written in C++, but it has first-class Ruby bindings. This means that all the concepts you'd use with Gosu in C++ map directly to Ruby. In other words, it's a fantastic Ruby library in addition to being a C++ library.
00:03:04.610 Let's take a look at what we can do with Gosu. I'm going to check out my Gosu library—I'm just wondering what my resolution is here. If you check out the Gosu GitHub repo, you can change into the examples directory, which is just Gosu.
00:03:20.930 So if you go to libgosu here, what is my resolution? My resolution is crazy big. If you go here, you'll get to the GitHub repo for Gosu. If you check out the Gosu repo on GitHub, there will be an examples directory. I need to switch to my Gosu gem set. Once you have Gosu installed as a gem, you can go to the repo, and there's a file called Captain Ruby, which is a pretty fun example. I’m going to change my display size a little bit.
00:05:00.090 Alright, so this is a little game that comes with Gosu, showing you how to play it. It's just a little platformer game, and it's super hard. This one does not have sound; I’ll show you some other games that do. I can never get to that upper right-hand corner because you have to go all the way back down. That's a cane—good luck getting all the rubies!
00:05:31.400 The code to all of this is available in the Gosu library. It is 224 lines long for the entire game, which isn't too bad. That includes the other code to build the map and manage input to move around. In less than 250 lines of code, you've got that game. What about the graphics? Yep, all that logic for playing the game is written in Ruby.
00:06:08.330 Here's another example: I've got some little kids. They were younger a couple of years ago, and I had an old netbook, one of those really small nine-inch ones. They always wanted to sit in my lap and be like, 'Dad, I want to work on the computer!' I needed to move them off and focus them on something else, so I created this little app called 'Little Brat' because I would often get frustrated when they were in front of me.
00:07:47.819 So they would play that for hours, and it was awesome! Another game I wrote, 'Captain Ruby', was created back in 2010. I gave an earlier version of this talk in 2010, and I created another gem that uses Gosu called 'Skagen'. At that time, I was big into ninjas! The whole point of the game is to try and reach the exit while avoiding snakes.
00:08:07.030 There was a gaming contest called Ludum Dare, where you have 48 hours to build a game completely on your own. You need to create all the art assets and code within that time frame. This library is fantastic for competing in the Ludum Dare contest.
00:08:55.490 So, lots is possible with Ruby for gaming! Show of hands—who would like to write games in Ruby? Alright, good; almost half of everybody! Super easy to do, not complex, and it's actually really fun as well. Here’s the thing: there are only a handful of concepts we need to understand to write games. The first is the game loop.
00:09:35.620 If you've done any kind of Windows or UI programming, you’re familiar with the evented model. Your application raises events, and you respond to them. That’s the same concept in a game loop: your game will have a game loop that runs continuously, called by the Gosu window object.
00:10:07.680 The game loop runs about 60 times a second, calling the update method and then the draw method. Every time you press or release a button, it will call the button down and the button up methods. That’s basically it! You start by creating a new instance of the Gosu window and define what you want to do within those methods.
00:10:43.100 Let's start. I'm going to open my editor and create a directory called 'Hello World'. In this directory, I’m going to create a very simple Ruby file. I'll create a new class called 'HelloWorldGame' that will inherit from Gosu::Window. My initializer will take three parameters: width, height, and whether or not the game is running in fullscreen. I’ll call super so that Gosu’s initialize method is called.
00:12:02.080 However, if I didn’t want to pass that in, I could just put 1024 by 768 here, and then false or true for fullscreen, and the super call would suffice. But I like to keep those values defined in my initializer.
00:12:24.060 Simply put, we are going to print 'Hello World' as the window caption. I also have my methods defined for update and draw, where we can put stuff in there. So, to call it, we will CD to the 'Hello World' directory and execute Ruby 'hello_world.rb'. And there it is—'Hello World'! It’s an 800 by 600 window, and the caption at the top says 'Hello World'.
00:12:52.440 If I hit escape or space, it won’t do anything because we haven’t told it to. Let’s define that button-down method. When the escape key ID is received, I’ll call close. It’s something I do in every Gosu game—finding an easy way to exit without having to click the little red dot.
00:13:31.100 Now let’s run it again. When I hit escape, it closes. We see that it's working, and we got these callbacks happening! Now, I want to see a bigger 'Hello World', not just in the title bar of the window but actually displayed on the screen.
00:14:27.610 So, one option would be creating an image that says 'Hello World'. Instead, I’m going to rely on Gosu to do this for us. In my initializer, I’ll create a new image object by asking Gosu to create it from text. I will look at the documentation for the window.
00:15:03.520 When we create the image, it takes parameters for the window, the text to display, the font name, font height, and optional parameters for line spacing and alignment. I’ll specify the window, the text 'Hello LA RubyConf', then use Gosu’s default font with a height of 100 pixels.
00:16:17.480 In the draw method, I want to draw the image at coordinates 0, 0, 0. This indicates where on the screen I want it illustrated. Let’s see if we can get that to work—and there it is, 'Hello LA RubyConf'!
00:17:13.810 What’s great is that when I press escape, it goes away. I’ll change it to just 'LA' and try it again. Now I want to make this image centered. The draw method accepts three critical parameters: X, Y, and Z.
00:18:54.000 The upper left corner of the screen is (0,0), and the bottom right is (800, 600). The midpoint is going to be (400, 300). So let’s move to the center by adjusting the coordinates.
00:19:33.860 We want to calculate the center point of the screen, adjusting for the image width and height. This will involve some math! So using self.width and self.height, I will do this: (self.width - image.width) / 2 for the X coordinate and similarly for Y.
00:20:31.270 All these calculations can be placed in an instance variable for X and Y. I want to make time-dependent changes, using Math.sin and Math.cos with time updates to create a smooth animation.
00:21:27.000 Now when we run it, our image moves side to side based on sine and cosine functions. This adds more depth to how the image appears, constantly refreshing its position.
00:21:50.000 Don't forget that Gosu allows us to play sounds, too! We have classes for songs intended to play continuously, and samples for shorter sounds. I’ll need to reference the documentation for sound methods.
00:22:15.120 Back on my desktop, I've dropped a couple of sound files into this project. I’ll create a song object using 'Gosu::Song.new' and pass it the filename, and a sample object for shorter sound files.
00:23:11.640 Now let’s play the song in the background by calling 'song.play'. When I hit a specific key, I want to play a sample sound using the same manner our updating commands work in Gosu.
00:23:56.220 I’ve successfully played a sound! It’s straightforward—less than 25 lines of code—and that showcases our abilities with audio in our games.
00:25:09.400 When people talk about sprites in gaming, we're often referring to the 2D representations like images or animations on the screen. A sprite sheet is a special custom image comprised of various frames, usually for animation.
00:26:23.060 Let’s create a directory called 'Sprite'. I’ll make a new file named 'sprite.rb' and initialize it with Gosu requirements, just like before. We’ll have a class named 'SpriteGame' that also inherits from 'Gosu::Window'.
00:27:56.570 I’ll grab a player sprite image, using Gosu to create a new image when initialized. We'll be manipulating this sprite position and allowing for input from keyboard events to move it around the screen.
00:29:53.840 As we’re getting into movement, I’ll include logic to check if the left or right buttons are pressed to move our sprite in those directions. We will need to check left and right buttons to adapt the visual appearance of the sprite.
00:31:16.590 For direction, I’ll set parameters to determine which side is facing. If moving left, it needs to flip horizontally to convey the correct movement visually. We apply basic transformations via the draw method to enhance the gameplay.
00:32:35.160 Animations can add depth to our characters, so instead of a static image, we can switch to frames from a sprite sheet to show movement. We'll treat the frames as tiles divided from the original sprite sheet. This creates a fluid animation as the character moves.
00:34:07.430 We must track our current frame and increment it with each update. This allows calling the relevant animated movement frames from the sprite sheet. We can create compelling visuals by adjusting the rate of the frame changes.
00:35:53.670 I’ll demonstrate how to add movement mechanics by checking the button states. If pressed, it moves smoothly to create a dynamic interaction within the game world.
00:36:34.440 Games can introduce various mechanics like parallax scrolling, which simulates depth by moving backgrounds at different speeds. I will invoke 'translate' methods to enhance our visual experience in this aspect.
00:37:58.490 I also want to show a jumping mechanic by implementing velocity calculations and updating position dynamically, allowing a character to jump and land smoothly. This will engage the player further by making the actions feel responsive.
00:39:33.810 In conclusion, writing games in Ruby is accessible and enjoyable! If you ever have the opportunity, I encourage you to pair up and write games during conferences or hackfests. It’s great fun, and that sums up my presentation! Thank you very much. My name is Mike Moore.
00:41:24.570 If you're interested, check out my GitHub for all the commits. Let's create together!