 So, hey everybody, my name is Corey Chamblin, I am a programmer, I write back-end software at a company called PagerDuty, but today I'm not going to talk about any of that stuff, I'm going to talk about something way sweeter, I'm going to talk about how to build video games in Ruby. I don't do this for my job, but I like to write games and I think Ruby is a good language to do it in. So the github for the talk, github.com slash Chamblin, you can go there, download the slides, download all the code for the talk. So first we're going to talk about kind of the reasons why you might want to make games or why you might try to get into this as like a hobby, just something to do on the weekends. We're going to talk about why Ruby is a pretty good choice for getting started making games. The second bit there, the main chunk of the talk, we're going to talk about how games are structured and pretty much every game framework out there. We're going to talk about Gosu, which is an amazing little library in Ruby for building your own games, and we're going to talk about how to write pieces of games that you might want to build by building a couple toy games using Gosu. And if we have a little bit of time at the end, we're going to talk about a few resources for aspiring independent game developers, so if you're not an artist, you can go get some open source artwork or some open source music, sound effects, and maybe some tools that you might use in building your own games. So first of all, why do I make games and why should you make games? So I like to make games because it reminds me of when I very first started programming. Back in the day, we would get these giant books of basic programs, and they were games and you would spend your whole afternoon typing this stupid program to your computer and you would get to the end and you would type run, and if you were very lucky and you didn't make any mistakes, you would blow yourself away with a really bad game. No, but it was exciting in the sense that I typed this thing in and something happened on my computer. And that is a real visceral kind of creative feeling that I think all professional programmers need to find some way to get that. The first time I hooked up an Arduino to my computer and I made the little light blink on it, I wrote some code and do a thing and I pressed play and a thing that was not my computer did something else. That was a similar feeling for me. So I think you should try to write games if you don't already have an outlet like this. See if games are that for you and if not, I highly encourage you to go find some way to creatively express yourself with your craft because it's very important to grow as an engineer, as a programmer that you can express yourself creatively. So what about Ruby? Nobody considers Ruby a high performance programming language. So is Ruby the right tool for the job? Is it the right tool to build games in? So when I first became a professional programmer, I first had some interest in writing games because a lot of people get into programming because of writing games and I think games are sweet. So I was like, okay, well, I can write stuff, I have a computer science degree. So what do I need to know to write games? And I thought, man, okay, well, I need to go learn C++, I need to go learn half a dozen graphics libraries. I need to know what SDL stands for. Like I felt like there was so much I had to learn to get out there to write games. But none of that is actually true. So almost every language out there, every language out there has some library where you can write really nice 2D independent style games, very commercially popular. These are the games I love to write. I love to play. And that's a ton of the kind of games. Ruby is no exception. We have Gosu and Ruby and there's plenty of power in Ruby to write these simple games that are very full and very satisfying to write. Photographers often say that the best camera that you can have is the one you have with you. So if you want to make games, don't feel like, okay, well, there's just so much I need to know to do that. You can make games today. If you know how to write Ruby programs, you can write games. So go make your games with Ruby. If you feel like later on, okay, well, I'm feeling kind of hamstrung. I need a little more performance. The lessons you learn writing games in Ruby, the lessons you learn writing games in Gosu, ports very well to the more commercial tools. I poked around in Unity. I wrote a couple of games using Unity, just having background writing games in Gosu. And the vocabulary, the semantics of writing games, the structure of games is very similar across the board. So you can kind of get your sea legs writing games in Ruby. And if you want to go do this professionally, totally room to grow into those higher end tools. But for me, I found out, hey, I love Ruby. Ruby is a great language and I'm not making a ton of money writing games. So I'm going to have fun doing it. I'm going to write my games in Ruby. So let's get into the kind of meat of the talk here. Gosu games can just be one class. So we inherit from a window class in Gosu. And you only have to implement three methods, generally. And these three methods, you're going to see them all over in game development. So like every game framework literally I've ever used has had these three methods be the primitives for building games. The first thing is the constructor of your game. So this is responsible for doing things like setting up the window details. Like what's the size of the window? What's the title on top of it? Is the game full screen? What's the resolution? If so, kind of the graphics setup of your game. It's responsible for loading assets from disks. So things like your image files, your sounds, and your music files. For reasons we'll talk about in a second. You don't want to be reading those things off disk in the middle of the game. You want quick access to them. So the constructor is responsible for loading all those things into memory. Finally it's responsible for setting up the initial game state. So things like, well I have three lives. So initialize says lives equals three. It's not very complicated. Level is one. Very simple stuff. The state of the game as the game begins, it's responsible for that. So this is called when your game first runs. This is called the setup method in most game frameworks. So after this gets done running, the game enters into an infinite loop. And that infinite loop is called the game loop. And then we call the other two methods in sequence in that game loop over and over again. The first of those methods is the update method. And it's responsible for detecting and responding to user input. So did the user press the B button? Okay what do I do? Did the user press the right arrow? What do I do? It's also responsible for updating all of the state of the game. So if the user pressed the B button, I'm shooting a fireball. If the user pressed the right arrow, I'm adjusting the player's position five pixels to the right. That kind of stuff. Finally, the draw method. It's responsible for drawing the current state of the game to the screen. So it doesn't change anything about the game. It just goes through say all of our image assets and says, okay, well based on the state of the game right now, I'm going to draw the hero right here. I'm going to put three hearts in the top right corner, all this kind of stuff. And so these are called in a loop, the game loop. And each time we go through that loop, that's called a frame. And however fast we're going through that loop, that's called the frame rate. And Gosu tries to run games at 60 frames a second. But obviously if you have a bunch of stuff in these two methods, that can slow it down. This is why we load images into memory. Because if you had to load all of your image files into memory on each frame, if you try to do that 60 times a second, your game is going to run really, really slowly. And you're going to turn your hard disk into a pile of slag. So that helps us keep up a frame rate. And that's basically at a very high level how games work. So to demonstrate these concepts, I wrote a really amazing game called Winner Winner Chicken Spinner. And how this game works is the chicken there, he spins until you press the space bar. And then when you press the space bar, the game ends, it's over. And if he stops in the highlighted area, you win. If he stops outside the highlighted area, you lose. The game is over. So the implementation of that game, it goes like this. So first, we're inheriting from Gosu window. At the bottom there, we're instantiating our game and we're calling the show method on it. I don't know why I named this game window. That's a terrible name. It should have been Winner Winner Chicken Spinner window. So anyway, here's the implementation of Initialize. We have the three responsibilities of Initialize and I kind of made different code paragraphs for the responsibilities. First, it's responsible for setting up the window. It's saying, okay, super class, make the window 480 by 480. It's setting the title of the window to Winner Winner Chicken Spinner. If the game were full screen, we would set that up. Second, it's loading all of our assets into memory. So the way we do that is we just instantiate the image class. We give it a path. These are just PNG files. There's no fancy games-only image format here, just PNG files. We have the chicken plate disk thing. We have the arrow and then we have two different images at the end of the game. If the player wins, we're going to draw that fantastic win logo and if they lose, the sad lose logo on top of everything. The last bit there is setting up the initial state of the game. So Winner Winner Chicken Spinner has really three pieces of state. It has the current rotation of the chicken because each frame we're going to rotate that chicken a little bit so he starts spinning. It has a game over flag so we know to stop spinning the chicken when the user presses the space bar. And it has a one flag so we can tell are we showing the win image or the lose image on the game over screen. The update function, remember, is responsible for checking for user input and it's responsible for updating the state of the game. So if the game is over, like the user's pressed space bar, this function does nothing because the user can't press space bar again and they can't cheat. However, if the game is not over, we want to check to see if the user has pressed the space bar in this frame. So if they did, we can use the button down method and it has a little constant called kb space. All the keys on the keyboard have these constants, they're all in the Gosu docs. But if they press the space bar, we're going to set that game over flag. We're going to set the one flag to whether or not we won and that just looks at the current angle of the chicken to figure that out and it was a lot of trial and error to come up with those numbers. There was no trick there. And if neither of those things are true, we're just going to rotate the chicken by 10 degrees by adding 10 to the chicken angle. And that is all update does. The draw method, remember, all it's doing is it's saying I'm going to render the state of the game to the screen. Whatever the game looks like right now, I'm just going to draw that. So the arrow, the little blue arrow that you saw, we're always going to draw that to the screen. That's at x equals 320, y equals 200. It's important to note in Gosu that the origin of 00 is on the top left-hand corner of the game window, not the bottom left-hand corner. So as you go down, your y coordinate goes up. Some game frameworks like to do bottom left, some like to do top left. I don't really know why, but Gosu is a top left kind of framework. The last number there is the z index. And if you do any web development, you're probably familiar with that. It's just the draw order of the images. The arrow will be on top of anything with a z index less than one and under anything with a z index greater than one. The next bit is drawing the chicken plate. So we're going to use the drawROT method because we want to rotate it. It's the same x, y, z stuff there, but we have the angle and degrees that we want to rotate the chicken. You'll note we're not setting it or changing the angle. We're simply drawing the angle that the update method has set. Finally, the game over state. So if the game is over, we want to draw the game over screen. And the game over screen depends on whether or not we won the game. And if we won the game, we want to draw the win image. Otherwise, we're going to draw the lose image. And we're going to draw it at z index of two, so it's on top of all the other stuff on the screen. And that's actually all the code there is in Winner, Winner, Chicken Spinner. But Winner, Winner, Chicken Spinner is a very, very simple game. And if you came to a talk about making games, you probably have ideas in your brain about games you want to build and they don't look anything like that. So we're going to make another very simple game, a toy game. But it will have, it's a little platform game. And that has a lot of important kind of mechanics, pieces of games that you'll map to pretty much any kind of game you want to build. So you don't have to make that huge mental leap from Winner, Winner, Chicken Spinner to what I actually want to do. So let's jump right into the code on this guy. So first the idea is we have a little guy and we want to be able to move him around on the ground just like a real platform game and we want him to be able to jump. So we're going to make a new game. This one's called Running Hero. And we have two images right now, the hero image and the background image. We're going to load those into memory and then we're just going to draw them statically on the screen. You know how to do this from Winner, Winner, Chicken Spinner. The next bit is we're going to make our guy be able to walk or at least be able to slide along the ground in an orderly fashion. So in a platform game the rules of movement are that the player can move to the left or the right but he can't move up and down. And if you want to build like your top down like Zelda kind of game you just change the perspective and then the player can walk up and down too. The same principles apply though. So all we got to do to walk we're going to store the current position of the hero in an array with the X and the Y coordinate. And in the update function remember update is going to check for that user input. It's also going to change the state of the game. So when they press the right arrow we're going to want to update that position by changing the X coordinate. And when they press the left arrow we're going to want to subtract from that X coordinate. So we wrote this little move function that does that. It just adds or subtracts five to the X coordinate based on the speed thing which you can set and change to make your hero a little faster. The only change I had to make to the draw function was just quit using hard coded numbers and start using our position when we're rendering our hero. And that's all there is to drawing the hero and making him be able to slide across the screen. Jumping is a little trickier. And you kind of have to think about how jumping works in real life and then you sort of have to like dumb that down for games. And I kind of just made this up for this talk so there's probably some way better way to do this but this is a simple way and it made sense to me. So how jumping works in running hero is you can only jump if you're on the ground so there's no double jumping antics. But when you jump you get a certain amount of vertical velocity. And then each frame the game's going to look does the hero have vertical velocity? If so I'm going to move their Y coordinate up by that number and then I'm going to divide their vertical velocity by some amount of gravity. And then eventually they're going to run out of vertical velocity they're going to be at zero and then they're going to start falling so I'm going to give them negative one vertical velocity and then each frame will be multiplying that velocity times gravity. So they'll go faster and faster and faster until they hit the ground and then they can jump again. So maybe some code is a better way to explain that. So the implementation of that just in the update function if the user presses the space bar we're going to call this jump function it just does nothing if the user's already in the air otherwise it'll give them a vertical velocity of 30 pixels per frame. The other change to the update function is we're going to call this handle jump function which is going to do all that math we just described and updating the hero's position and updating vertical velocity. The implementation of that we have this gravity constant of 1.75 just has to be greater than one I just fiddled around until I found a good feeling number you will see that a lot in my game it's just most of these numbers are just made up. The ground level I can talk about that in a second it's just the Y coordinate where the hero is standing on the ground because that is currently how we're going to find out that we've landed. The next bit just subtracting the vertical velocity from the hero's Y coordinate because remember the top of the screen is Y equals zero so as you go up your vertical velocity goes down and then when you have negative vertical velocity your Y coordinate will start going up again. The next paragraph thing there is just changing the vertical velocity so if the vertical velocity is zero that means the hero is at the top of the jump and we need to start falling so we'll give them a vertical velocity of negative one so on the next frame we'll start falling if the vertical velocity is negative that means they are falling so we're going to multiply the vertical velocity times the gravity constant so they're falling a little faster on the next frame and if they're going up then we want to divide the vertical velocity by the gravity constant to go up a little less on the next frame. The last bit there like I said so when we get back on the ground we need to know that we're back on the ground otherwise we're just going to fall forever so how we're doing that is our ground is a straight line so the hero is always at the same Y coordinate when he's standing on the ground so we could just look at the Y coordinate if it's at the ground level then we can stop jumping since this is a platform game eventually you're going to get to the point where you have platforms to jump on that kind of thing the logic will have to change you'll have to use something like collision detection to know if you're on the ground or not but that's actually all there is to jumping and to walking so now our guy he can walk and he can jump but he does look a little silly because he cannot look to the left which is sad and he also kind of just moves like a cut out paper doll and not like a real hero it doesn't feel like a game yet it feels like a toy so in this chunk we're going to animate the guy we're going to add a few poses to him and make him look like way better so to make the guy be able to look to the left we're going to need to know which way he's facing and that can change as the game changes to a new piece of state so we're going to store the direction he's facing we're going to update that direction in our move function because that's the only way currently that our player can be turned around to face the other way is that they start walking the other way and then we're going to do this little trick in the draw function so one way you could do this is that you have a left facing image for every image in the game but that tends to get a little unwieldy and is a little hacky so a better way to do it is that the draw function on the image class has a scale x and a scale y parameter and if you set those things to negative numbers it actually will mirror the image and make it face the other way on that axis so if you set scale x to negative 1 it's going to flip the hero over back the other way and he's going to be facing the other direction back to back with his original position to compensate for the fact that we just moved the hero to the left by his width we're going to add the width back to the x coordinate so now our hero can be standing in the same spot but he can turn around and can face the other way so a pretty neat little trick there so now our guy can look to the left he can look to the right but now we need to animate him so animation in Gosu is very simple and by simple I mean you're on your own so so what you do is you get an array of images and each frame you just decide this is the one I'm going to draw this frame so you load up all of your stuff into an array and then you pick based on the state of the game which of these am I going to draw fortunately we have a really easy way to get a bunch of images into an array and that's by using sprite sheets so sprite sheets are a very very common tool in games development you just basically take all of your images that you want you make them all the same size and then you put them all in a bigger image and then you load them into your game and you say all of my sub images are this size and you cut them out for me and it'll do that for you this is usually done for complicated graphics card reasons but in running hero it's done because it makes the code nicer that the thing there behind the blue wall is our sprite sheet so we have seven poses for our hero we have the standing still and doing nothing pose we have three frames of animation for walking so if you play these in a loop it looks like walking it's called a walk cycle the fifth the fifth image is the player kind of with his arms out going up I don't know why this is going up I have never jumped like that but that is what going up looks like for our hero for going down our hero is kind of looking down at the ground and then the last image there is like our hero has been hurt and he stunned or just very surprised so to build all this animation all these poses into our game in the initialize function remember we load assets there we're going to use the load tiles class function on the image class we're going to give it a sprite sheet we're going to say our sprites are 64 by 64 so load those all into memory and this will just return that array for us of regular images we also need to keep track of which image we're going to show on this frame so we have this piece of state called the current hero image which update is going to check or which update is going to set and then draw is going to draw so in update we're going to look at the state of the game to figure out which frame to draw so if the hero is jumping that means they have a vertical velocity and based on that vertical velocity we're going to decide to use the going up or coming down image if they have a positive vertical velocity we'll use the going up image if they have a negative vertical velocity we'll use the going down image otherwise if the hero is walking one of the weird things about this is that the hero can be jumping and walking at the same time so if the hero is walking then we will just use one of these three images in the walk cycle and you don't want to just loop through these like one per frame because your game runs at 60 frames a second and this animation looks ridiculous at 60 frames a second so you want to slow that way down without slowing down your whole game so how we do that is we can take the number of milliseconds since the game started divided by 100 and that gives us 10 frames a second so we just take that number modulo 3 and that gives us a loop 012 012 we add one to that and then we get the right offsets in the array for the hero images that we need to show this frame finally if the hero is neither jumping nor walking we're going to just set the current hero image to the resting hero image, the first hero image and the only change we had to make in the draw function was that we want to use the current hero image instead of that old static hero and shockingly that is all that it took to animate our guy and actually he looks a lot better right now and he's feeling great about life however our game is missing a plot it's missing drama and to have drama you need to have pain and you need to have suffering and in games to have pain and to have suffering you have to have collision detection and so we want our guy to be able to slam into things we want our guy to be able to get hurt and so we're going to add a bad guy who currently doesn't do anything so he's not really that bad he's more of a painful obstacle but it's going to let us start building collision detection to our game so how does collision detection work well in our game we are going to put rectangles imaginary rectangles around our hero and around all the stuff that our hero can run into and then we're going to look for intersections of those rectangles and if there's an intersection that means there's a collision there are other ways to do this there's so called pixel perfect collision detection which will tell you exactly which pixels overlapped between two things on the screen but every platformer I've ever played as a kid used rectangles and it feels great it feels good it's also very conceptually simple it is you can run these in constant time so it doesn't matter how big the things are that you want to detect collisions are the collision detection is always just very easy math and it's totally good enough for our game so this is what we're going to do so let's draw our enemy into place so we just have a static enemy image for now we are going to draw use this draw collision bodies method which I'm going to talk about in a second it just draws rectangles around the physics bodies in the game so you can see where do your rectangles need to be we have a couple changes in the update method so first of all our hero can feel pain now we have this hurt until timer thing so our hero can be hurt for a little bit but then we want him to recover so how this works is we're going to set if the hero gets hurt we're going to set hurt until to some time in the future and then if that is set we're going to say ok the hero is hurt once you get past that time you can un-set it the last bit there is we're just going to call this handle collisions function because we need something to detect and respond to collisions in our game and how is it going to respond so a couple different modes of collision detection that can happen in our game first of all the hero can run into the enemy from the side like from the left or the right and when that happens that means the hero made a mistake so he should be hurt and in order to hurt the hero we're going to knock him back 30 pixels and then we're going to you know stun him for a little bit however if we collide with the bottom of the hero that means the hero jumped on the enemy's head and as we all know if you jump on the enemy's head you did a good thing and the enemy should die so that so right now we don't know how to kill an enemy so we're not going to talk about that but we are going to give the hero a little bounce which is a very cheerful celebration of jumping on the enemy's head so handle collisions implemented like this the first third of the code there is just defining the rectangle around the player and around the enemy there are a billion ways to describe rectangles in code I chose the worst one which is to use a hash but it looks good on slides so that's why I went with that in real life I probably would have used a struct or even just an array with the two corners specified to specify your rectangle the next bit there is we're calling this check for collisions function which for now all you need to know is it takes two rectangles if there's a collision between those two rectangles it's going to return the direction of that collision relative to the hero so if the hero gets hit on the left side it's going to return the symbol left if the hero gets hit on the bottom side we're going to return bottom and then the logic for how to deal with those collisions if you get hit on the left or the right that means you want to get knocked back by 30 pixels and we're going to set the hurt until timer to the current time plus 200 milliseconds which again just a magic number I made up because it felt pretty good if you collide with the bottom of the hero however you want that little bounce so bounce all you need to do is set that jumping flag to true and give the hero a vertical velocity of 10 pixels per frame the check for collisions function I just described so first you need to get the intersection of the two rectangles you were given so this is very simple math if you had like three minutes and a piece of paper you could figure out how to get the intersection of two rectangles but I just got my answer off stack overflow and if there is an intersection we can use that intersection as a heuristic for figuring out the direction that the collision came from the reason we can do this is because okay so if the intersection is wider than it is tall so if it's like a landscape style intersection we can know with high probability that the intersection came from the top or the bottom of the hero rectangle the reason for that is because the rules of the game don't allow you to intersect very deeply with another rectangle like it'll stop you, it'll knock you back 30 pixels or you bounce off the enemy's head so if it's wider than it is tall that means these rectangles aren't very thin it's probably a top bottom collision and otherwise it's a left-right collision for the same reasons so knowing that we can look at the top of the intersection and the top of the hero rectangle and decide if it's a top collision by checking if they're the same because if they're the same that means the top of the hero's rectangle is pushing through the bottom of some other rectangle and if it's a wide intersection and it's not a top collision then it must be a bottom collision so the same kind of trick applies to the left-right thing if we know it's a left-right collision we can look at the left of the intersection and the left of the hero rectangle and if they're the same it's a left collision otherwise it must be a right collision that was a lot of words and not very many diagrams so this is that draw collision bodies function I talked about you should definitely do this if you're going to write a game with collision detection because it's very tricky to dial these numbers in without having some visual aid all it is is just drawing drawing four lines makes a rectangle goes through as built-in drawing functions draw line is a neat one so I set a debug flag whenever I want to draw the physics bodies in the game and that's all there is to collision detection so now our guy can get hurt he can bounce off the enemy and he can celebrate in triumph so the very last bit of the game so we want to make it flesh it out a little more we want to be able to kill the enemy we want the enemy to be a little bit smarter and we want to be able to keep score so the first thing I did was I separated the enemy class out as its own entity because eventually your game is just going to get unwieldy if you leave it in one class forever so this is one way you can start moving out various entities in your game to have their own logic also maybe we want to make a bunch of enemies so this is a neat way to do it so we implement an update, a draw, and a body method on the enemy class here the update and draw methods are just called on all enemies in the appropriate method in the game call is going to call update on all the enemies every draw call is going to call draw on all the enemies the enemies know how to draw themselves the enemies know how to update their state as the game progresses the body method just returns the rectangle for collision detection because the game itself is still going to be responsible for detecting those collisions so here's how we plug that in we have we're going to instantiate an enemy in our initialized function we're giving it a sprite sheet now instead of just a static image you could make many enemies we're just going to make one for the purposes of this talk in our update function we're going to call update on all of our enemies in our draw function we're going to call draw on all of our enemies and in our collision detection function we're going to loop through all of our enemies and we're going to check for collisions on all of them otherwise the logic remains the same and since we have that in place we can now implement the draw and update functions on the enemy to handle those bits so the draw function on the enemy the enemy only has two states he can either be alive which means he's walking around or dead which means he's squashed so in our sprite sheet for our enemy we have four frames of animation so we just do the same kind of thing with the 0 with the milliseconds trick to loop to slow down the animation and if the enemy is dead we have a little squashed enemy image there on the end the call to draw just uses some ternary stuff to figure out if the enemy is facing the other way and if he is flip him over so he's facing the right direction the update function is responsible for the brains of the enemy if he's dead the enemy's brain is no longer functioning so it doesn't do anything otherwise we want to move the enemy five pixels in the direction he's facing and if the enemy walks off the screen then we want to turn him around so he's facing the other way so he starts walking back so besides AI and besides drawing the enemy we want to be able to keep score so we're going to have this new piece of score state it starts at a zero as one might expect we're going to load a font into memory this is just a ttf file nothing too fancy you give it a size you say it's a 64 point font and load this file then in the draw function we're just going to say hey font draw the score in the top left corner of the screen and draw will happily oblige finally to get points we're just going to update our handle collisions function so when we have that bottom collision we're going to set the enemies a live flag to false and we're going to increment our score and that is the final product of running hero so you can see we can jump on the enemy's head we can get points, we have drama and you can imagine how like going from here you could make this a full game you could add an endless number of enemies coming at you that get smarter and better you could add interrupts and weapons and all kinds of stuff you could make platforms and levels and goals and hopefully you have a starting point where you could start to think okay well that's how I would do that in gosu a couple of resources for your game development career highly recommend open game art huge resource if you look at the game development community this is like the one everybody says use this the hero image and the enemy image both cc0 images I pulled off of open game art you can go there and build a collection of images for a game idea you've got you can just go there for inspiration they have sound effects, music tons of art, just a great resource for tools for image manipulation you can use whatever you want you don't need anything super fancy I use paint and paint like tools I think I use pinta on the mac but also occasionally pico pixel which is a dedicated pixel editor all that stuff is free I highly recommend the tiled map editor so when you're building a game you're going to start building up all these chunks of games like okay well I've built this kind of enemy thing I built this kind of block and you're going to want to lay out your levels, your maps you can load all of your stuff into tiled and then it'll export json or xml you can parse that in you can parse that in your game and it makes building levels so much nicer I highly recommend that tool of course you can get gosu all the docs for gosu a really great tutorial on gosu from libgosu.org I highly recommend it check it out I hope you all feel inspired to make your own games now I hope you feel at least a little more equipped to go make games now and thanks for coming to my talk I think we have about a couple minutes if anybody has any questions so for testing okay so testing in gosu you can write unit tests that do things like send keystrokes to the game testing in games is really fidgety because there's so much that can happen there's a lot of state that has to be set up and so tdd in game development doesn't seem like to be much of a thing but certainly like sanity checks and tests like that are a lot more appropriate in game development it's a lot more experimental and like okay I did a thing how does it look, how does it feel kind of iterative development the most fun game I made with gosu man all my games are terrible okay so okay so the most terrible game I made with gosu I made a game that was really just kind of this stupid art game but it has this little fly and he starts buzzing around on the screen and then you slap the fly and then more flies appear and then you kill more flies and then eventually it ends and you just try to get as high a score as possible like I don't have it with me sorry but I'll put it on my github so so everybody can see how bad I am at this my github it's on the first slide github.com slash chamberlain yeah there's the link to the github all these slides and all the code for this talk will be on that github do I think they're going to make a library to write VR games and ruby I think it would be tough just because 3D is more computationally intensive it might be possible but I think it would be very constrained by the performance of ruby is there a 3D library I don't know of one there probably is but I'm not aware of one yeah so the question is the question is like why do you draw the same images in every frame does that sum it up so my understanding of how it ends up working is that you sort of end up with a blank slate each frame and like for video memory reasons or whatever and so you're actually just going to redraw everything every frame anyway but if you think about games from the point of view of like regular application development it seems very weird that I have to keep drawing this thing all the time but under the covers your graphics card has to redraw things every frame so this is just getting very explicit about that no more questions alright thanks everybody