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!