Creating RPG-style NPCs

9

Index

Attached Files

The following files have been attached to this tutorial:

.c3p

npc-example.c3p

Download now 237.03 KB

Stats

7,480 visits, 13,378 views

Tools

Translations

This tutorial hasn't been translated.

License

This tutorial is licensed under CC BY 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

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!

  • 3 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • It's a bad idea to use Wait, about 10% of the times for complex projects it bugs and doesn't work, especially in triggers. Using a global timer would be better, though a bit clunkier.

  • Nice! This will also help the user get familiar with functions and passing parameters through which is always daunting to think about when you haven't used them.

      • [-] [+]
      • 2
      • Laura_D's avatar
      • Laura_D
      • Construct Team Community Manager
      • 2 points
      • (0 children)

      Tell me about it! I'd been putting off using functions for ages because I had no idea what to do with them!