In this lecture, we'll look at how the basic gameplay is implemented in our game. We'll also see how we can build a nicer HUD using slate widgets. We'll start with a reminder of how the basic gameplay works and then we'll go look at the code that implements it. I have turned off the sound effects, so that I can talk about stuff without talking over the sounds of the game. Remember we pick a game difficulty then we go to the game. As you can see on the top, I've implemented a HUD and I've implemented that HUD using slate widgets, instead of just using the Canvas draw text that we used way back. When we have a countdown timer on the upper left, I have a health bar for my burger in the middle and I have my score in the upper right. Let me see if I can score a little bit here. There we go. I've got some score as well. As you can see, the game ended when the timer ran out. The game is over. I scored 20. The high score is 40. That's what my saved game, high score is. Then I can quit from here back to the main menu. The other way the game can end is if I run out of health. There's two ways the game ends. Either the timer runs out or I run out of health. We'll look at the Burger Pawn first because that's the player's avatar. Begin play, we do the usual stuff including adding ourselves to the event manager as a game over event invoker, as we saw when we talked about the event manager. I'm also using configuration data. We'll talk about that in a lecture later in the module. On tick, I move using the pending movement input, just like we've seen ever since we started using player controllers and ponds when the burger overlaps with something. If the burger overlaps with a teddy bear we're going to lose health, so I use whatever damage the bear inflicts from configuration data and reduce health by that amount. We'll see why I use health percent in a moment. I destroyed the teddy bear I just ran into and I check to see if the game is over. Because if I just run out of health, the game is over. If I run it into a teddy bear projectile, I lose health. I calculate the health percent. I destroy the teddy bear projectile and I check to see if the game is over. We'll see why I'm using that health percent when we actually look at the implementation of the HUD. Finally, checking if the game is over. If health is less than or equal to zero, I broadcast that game over event. My game mode is listening for that event, so it will know to end the game if this event is broadcast. The burger can of course, shoot french fries. Here's the fries actor. Again, it does the usual stuff, adding itself to the event manager as appoints, added event invoker and using configuration data and getting itself moving it using the static mesh component. We make sure we destroyed the fries if they go past the top of the screen, french fries are always shot up when the french fries overlap with something. If we shoot a teddy bear, that's how we actually score points in the game. We broadcast the points out of the event. We destroy the teddy bear and we destroy the french fries. If the french fries run into other french fries or teddy bear projectile, we just destroy the other actor and this actor, both of them are destroyed on that particular collision. If the french fries are being removed from the level, remember we want to remove ourselves as an invoker and this happens all the time. French fries are leaving the screen all the time. We want to make sure we remove ourselves from the event manager as an invoker of the points added event. That's it for the french fries. Our teddy bear actor uses configuration data, gets itself moving with a random force on begin play. Checks to see if it's off screen. If it's off screen, we're going to wrap the teddy bear. If it goes out on the right-hand side, it comes back in from the left-hand side. This is straightforward code that wraps horizontally and vertically. Notice I don't use an Else-If here because if I hit a corner, I need to wrap both horizontally and vertically on the same frame. This isn't an Else-If here for the wrapping. I check for wrapping horizontally and I check for wrapping vertically. I might end up doing both on a particular frame. Wrapping itself is a really easy thing to do. If I'm outside on the left, that means that all I have to do is negate my Y. If I'm outside on the right, all I have to do is negate my Y and I do similar stuff with Z for top and bottom. If a teddy bear overlaps with a teddy bear projectile, we destroy the teddy bear projectile. We don't kill the teddy bear but we kill the teddy bear projectile we just ran into. This is a private utility function that just tells whether or not I'm off-screen. Shooting a projectile is standard stuff. I spawn the projectile and then I start to shoot timer again. A shoot timer makes the teddy bear shoot at random intervals. I get this random range between the min shot delay and the max shot delay, again using configuration data, and then I set my timer and when my timer finishes, it calls the shoot projectile function. The last class we'll look at before we go look at the implementation of the HUD is my game mode. So in the constructor I set the pond and player controller like we've been doing many times. I add myself to the event manager as a listener for the two events that can be invoked or broadcast in the game. I add a HUD. So I have a property called HUD widget class that I populate in the blueprints editor and as long as I've remembered to that, I create the HUD widget and as long as that worked fine, I add the HUD to the viewport. I also start a one second timer. So this is my countdown timer. The configuration data tells me how long each game should last and so I extract that from the configuration data and set that to my seconds left here as we start playing. So this is currently set to 30. So I set seconds left to 30 when the game starts, and I start a one second timer. This is just adding points to the score. This is the delegate that I need when I add myself as a listener. When the game ends, we've already looked at this end game function in game mode when we talked about how we display the game over widget and this is more stuff for dealing with the event handler. When we're removed from the level, I remove myself as a listener for both those event, and here's starting that one second timer. This is really straightforward. We've used timers before. This time, this is not some random amount, this is one second exactly and when the timer finishes, we'll call change seconds left which reduces seconds left by one and then checks to see if time is up, and if time is up, we end the game, but if time isn't up, we start that one second timer again. So that's all the C++ code implementing the gameplay. Let's go look at the implementation of the HUD. So here's my HUD widget. As you can see, I have some text labels that don't do anything dynamic, but they do have some elements in the HUD that should change as the game changes. So we have the seconds that are left, we have the health bar that I should change, and we have the score. Seconds left, and score are textboxes, but the health bar is actually a progress bar. So I used this progress bar for my health bar. If we go to our event graph, you can see when I construct this widget, I do a number of different things. First I get the player pawn and I cast to my burger pawn and I set a burger pawn variable that I've declared over here on the left to be that burger pawn. Then I get my game mode and cast to my feed the teddies Game Mode base, and I set this variable over here. The feed the teddies Game Mode base variable that I've declared to that object. So I have a couple of variables that I'm storing when I construct this widget: a variable that holds a reference to the burger pawn and a variable that holds a reference to the Game Mode base. If I look at how I bind time left, you can see that I've bound that text block to the seconds left property in the Game Mode base. We just looked at the code that changes seconds left as the timer counts down and this will display how many seconds are left. For score, I've done it slightly differently. So the way I actually built this is I'm not binding it to a specific variable. I created a binding and so if we look at that binding, I take my game mode base, I access its score property, and then I set that score text block to be that value. Now I will say I could have bound this to the Game Mode base score property as well. That would also have worked fine. I just wanted to show you two different ways that we can actually set something. We can bind to a specific property or we can write a custom function that actually binds a value to a particular text block. I wanted to show you both ways to do that. Finally my health bar. I've bound to my burger pawn variables health percent property and this is why I needed a health percent property in addition to my health property that I have in my burger pawn, because progress bars want us to have our bound value to have a range from 0-1. So I just convert my health that will be from 0-100 to be a percentage which is from 0-1 and then I can just directly bind it to this progress bar. So in addition to looking at our basic gameplay, you got to see how we can implement a more robust HUD using Slate widgets instead of just drawing text to a canvas. To recap, in this lecture, we saw how we used a number of different gameplay classes to implement our basic gameplay and we also learned how we can implement a HUD using Slate widget.