Random Path NPCs
The final section of this tutorial covers an NPC that will move about in random fashion. The NPC has a timer that when it runs out, the NPC will pick a new direction and movement type, creating the random nature of the movement.
As with the rest of the NPCs, the first step is to set up the pairing events:
Notice the On created event has a few extra bits in it - firstly, we want our NPC to pick a state and direction as soon as it's created. We then need to start a timer which will be defined a little later. But first, let’s set up the states. This NPC will have five states: “Idle”, “Pause”, “Walk”, “Checking” and “Talking”. First, “Idle”:
Condition:
System ▶︎ For Each RandomPath_NPC_Base
RandomPath_NPC_Sprite ▶︎ State = “Idle”
Action:
RandomPath_NPC_Base ▶︎ Set TileMovement Enabled
RandomPath_NPC_Sprite ▶︎ Set animation to “Idle” (Play from beginning)
Sub-Event Condition
RandomPath_NPC_Sprite ▶︎ Direction = Right
Sub-Event Action
RandomPath_NPC_Sprite ▶︎ Set animation frame to 3
Now complete the event block with three more sub-events for the other directions.
To set up the “Pause” state, simply copy the whole event block and paste it below, replacing “Idle” with “Pause”. The states do the same thing
but are used differently, which is why we need the two separate states.
The next state needed is the “Walk” state. This event block comprises the code needed to create the movement, but will also contain events which will trigger the “Checking” state, used to detect solids.
Condition:
System ▶︎ For Each RandomPath_NPC_Base
RandomPath_NPC_Sprite ▶︎ State = “Walk”
Action
RandomPath_NPC_Sprite ▶︎ Set animation to “Walk” & Self.Direction (play from beginning)
RandomPath_NPC_Base ▶︎ Set TileMovement Enabled
RandomPath_NPC_Base ▶︎ Set TileMovement speed to (RandomPath_NPC_Sprite.TileSpeedX, RandomPath_NPC_Sprite.TileSpeedY)
Sub-event Condition
RandomPath_NPC_Sprite ▶︎ Direction = Right
Sub-event Action
RandomPath_NPC_Base ▶︎ Simulate TileMovement pressing right
This covers the actual movement bit of the event block, we now need a sub-event off of Direction = Right to allow to NPC to check for adjacent solids:
Sub-event Condition
RandomPath_NPC_Base ▶︎ TileMovement CANNOT move to (Self.TileMovementGridX+1, Self.TileMovementGridY)
Sub-event Action
RandomPath_NPC_Sprite ▶︎ Set State to Checking
Now, repeat those events for the remaining directions and the “Walk” state is complete!
Moving onto “Checking”, this is where things get more complicated. First, you need to add four Boolean variables to the RandomPath_NPC_Sprite – CanMoveRight, CanMoveLeft, CanMoveUp and CanMoveDown. These will help us tell the NPC which directions to pick when choosing a new one whilst adjacent to a solid. And while you’re adding variables, add the Number instance variable PauseTimer as we’ll need this later on.
So to start the “Checking” state event block:
Condition:
System ▶︎ For Each RandomPath_NPC_Base
RandomPath_NPC_Sprite ▶︎ State = “Checking”
Action
RandomPath_NPC_Base ▶︎ Set TileMovement Enabled
RandomPath_NPC_Sprite ▶︎ Set animation to “Walk” & Self.Direction (play from beginning)
RandomPath_NPC_Base ▶︎ Set animation speed to 0
RandomPath_NPC_Base ▶︎ Set animation frame to 0
Sub-event Action
RandomPath_NPC_Sprite ▶︎ Set CanMoveRight to False
RandomPath_NPC_Sprite ▶︎ Set CanMoveLeft to False
RandomPath_NPC_Sprite ▶︎ Set CanMoveUp to False
RandomPath_NPC_Sprite ▶︎ Set CanMoveDown to False
Sub-event Condition
RandomPath_NPC_Base ▶︎ TileMovement CAN move to (Self.TileMovementGridX+1, Self.TileMovementGridY)
Sub-event Action
RandomPath_NPC_Sprite ▶︎ Set CanMoveRight to True
Repeat the second sub-event for the remaining three direction Booleans.
Now we’re going to need a set of sub-events under the “Can move to” events. These will be all of the combinations of events that see our NPC being surrounded by solids on one, two or three sides. I’ve found it easier to group these sub-events based on the number of available movement directions.
Starting with the scenario that the NPC is surrounded on three sides, (or has one available direction for movement) – you’ll have a sub-event for ‘Can only move Right’, ‘Can only move Left’ etc. Set them up as follows:
Sub-event Condition
RandomPath_NPC_Sprite ▶︎ IS NOT CanMoveDown
RandomPath_NPC_Sprite ▶︎ IS NOT CanMoveLeft
RandomPath_NPC_Sprite ▶︎ IS CanMoveRight
RandomPath_NPC_Sprite ▶︎ IS NOT CanMoveUp
Sub-event Action
RandomPath_NPC_Sprite ▶︎ Set Direction to “Right”
RandomPath_NPC_Sprite ▶︎ Set State to “Walk”
You should have four of these sub-events in total, and they should look like this:
Next, we need six more sub-events to cover the scenarios when the NPC has two available directions for movement: Left/Up, Left/Right, Left/Down, Right/Up, Right/Down, Up/Down.
Using Left/Up as an example:
Sub-event Condition
RandomPath_NPC_Sprite ▶︎ IS NOT CanMoveDown
RandomPath_NPC_Sprite ▶︎ IS CanMoveLeft
RandomPath_NPC_Sprite ▶︎ IS NOT CanMoveRight
RandomPath_NPC_Sprite ▶︎ IS CanMoveUp
Sub-event Action
RandomPath_NPC_Sprite ▶︎ Set Direction to choose(“Left”,“Up”)
RandomPath_NPC_Sprite ▶︎ Set State to “Walk”
Repeat this for the remaining combinations.
Then, there’s the final sub-group: three available movement directions. There will be four events in this group: Can move left/right/up, left/right/down, right/up/down and left/up/down.
Using left/right/up as the example:
Sub-event Condition
RandomPath_NPC_Sprite ▶︎ IS NOT CanMoveDown
RandomPath_NPC_Sprite ▶︎ IS CanMoveLeft
RandomPath_NPC_Sprite ▶︎ IS CanMoveRight
RandomPath_NPC_Sprite ▶︎ IS CanMoveUp
Sub-event Action
RandomPath_NPC_Sprite ▶︎ Set Direction to choose(“Left”,“Right”,“Up”)
RandomPath_NPC_Sprite ▶︎ Set State to “Walk”
Again, repeat this for the other three combinations. And that completes the “Checking” state!
The only remaining state to put in is “Talking”:
Condition:
System ▶︎ For Each RandomPath_NPC_Base
RandomPath_NPC_Sprite ▶︎ State = “Talking”
Action
RandomPath_NPC_Base ▶︎ Set TileMovement Disabled
RandomPath_NPC_Sprite ▶︎ Set animation to “Idle” & Self.Direction (play from beginning)
Sub-event Condition
RandomPath_NPC_Sprite ▶︎ Direction = Down
Sub-event Action
RandomPath_NPC_Base ▶︎ Set animation frame to 0
You could just copy this from the SetPath NPC section and replace the base and sprite objects. Either way, make sure you have all four directions coded in with their appropriate animation frames.
The next thing to do is to set up two timers: “RandomNPCMove” and “MovementChooser”. These will work together to create the random movement we’re after. Let’s do “RandomNPCMove” first:
Condition:
RandomPath_NPC_Sprite ▶︎ On timer “RandomNPCMove”
Action
RandomPath_NPC_Base ▶︎ Set State to “Pause”
RandomPath_NPC_Sprite ▶︎ Start Timer “MovementChooser” for Self.PauseTimer
Seeing as the “MovementChooser” timer is being started here, we should probably define what that does:
Condition:
RandomPath_NPC_Sprite ▶︎ On timer “MovementChooser”
Action
RandomPath_NPC_Base ▶︎ Set Direction to choose(“Up”,“Down”,“Left”,“Right”)
RandomPath_NPC_Sprite ▶︎ Set State to choose(“Idle”,“Walk”)
Sub-event Condition
RandomPath_NPC_Sprite ▶︎ State = “Idle”
OR
RandomPath_NPC_Sprite ▶︎ State = “Walk”
Sub-event Action
RandomPath_NPC_Base ▶︎ Start timer “RandomNPCMove” for Self.StateTimer
You’ll notice we’re using two instance variables here – StateTimer and PauseTimer. StateTimer defines how long the NPC stays in a specific state, while PauseTimer defines how long the NPC remains paused before choosing a new direction and state.
The final event block to create is the same as the rest of the NPCs – what happens when the player talks to one of our NPCs. Again, you can copy the event block from a previous NPC, but it will need a few tweaks – namely to make sure our timers work correctly. So the full block should be:
Condition
RandomPath_NPC_Base ▶︎ State = “Talking”
Action
RandomPath_NPC_Sprite ▶︎ Set timer “RandomNPCMove” paused
Function ▶︎ Call NPCTalk (NPCUid: RandomPath_NPC_Sprite.UID)
System ▶︎ Wait for signal “EndInteraction”
RandomPath_NPC_Sprite ▶︎ Set opacity to 100%
RandomPath_NPC_Sprite ▶︎ Set Direction to Self.InterruptedDirection
RandomPath_NPC_Sprite ▶︎ Set State to Self.InterruptedState
Player ▶︎ Set State to “Normal”
RandomPath_NPC_Sprite ▶︎ Set timer “RandomNPCMove” resumed
And that’s it! We’ve covered how to make four different types of NPC movement, and how to have the player interact with each of them. This may not work for every project, and I’m sure there are ways to tweak this to make it better, but I hope you still find this useful!