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.
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.
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.
So we set the next state variable two GS generate terrain, which is the next state.
But that doesn't go there straight away because this is a switch block and that's the behavior we want.
We don't want it to execute two states during one frame update.
So at the end of our own user update function, I'm going to update the current state with the next state variable will initialize them to reset.
Whilst I'm in the unused create function, I'm going to get rid of our create map.
The state is now going to handle that will still allocate the memory for it.
But the actual generation of the pearly noise will now be handled during the generate terrain state.
So in the generate train states, I'm going to call create map.
That is one action that this state does and then sets the next state to go into the generating terrain state.
For now, I'm also going to leave this blank.
This state's going to do nothing.
Will see in the next video why I'm putting this state here.
So this state is just going to go directly to the next one, which is allocate units.
We allocate units state it's going to be used for adding two units to the map.
So I'm just going to add one for now, which will put at the top of the screen as before.
I'm going to set that to be the object under control.
This state is now done its one and only purpose, which was to add units to the map.
So we set the next state which is allocating units now you might be thinking, Well, why do we need to have such discreet levels of states?
I've just added a unit to the top of the screen.
I don't want the game to continue until the unit has settled on the map.
And so in the allocating unit state, I'm going to sit here on only allow it to progress to the next state once the game is stable.
So I'm going to need out of Boolean, which represents the stability of the physics engine.
The idea here being is that when the unit is falling, we can't move on.
We're still allocating the units unit will hit the ground and bounce around for a little bit.
It's only once it becomes stable that we then go on to the next state, which is start play.
This is the state that allows the play to have some control.
So I'm adding a flag that represents the overall stability of the game, and we'll have to maintain this flag now.
There are probably more efficient locations to put this, but for stability, what I'm going to do is it a rate through all of the objects in my list of objects and see if they're stable?
Flags are set to true.
If all of the objects are stable, then I'm going to assume the game is stable.
There's going to be no more movement, so all of the debris will have settled on.
It's time for things to move on.
In fact, I feel that this is such an important flag.
I was put in a little D book, visualize er in the top corner.
So if the game is stable, is going to draw a little red rectangle just to show me we will, of course, remove this for the final product.
I don't want the plate.
Have any control over the object until we get to the start play state.
So I'm going to create another flag, which represents whether the player has control over the character.
I'm going to set it to false and for all the state, so I don't want the players have control.
I'm going to make sure this flag gets set to false that's in reset its in generate terrain.
I certainly don't want the player to have control whilst the terrain is generating and nor do I want them to have control.
Whilst we're allocating the units and whilst the units of falling from the top of the screen, I don't want them to have control, either.
In fact, it's only once the player can stop playing.
I want to set this to truth, so now I can make all of my keyboard entry input contingent on this flag.
The game will remain in the start place state until the player has completed his action.
So we won't have a flag for this, which I'll call player action.
Complete on this acts, in a way, is a gate on when the player has finished in action.
Chances are we want to go into camera mode to at least look at the action on Watch it on fell.
We know that just before we enter the place state that the players action can't have been finished.
So I'm going to set this to false here.
This may indicate that actually, we need another state, which is start play on playing, and I'll probably update that for the next video.
When we're in camera mode, we don't want the plates have any control.
So all set that back to false the camera mode State is used to track the action, and so we wanted to do that until all the action is finished, so we'll wait until the game is stable again before we moved to the next state, which in this case is just going to be going background to start play again.
I will also say at this point that the play action complete variable can be reset if you're not familiar with state machines.
This approach may seem quite strange on dhe, unnecessarily time consuming, but by responding to input flags, we can change what mode the game is in at any given time, quite easily on the different game, play modes will set the flags necessary to control the simulation engine underneath.
Now, as we're still early days with this whole project, we haven't got very many inputs to our state machine.
In fact, right now all we've got are the system's stability flag on the player action, complete flag.
We mustn't forget to set this flag either, so we know that a player action is complete.
When they fired the weapon, when we set up the fire weapon code, we set the camera to track the missile object that was created on when the missile died.
We set it back to the objects under control, and this gave us this awkward problem that the camera immediately pants with worm.
Now we have a state machine.
We've got a little bit more control over this, so I'm going to set the camera tracking object this setback to know, pointer when the object no longer exists, this makes some sort of sense.
When the camera mode status signal to exit, I'm going to set the camera back to the object under control.
So that's quite a lot of code.
But let's take a little conceive.
It all works.
So I'm starting the application and immediately we've generated the terrain and we've deployed a unit.
We saw the unit fall in.
I've no got control over the unit.
And if I fire the weapon, the camera is automatically following the missile lands and we're now waiting for the debris to settle before the camera pans back to the unit under control.
Let's just see that again.
Full throttle, big pan.
Lots of debris.
And once it's all settled, the camera automatically scrolls back to the unit.
We can also see that our little red rectangle is representing the stability state of the physics engine underneath.
As the units are moving around, they're not stable.
So this red flag indicates when we could move from one state to the next if those states are dependent on stability.
And so I think a state machine has made this all quite smooth and easy to build as the state machine has allowed us to collect and use a whole bunch of Boolean flags in a far more elegant way than lots of nested if statements, in fact, we've not had to make any alterations to the underlying code to facilitate transitions from one mode of gameplay to the next.
And so that's all for this video in the next part of the Siri's, we're going to be looking at adding more stuff to the state machine to turn this into the final game.
If you've enjoyed this video usual, give us a thumbs up.
Have a think about subscribing all of the source code is available on Get hope on if you've any problems, leave some comments in the YouTube comments or log onto the discord server that's just growing in strength.
And I just thought a friendly reminder that occasionally I also stream on twitch.
They're not like the videos on twitch, though it's just really just me coding and listening to cool music.
But I tried one the other night, and it was surprisingly more popular than I thought it would be.