Placeholder Image

Subtitles section Play video

  • Hello.

  • This video is a direct continuation from the previous video, which was worms part one.

  • So if you've no wash that video, go and watch it Now we can click the little link above.

  • At the end of the last video, we had a game where we could generate a random terrain on.

  • We could deploy units on it by clicking the middle mouse button.

  • We could cause arbitrary explosions anywhere on the screen, and we could drop bombs on the scene on the unit's interacted with the explosions.

  • And admittedly, that was quite a long video because we had all the physics stuff to get through.

  • I'll try and keep this one a bit short.

  • In this video.

  • We're going to look at adding some user input so we can control the units and make them walk around the map.

  • We're also going to add a smart camera, which will follow the action so the player can see what's going on and finally will introduce a state machine, which is used to coordinate and sequence all of the events that go on.

  • I will turn this from being just a playable demo into an actual game.

  • Let's get started.

  • I'm starting off with the code that's available on the getup, and it is the code that we created in the first video, so I'm going to change that one to it, too.

  • At any given time, the player can control one of multiple units on the screen, so we're going to need to store a pointer for the object that's under control on this point will be used to direct all of the user input towards that particular object.

  • For now, I'm goingto hack in that That pointer points to the last worm or the last unit that was added to the map.

  • So I'm going to borrow this code from here, create a new worm object and push that to the back of the list.

  • Then this means I've got access to the pointer for my object under control Variable.

  • We won't be leaving it this way, but this allows us to do tests quite quickly.

  • If the object under control pointer isn't a Noel pointer and it must be pointing to something and hopefully that's going to be a unit.

  • In fact, what we're going to ensure through the rest of the game code is that P object under control always points to a worm unit, so it won't point to a missile or some debris.

  • And then we should ensure that user input only applies when the object is stable.

  • For example, we don't want the objects built to jump whilst it's in mid air or it's falling.

  • I'm going to use the said an ex keys to make the worm jump in a particular direction that for left an X for right and to make the unit jump, we just need to set the velocity vector directly.

  • So here I'm setting it with a positive X component.

  • So it jumps towards the right and said, I'm going to set that to a negative X component because it's jumping.

  • We'll have to set the white component to be negative.

  • So it's working against gravity.

  • Let's take a look.

  • So I've created my pearly noise map, and I'm going to add a unit to it now.

  • The last unit added, is the object under control.

  • So right now all of my user input is going to refer to this one unit.

  • I press the X button, it jobs to the right.

  • I press that button, it jumps to the left and I can't jump in mid ER.

  • Clearly, this object is jumping around on the moon, but that's nothing.

  • A little fine tuning can't sort out later.

  • The unit is only going to movie jumping on.

  • The reason I've decided to do this is actually quite complicated to make it walk across the surface, using the physics engine that we've got.

  • But I'm going to disguise the inadequacy of the physics engine by making the player jump.

  • Because the player then has to take some risks.

  • They have to estimate where their unit will end up.

  • If I had another unit, this is now the unit under control now worms his game all about angles.

  • We used them to work out the trajectory to fire weapons on.

  • I'm also going to use the angle toe workout, a jumping trajectory so the user has some control over the jump because right now, just by jumping backwards and forwards, I don't get very many options of where the worm could be on the terrain.

  • The only variability comes from when the worm falls down hills.

  • So let's add a trajectory cursor.

  • This is where we're going to start having some properties to the worm class, and in this instance, I want to add a shooting angle, which is floating point.

  • I'm going to add some more clauses now to the user input.

  • So when the user presses the a key, I want the cursor to rotate counterclockwise.

  • Now again, assuming that the object under control is a worm, I'm going to cast the object control pointer to a type of seat worm is this, then allows me to access the shooting angle variable.

  • So whilst the a key is held down, I'm going to be subtracting from the shooting angle with reference to every lapse time just to make it smooth.

  • But I'm also going to add in some protection that if we go below minus pi, it wraps back around two plus pi.

  • This way, the cursor can be aimed at any angle around the unit.

  • I'm going to do exactly the same for the S Ky, except this time I'm going to be increasing the shooting angle.

  • Naturally, we're going to want to visualize the curse.

  • It's of the player else.

  • This game will be very tricky indeed, and currently we're drawing all of the units by automatically scrolling through the list of objects and getting it to call their own drawer routines.

  • But we want to add extra information, so we'll have to expand this loop a little bit.

  • We still want the object to draw itself, but I'm also going to again cast the object under control Pointer to a type of worm.

  • And if the current object in the list that's being scroll through is equal to that worm, then we know we're drawing a cursor only around the worm that is the object under control.

  • Let's work out where the center point of our cross her is, create a variable C X, and we know it's going to be somewhere near the position of the object.

  • And I'm going to use our old friends Simon, Co sign to turn our shooting angle into a vector.

  • I'm setting the length of this rector to eight AII the radius of the circle that described by the cursor.

  • There's one more thing to do, of course.

  • We're working in world space at the moment.

  • We need to turn that into screen space, so I'm going to offset it by the camera position, going to exactly the same for why I just need to change my co sign into a sign.

  • They want to draw the black pixel of that location to represent the cursor.

  • But I'm also going to draw the pixels to the north, south, east and west of the center pixel to make it look like a plus symbol.

  • Let's take a look.

  • So if I add a unit, we can see that there's a cursor attached to it, and I can use the es and S keys to rotate the cursor around the unit.

  • If I had another units, which becomes the objects under control, the cursor has moved from the unit we're no longer in control of.

  • Let's use some similar code now to make it so that the worm jumps in the direction the cursor is pointing.

  • So now I no longer want to hard coat these values in.

  • Instead, what I want to do is get the shooting angle for the objects under control, which for will be for that worm that we're now controlling and use this angle to create a vector in much the same way.

  • We just created the cursor.

  • However, now I no longer need a jump in the other direction.

  • Everything is governed by the cursor.

  • So when the user presses the Zed key, hopefully the unit will move in that direction to take a look.

  • But the units on on if I jump, it's sort of nudging sideways.

  • So let's move the cursor vertically and jump.

  • Yeah, we can see the worm jumps vertically, and now the user has a lot more control over the jumps.

  • And when we put a time limit later on how much time the user has to play, it becomes a little bit more pressure because it takes time to move this cursor.

  • Currently, the camera is completely controlled by the player on where they've got the mouse on the screen.

  • I think it's more natural to have the camera follow the object that's under control, or indeed, any other object that we wanted to follow, for example, a missile later on.

  • So I'm going to cause another pointer, which points to the object that we want the camera to center on this piece of code from the first video, make sure the camera is always within a sensible space within the world map, so we don't go out of bounds, so it's important we do all camera manipulation before we clamp it on.

  • We only want to move the camera automatically.

  • If the tracking object is not, no point it.

  • And in this situation I want to set the cameras X coordinate to be equal to the objects.

  • Were tracking is X coordinate, offset by half of the screen, so the object is always in the middle of the screen.

  • I don't want to do exactly the same for why, in much the same way we hacked the object under control variable, I'm goingto hack the camera variable, too, just for now, let's take a look.

  • So I put my unit's on the screen and we could see the camera has already started to follow it.

  • Let me move the cursor up a little bit, causing to jump, and we could see the camera now follows.

  • The unit keeps the unit in the center of the screen.

  • In fact, we blow the in itself.

  • It always stays in the center but are clamping.

  • Code should ensure that when we get towards the map boundaries, the unit moves from the center and we don't have a horrible crash Now let's make it to the user Can fire a missile in the original Worms game.

  • The user would hold down the button to build up an energy bar to indicate how much force they want to put into the projectile.

  • So we'll do the same.

  • I'm going to create a flag, which is be energizing to indicate that the user is indeed charging something up on.

  • I'm going to create a floating point, which stores the amount that has been charged so far will initialize that to zero.

  • I'm back in the section where we're handling user input.

  • I'm going to make it so that the space bar starts charging up the weapon.

  • So as soon as the space bar is pressed, we're going to set the energizing flag to True on will reset the energy level.

  • One of the nice things about the council game engine is we can distinguish between the button being pressed on the button being held down.

  • So whilst the space bar is continuing to be held down, I want to increase the energy level.

  • And of course, I'm using every elapsed time to make sure that all smooths out.

  • And if the energy level goes to larger than one.

  • I'm going to clamp it and then I'm going to do something else because it is at this point the weapon needs to fire.

  • And it's important that we do fire here because it's this little pressure which punishes the player for hesitating about the shot.

  • I were trying to introduce some skill that the player has to acquire in order to be good at the game.

  • So I'm going to add an additional Boolean, which acts as a trigger toe handle.

  • The firing of the weapon will default.

  • It's false.

  • We'll make sure that we set it to false when the user's starts pressing so we don't know weapon to fire straight away.

  • We're going to set it too true when the energy level is at its maximum, so it fires the weapons straight away.

  • But we also need to consider the case where the players playing accurately doesn't want to put the full force behind the projectile, and this will happen when they release the space bar earlier.

  • So we also want to look for this event and in this case, as long as the weapon is being energized, assumes the space buyers released.

  • The fire weapon flag is set to truth, so we'll do that later will handle the firing of the weapon code.

  • But it does mean that the energy level might not be at its maximum value.

  • So let's do something when the fire weapon flag is set to true.

  • Well, we know that ultimately we want to reset all of those states before we exit this routine.

  • Let's grab the current worm that's being controlled, and we're going to get some vectors from this worm that indicate the origin of where the missile is going to be fired from on the direction.

  • Which, of course, is the sign and co sign of the shooting angle on because we have a nice, robust framework or we need to do is add the missile to the object list.

  • But I'm adding it at the location of the worm, and I'm giving it a velocity vector, which is the energy level between zero and one times 40 times the direction.

  • These values may need to be changed depending on the nature of the weapon being deployed.

  • We'll just have the object to the list we will need to indicate to the player how much energy they're putting into the weapon.

  • So in the same Murray of the code, where we're drawing the cursor to indicate the direction, I'm also going to draw a progress bar, which will be 11 pixels modulated by F energy level.

  • So it'll be all 11 when it's one on no pictures at all when it zero.

  • And I'm just choosing the appropriate X and Y offsets to make it look pretty surrounding the word.

  • Let's take a look, someone to deploy units, and clearly there's no energy bar.

  • Let's move the cursor.

  • I'm going to hold down the space bar when you see the bar filling up and it filled up in a missile shot out in that direction.

  • Let go a little bit earlier.

  • We can see the missile is given less and less energy.

  • Let's see if we get him to blow himself up.

  • What goes up must come down.

  • We saw then that when the missile flew off the screen, we lost track of it, and that's not gonna be very exciting for the player.

  • They're not going to see the consequences off the devastation, so I'm going to tell the camera to track the missile object.

  • The downside, of course, to this is that the missile will eventually die and be removed from the list.

  • And we don't want the camera tracking object to be pointing to an object which no longer exists.

  • Fortunately, we capture the event when an object dies, and in this case, we know that missiles explode and call the boom function.

  • And so, in this event, I'm going to say the camera two point back to the object under control.

  • Let's take a look deploy unit angle refuting angle, charge of the weapon and release.

  • And we can see now the missile is the focus of the cameras.

  • Attention.

  • What we see is it immediately snaps back.

  • We don't see any of the devastation, and this could be quite off putting for the player one way around.

  • This is too low.

  • Pass filter the camera's position coordinates, which we've seen in many other videos, including the retro racing arcade game on the augmented reality in the console.

  • The idea is that we specify a target coordinate, which acts as a guide for where the actual coordinates should be, but we make it so the actual coordinates lag behind the target coordinates.

  • This means we no longer set the camera coordinates directly.

  • Instead, we want to set the camera target coordinates and that the camera's current position is always slowly inter plating between the current position on the target position.

  • I've used a factor of five as the interpolation coefficient.

  • Let's take a look at our unit, and if we make the unit jump around, we can see the camera has a slight lack to it.

  • Let's far Ms El we see.

  • Even though we still didn't get to see the devastation, the camera panned back to the unit rather than being set to it directly.

  • One nice side effect of controlling the camera in this way is that if the user moves the cursor towards the edges of the screen, like we've always been able to do in this settle, it can only pan a certain amount before the equations balance out.

  • This is nice, so it gives the player the ability to have local field of view.

  • However, the camera not hanging around to see the results of the explosion is still a little disappointing.

  • We're going to need a higher level of control to decide what the game is doing.

  • At any given point, I went to allow the player to actually have input.

  • What sequence and ordering of the units are under control, where the camera is looking at at any given time, updating scores and health and checking for game wind conditions?

  • What we need is a state machine state machine is a set off states connected by events and for the state machine aficionados out there, I'm going to be using a more machine.

  • But the principle is in our game engine that we will quite happily sit in a single state until on event occurs.

  • And when that event occurs on, depending on the nature of the event, we move to the next state and then sit in that state until the next event occurs, etcetera, etcetera.

  • Some events can be global, and in this case I'm going to use a reset event, which means that at any point I can get to a known state, I'm going to be using Julian's to control state transitions.

  • And when I'm in a state, I may perform some one time actions or set some more billions as outputs, which can be used to control multiple other actions.

  • Let's have a think about our game state machine.

  • I know I'm going to want to start with a reset state, and this is where I'm going to initialize all of the game variables and then want to go to a second state to generate the terrain.

  • I don't want to go to 1/3 state to deploy the units.

  • I'II place them on the map.

  • Most the units are deployed.

  • The player can start playing the game so the full state will be played control.

  • Once the players performed in action, such as firing a weapon.

  • I'm going to go into a camera control state.

  • The player no longer has control and the camera is going to follow the action.

  • And for the scope of this video, whilst the action has completed, we go back to the player control state.

  • However, we've already broken our own rules of state machines.

  • We've got to remember state can only do one thing, and so we need a few more.

  • For example, the generate terrain state will allocate the memory for the terrain and call the pearly noise function.

  • That's really one thing, and it can happen instantly.

  • for that one frame, however, the deploy units state is a little more complicated because my intention is to have the units parachute in from the top of the screen.

  • So when we enter the Deploy units state, we're going to place the units at the top of the screen.

  • But then we need a second state, which represents the units in the process of being deployed.

  • So let's get rid of that.

  • And I did units deploying.

  • And so we sit in this state waiting for the condition to be true that the units have in fact finished deploying, and at that point we move on to play control in the player control state.

  • We're waiting for the player to perform a final action, for example, firing the bazooka, at which point we go into the camera control state.

  • And as we saw earlier, once the missile has hit the ground, it immediately pans back to the player that's under control.

  • What would be better off doing is waiting for the consequences off the missiles actions to have finished before we resume play control.

  • So we're going to add another state here, too, to represent the state machine.

  • I'm going to create an enumeration called Game State and have two variables.

  • One which is Game State, which reflects the current state that's active and one which is next state on this is quite important because per frame update, we only ever want to execute one state.

  • And I think the best place to put our state machine is before we handle the user input.

  • Because some of the states may disable user input, I'm going to use a switch block toe handle the state machine I've added in empty case blocks to represent the different states.

  • For now, the reset state doesn't do anything.