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,528 visits, 13,432 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.

Rotating NPCs

Our second NPC movement type is Rotation, and will have three variations – non-random clockwise, non-random anti-clockwise, and random rotation. These NPCs will stay in the same spot and change directions in a random or non-random fashion. Random and non-random movers have their own object types because each requires slightly different events.

We’ll start with the random rotation, because it has no variation and requires fewer events. The event block starts in the same way as the Static NPC – we need to set the Pair_ID for the base, and to set the position of the sprite to keep it with the base.

Condition

RotateRandom_NPC_Base ▶︎ On created

Action

RotateRandom_NPC_Base ▶︎ Set Pair_ID to RotateRandom_NPC_Sprite.UID

Condition

System ▶︎ Every tick

Action

RotateRandom_NPC_Sprite ▶︎ Set position to (RotateRandom_NPC_Base.X, RotateRandom_NPC_Base.Y)

Next, we need to set up the states for the NPC. We’ll only need two – Rotate and Talking. Starting with Rotate:

Condition

RotateRandom_NPC_Sprite ▶︎ State = Rotate

System ▶︎ Every random(0.1,1.0) seconds

Action

RotateRandom_NPC_Sprite ▶︎ Set animation to “Idle” (Play from beginning)

RotateRandom_NPC_Sprite ▶︎ Set animation frame to choose(0,1,2,3)

And for the state, Talking:

Condition

System ▶︎ For Each RotateRandom_NPC_Base

RotateRandom_NPC_Sprite ▶︎ State = Talking

Sub-event Condition

RotateRandom_NPC_Sprite ▶︎ Direction = Down

Sub-event Action

RotateRandom_NPC_Sprite ▶︎ Set animation frame to 0

Then create three more sub-events for Left, Right and Up directions.

Now we have the states set up, we need to put in the placeholder code for the player interaction – which is essentially the same as for the Static NPC, just using the RandomRotate NPC objects instead:

Condition

RotateRandom_NPC_Base ▶︎ State = “Talking”

Action

Function ▶︎ Call NPCTalk (NPCUid: RotateRandom_NPC_Sprite.UID)

System ▶︎ Wait for signal “EndInteraction”

RotateRandom_NPC_Sprite ▶︎ Set opacity to 100%

RotateRandom_NPC_Sprite ▶︎ Set Direction to Self.InterruptedDirection

RotateRandom_NPC_Sprite ▶︎ Set State to Self.InterruptedState

Player ▶︎ Set State to “Normal”

So your event block for the randomly rotating NPC should look like this:

Most of the events are the same for the non-random rotating NPC, but rather than a single rotating state, this NPC uses one for each direction.

Start by setting up the pairing events in the same way as for the random rotating NPC. Next, we’ll set up the two rotating states. Both will use the same events, but we need to tweak the animations in the NPC Sprite object to make the states look different.

Where the random rotate NPC just has Idle and Walk animations, the non-random NPC will need two ‘Idle’ type animations – in this case, labelled ‘Clockwise’ and ‘AntiClockwise’. The animations contain the same frames, just in a different order – this means when the animation is played, one will appear to be turning clockwise and the other anticlockwise.

There’s one more addition to the Rotate_NPC_Sprite – an instance variable called SpinSpeed. This variable will be used to dictate how quickly an NPC rotates.

Once you have the animations set up, program the rotation states using the following:

Condition

System ▶︎ For Each Rotate_NPC_Base

Rotate_NPC_Sprite ▶︎ State = Clockwise

Action

Rotate_NPC_Sprite ▶︎ Set animation to “Clockwise” (Play from beginning)

Rotate_NPC_Sprite ▶︎ Set animation speed to Self.SpinSpeed

Condition

System ▶︎ For Each Rotate_NPC_Base

Rotate_NPC_Sprite ▶︎ State = AntiClockwise

Action

Rotate_NPC_Sprite ▶︎ Set animation to “AntiClockwise” (Play from beginning)

Rotate_NPC_Sprite ▶︎ Set animation speed to Self.SpinSpeed

Finish this event block by copying over the two parts of the Talking state code (defining the state and calling the interaction function.) Don’t forget to replace the NPC base and sprite objects! You will also need to add a little extra into the Talking state block - seeing as the Clockwise and AntiClockwise animations now have their frames in different orders!

The Up and Down directions shouldn't change, but for Left and Right, there needs to be an additional check to see which animation is playing so we can make it display the correct frame. So for the Left direction, you'll need two similar events. One for each rotation direction:

Condition

System ▶︎ For Each RotateRandom_NPC_Base

RotateRandom_NPC_Sprite ▶︎ State = Talking

Sub-event Condition

RotateRandom_NPC_Sprite ▶︎ Direction = Left

RotateRandom_NPC_Sprite ▶︎ Is animation "Clockwise" playing

Sub-event Action

RotateRandom_NPC_Sprite ▶︎ Set animation frame to 1

Sub-event Condition

RotateRandom_NPC_Sprite ▶︎ Direction = Left

RotateRandom_NPC_Sprite ▶︎ Is animation "AntiClockwise" playing

Sub-event Action

RotateRandom_NPC_Sprite ▶︎ Set animation frame to 3

That should make sure that the animation frames still line up with the direction of the NPC, no matter which way they're rotating.

So, you should end up with this:

Two movement types down, two to go. Next up, set path NPCs!

  • 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!