Sessions is temporarily moving to YouTube, check out all our new videos here.

Let's Create a React Powered Game in 25 Minutes

Johannes Stein speaking at Reactivate London in August, 2017
2623Views
 
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

The talk will cover React patterns that can be used in every stage of game development, from user events to animations. We'll be implementing a new feature until we have a playable prototype to show by the end of the talk.


Transcript


My name is Johannes and was already mentioned, or Jo, feel free to call me Jo. I have other nicknames as well, but talk to me about them after. So what I'm going to be talking about today is creating a game in React. So people usually ask me, so why do you create a game in React? Don't you use like something else that is better suited for the job? And I'm mostly like, well, I know React, and so I'm just trying to either find some use case for React that it's usually not being used as, or it's also easier for me. It's kind of saying like use the tools that you're most familiar with. And so I am really into game development. I haven't done as much recently as I want to, but every now and again, I kind of participate in some game jams. And then I want to-- Or usually I use React because the thing I use everyday at work, and I just find it easy enough for me. So yeah. Long story short, let's just get started. So what I kind of prepared is I'm just gonna write some code and then at the end it's hopefully gonna be a game. Or not. Damn it. So yeah, we've got a background that's just like water, and then I'll make like a ship. And then let's create another ship. Obviously they're like the same position, so you need to update the first one. So let's put that 200 pixels in. Let's move those a bit around. Oh by the way there's actually not gonna be any treasure, unfortunately. It's just gonna be ships and stuff and no treasure. All right, so now we've got two ships on the screen, but kind of want one of them to be like the pirate ship. So for that we just put in another component, and now that kind of turns that one ship into a pirate ship. Well, that's pretty much done. So how this works under the hood is kind of when I say it's a game component, then the under the hood it has like a game loop, it has a stage, it has a world, and then it puts everything in. So it's just abstracts arrays, some of the game specific mechanics for us. And we'll go into what the loop does for us in just a moment. But first we kind of want to move the ship around instead. So obviously on a key press we want it to move a bit. So for that to happen, we just say-- I keep typing shop for some reason. We just put in a key event. All right. And then we have a prop called onKeyDown. So this one takes a function. So in this function it gives me keys and the previous state. So if I know say I want keys, inside of keys I'm checking for, let's do the ask key. And then, hold on. My keyboard layout is a bit weird right now, sorry about that. There we go, found it. And then we just define a new state that we want to be returned. So we know already that the ship has like an X and a Y position. So what we want to do is just update that depending on the previous state. So state.y equals prevState.y and then just minus four. There we go. And then it should potentially work. But it doesn't. Let's just-- I love debugging life. It's not even giving me an alert. What is going on? Oh, sorry. So it's actually-- There we go. I kind of had an issue with the prop. But now if I press the W key, it's actually going up. So let's just copy and paste this a couple of times. Right, so now it can go up and down, this is very nice. And then just do the same for left and right. Yay, it works! All right, so this is good, and it also moves diagonally if I press both keys at the same time. Yay. Okay. So I just kind of want to explain or take a moment to explain how this actually works. Because obviously KeyEvent is not an actual React component, it doesn't render anything. So how this works is that I just defined this as a component but it renders null, or something that gives like a false value. And then inside of the chip, I'm sorry inside of the ship, I check for the component, and if it can't find a component, I just do something once I see that the onDown prop has been defined. Like in this case if it's pressed, then it will actually move the ship. All right. So the next kind of thing that I want to talk about is the sprite sheets. So the official definition, and I got this one off of Wikipedia or somewhere else, is it's an image that contains several smaller graphics in a tiled grid arrangement. And this is kind of how it looks like. So you have like big image that uses smaller images. You've probably seen this before if you've done any kind of CSS for example, and you have like big icons and you just need to display like smaller icons off it. So obviously this can be used for animations. But I'm not going to use this for animations. So what I'm gonna do is depending on where I want to move my ship, I want a specific position of the ship being displayed. So obviously if I move down, I want the ship facing downwards. If I move up, I want the ship moving upwards. So starting with the code from previously, we just have to define a direction index that I made up. So this is the wrong one, and now this is going to be fun just figuring out which one is the correct one. There we go, one down four to go. I'm sorry, actually it's seven more to go. Right, so we got that. Is that the correct one, I don't think it is. There we go. And one more. Right, this is looking good. So now obviously for the diagonal ones, it doesn't display them. So we need to find a way to show them. So we are kind of checking for both keys at the same time. So let's say, in this case, if we want to show like the ship facing diagonally, we have to check if it's like the W key and the A key at the same time. Then pull in the correct image and then show it. I think there should be one here right? Yes, got it. Thank you. So yeah. Hold on, just toggling through the correct ones. There we go. Right, and so then I just need to copy and paste this over, and then we've got it. So we've got W and D. Perfect. And then we've got S and A. All right, this wasn't the correct one. There we go. And one more. All right, there we go. So now we've got the ship moving, and depending on where we're moving, it's displaying, the ship is facing in-- Aw thank you! All right, so now we've got the movement of our ship out of the way. What we kind of want to do is the black pirate ship that is just now standing there, we kind of want to move that around on it's own. So we're gonna start with the same code that I pretty much wrote previously, and then there is this thing called onUpdate. And this is where the game loop kicks in that I referenced earlier. But let's just show what it does. So it takes in the previous state as well. And then it returns in object with the new state. You can see the ship moving while I type, which is great. It's a bug that I haven't fixed. Right, so what that does, the onUpdate. It's a function that runs, sorry. It's a function that runs on every frame. And then it just takes in what's being there and then executes it every frame. That's why the game loop is in, the game loop enables us to have components do an action every frame. So what we want to do here is obviously we don't just want to move it away, instead we want to try to set like kind of like a patrol. Like if it hits a specific point on the left, then toggle to the right. Then if it hits a specific point on the right, toggle it back and forth. So let's see if we can do this. So we want to do like-- Sorry, if previous state X, something along the lines of 100 pixel. Then we want this thing to switch. So by default this component already has the state of moving to the right, so we just define that. So if right, which is defined on the state, or on the prevState to be exact. All right let's just hope this works. Oh actually we need to switch those around. I almost forgot that we need to toggle the other value. Right. Moment of truth in just a second. All right, boom. Boom. All right. So we got the ship moving around. Pretty much the next step that I'm going to do, and this is going to be actually the last step for this presentation. Is that I want to shoot cannonballs with my ship. So obviously the ship is still on patrol, and now we want to put in a cannonball, which is another component. And then it just hangs right there. And then, whoa, oh no. I almost went too far. Right, so cannonball, let's put back in the cannonball. So as you can see, the component, they are relatively positioned. So the position of the cannonball takes the position of the ship. So if I put in another X and a Y value, this will now be positioned inside of the ship. So what I want to do then is similar to how we had the key event for the ship, we can define a key event inside of the cannonball. And this time I'm gonna put in the correct prop so that it actually works, hopefully. And then put in the keys. And takes the previous state again, and needs to return a new state. Right. So we can also toggle the visibility. Obviously we don't want the cannonball to be displayed at the beginning, we only want it to be displayed once we actually shoot it. So we switch the visibility off. And now, we check for key, and because I'm lazy, I'm just binding this to the Q key. Also it might mess up my stuff if I put it in any of the other keys. Right, so now what we are doing with that, just to show you that it works, I'm just gonna toggle the visibility, but obviously it's not just shooting yet. So let's define the state that I want returned. State.visible and then just put true. Return the new state, and then once I press Q, we see the cannonball. Well obviously that's not the whole story, we kind of want it to actually move around. So the next thing, we just kind of combine it with what we had in the previous example when we moved around the ship. So we define the onUpdate here. Taking in the previous state, again. And so once we know it's-- So in prevState. So once we know it's visible actually, if we then kind of just want to shoot it up for a bit, we just want to move the cannonball just a couple of pixels up, just maybe 40 pixels, so that it's not in the ship anymore. All right, same procedure. Defining the state or ending the state. And then just say Y position should be, should be the prevState minus maybe like two pixels. So now if we press it, let's just put the ship up and down. Now if we press the Q key, it goes all way over the screen. This is not kind of what we want, but it's better. So we just need to define like a condition where it says, if it moves like a certain pixel, then just hide it. If prevState.y is, I don't know, let's say lower than zero, let's see if that works. And then just All right. All right this is almost good but I think we can do a bit better. Let's do minus 40 and just check this again. Right, this looks good. So obviously we don't want this to shoot like always to the top, but that's something we can then check. For example if we were to take this further, we can then have like a direction index check which direction it's currently at, and then decide in which direction we want to shoot the cannonball. But this might be a bit out of scope for this slide, and I think the code is getting messy already. So yeah this is just an example again, just in case I wouldn't have been able to actually reproduce this. It's just the same thing. And this kind of leads me to my last few slides. Obviously this is what's just kind of an idea if you want to do game development with React, this is like the kind of like first stepping point that you would need to do. You could do like a keyboard input really easily and obviously because of React's component structures, it kind of lends itself to being quite easy to drop in specific things like specific things that actually don't render, but modify a compound in a way so that makes it very easy to read and to maintain. And if you would want to take this specific example, like for the next step would be to have like some physics in there to actually have like some collision, and then maybe like some hit points so that if the cannonball hit, it wouldn't destroy the ship quite at first, but just like remove a few hit points and it needs like a few shots to actually be destroyed. So what I used to do this is actually React Game Kit. It has physics in there by default, it has like a lot of things that help people with that. But what I think actually, this is an implementation detail. If you have like a structure, a self-defense structure, how you develop your game, then it doesn't matter if you use React Game Kit or like React Primitives or like anything else. If you have your components defined in a way, I think it's kind really visible very quickly. Right, and that's it.