Categories
Basic Tutorials

Basic Tutorial 2: Events

Preface

Every game needs user interaction. Without interaction, games lack their most powerful ingredient – player choice. In this tutorial, we will start to add more interactivity to our games using an event-driven system. 

In the context of a game, an Event could be anything that changes in the game world. It could be the user pressing a button on their gamepad, a countdown timer reaching zero, or two enemies colliding. There are three main types of Event :

  • User interface – the user has interacted with something in some way.
  • Timer – a timer has reached a value.
  • System – an embedded system (such as the physics engine) has fired an event.

When an Event occurs in our game, we can use that event to cause a reaction. This tutorial will be focusing on adding functionality to our game that causes a response to an Event, and changes the state of the game.

Introduction To Puzzle Games

Puzzle games can be as elaborate and exciting as you like. They can be made more complicated by giving obscure clues and adding layered objectives, or easier by giving more clues and reducing the number of objectives.

For example, a puzzle game could be as simple as “Open the door”, where the user just opens a door. Or it could be a bit more complicated. For example, if the door needs a key, but the key is locked in a vault, and to get in the vault you need the code which is written on the inside of a teapot which you need to smash with a hammer, but the hammer is positioned a bit too high to reach so you need a box to stand on…you get the picture.


An example of an easy puzzle game. The player has one simple puzzle that stands between them and the objective.
A more difficult puzzle game would have several puzzles between the player and the objective. You could also increase the difficulty of the puzzles, but make sure the player can still solve them!

This tutorial will guide you through making an easy puzzle game, and then add more obstacles to make it harder.

Create Your Game

Create a new Empty Game and call it “Super Smash-n-Grab”. 

When you enter the game, open the Library by pressing Y

Press Y to open the Library and press Y again to open the Community tab. Find and install the Package “Super Smash-n-Grab”. If you have any difficulties with this step, revisit the Packages tutorial to get a rundown on installing Packages in Crayta.

Navigate to the Store, and install the “Super Smash-n-Grab Package.

The SuperSmashNGrab Package gives you everything you need to make a simple heist-themed puzzle game.

First you need to add your bank vault. Open the Library (press ‘Y’ again), use R2 and L2 to navigate to the Templates tab. Use the D-PAD to highlight the Bank Vault Template.

Press “A” to add it to your Hotbar

Add a BankVault Entity to your game world.

Close the Library by pressing “B”. Add an instance of the bank vault Template to your world. Find a good location and press R2 to place it. Press RB or LB to select an empty Hotbar slot to make it easier to navigate the scene.

Gaining Entry: Unlock The Door

By default, the door of the Bank Vault is locked. Before we Preview the game we need to unlock the door and then link the keypad to the door to be able to open it.

Start by looking at the door, and open the Entity Editor by pressing X. If you navigate to the bottom of the Entity Editor you can find the Script: LockedDoor Properties.

Aha here is the first problem. You can see that the “locked” Property is checked, which means the door is currently locked. Uncheck the locked checkbox.

Open the Entity Editor for the Bank Vault door.
Uncheck the “locked” Property checkbox.

Preview the game by holding the DOWN D-PAD.

Interact with the keypad next to the door by looking at it and pressing X. The door should swing open.

Interacting with the keypad should make the door swing open.

Seems pretty easy to get in the bank vault, right? This is because the door is unlocked by default. Let’s turn up the difficulty of this puzzle game. Return to the game editor by holding DOWN D-PAD.

Adding An Obstacle

In Edit mode, look at the door and press X to enter Entity Editor.

Edit the Properties of the vault door.

Make sure you are editing the door by checking the name at the top of the Entity Editor – it should be “BankVault-VaultDoor”. Return the Locked Checkbox to its Locked state by highlighting the box and pressing A.

Lock the bank vault door again.

You have just created a puzzle. Now we need to give the player a way to solve it!

Gaining Entry: Detonation

This tutorial will cover blowing open the door with TNT first, and then using a key to open a different door. 

Creative Control: Player Choice

Games like Hitman and Metal Gear Solid strive to have multiple solutions to each problem. Giving your player choice forces them to decide, makes the journey more interesting and makes the game feel less linear.
Jam some other ideas on other ways to get past a door. For example, you could use the voxel tools to create a hidden tunnel under the vault, or add a keycard that unlocks the keypad, or you could blow the door open with TNT! The only limit is your imagination (and, let’s face it, physics). 

Open the Library and navigate to Templates.

Open the Templates tab.

Switch to an empty slot on your Hotbar and add the TNT Template to your Hotbar.

Place the TNT on the door of your bank vault.

Put some TNT on your bank vault.

Open the Entity Editor for the TNT and change the position and rotation Properties to fine tune the position of the TNT. It should be flat against the door.

Fine-tune the rotation and position of the TNT.

Open the Library again and open the meshes tab. Add the TNT Plunger to your Hotbar.

Add the TNT Plunger Template to your Hotbar.

Place the TNT Plunger nearby, so you can see the door when you press the plunger. 

Place the TNT Plunger a short distance from the vault door.

Preview your game and make further adjustments as required.

If you try interacting with the plunger in Preview mode you will find that nothing happens. This is because we haven’t told the TNT Plunger to listen to any events yet. We need to tell the TNT Plunger what to do when the user interacts with it, otherwise nothing happens. Return to edit mode and we will do just that.

Tech Tip: Events Terminology

Listening, triggering, handling…these are terms used by game developers to discuss Event systems. Using the correct names is super useful when you need to communicate your vision to other members of your game development team.

Event trigger/ Event fire: When an event occurs, we say that the event has “fired”. The thing that caused the event to fire is called the “trigger”. 

Event handler: The code that is executed due to an Event being fired is called an “Event handler”. 

Event listener: An event listener links an Event Handler to an Event. In some game engines we would need to write this in manually, but Crayta manages our Event listeners for us. 

In edit mode, look at the TNT Plunger and press X to open the Entity Editor

Edit the TNT Plunger Properties in the Entity Editor.

Use the D-PAD to navigate to the bottom of the Entity Editor to find the onInteract Property.

Crayta Entities automatically listen out for events that might affect their state in the Game World, such as colliding with another Entity or the player interacting with an it. You can make things happen by adding functions to the event property boxes. 

There are 2 possible events that we can listen for on the TNT Plunger:

  • onInteract: The player looks at this entity and presses X
  • onCollision: The player’s character touches this entity

Tech Tip: Functions

A function is a chunk of code with a single identifier. Programmers group chunks of code into functions so that they can be re-used easily, and to help organise the code into a logical pattern. A single script can have multiple functions. 

A function identifier will usually describe the intention of the code within the function. For example, a function with the identifier “makeInvisible()” should make an entity disappear, a function with the identifier “explode()” should make an entity explode. To run a function, we “call” it.

For example, here is the function within the LockedDoor script which “destroys” the door:

function

LockedDoor:DestroyDoor() self:GetEntity().collisionEnabled = false self:GetEntity().visible = false

End

If you read the code above, it states “for the entity this is attached to, make collisionEnabled false and visible false”. What this means, is that the collisions are disabled and it is made invisible. This is a simplified way of removing an entity from the game. It’s not the most optimal way, but completely destroying an entity comes with other programming responsibilities that are beyond the scope of this tutorial. 

Use the D-PAD to highlight the “+” next to onInteract and press A. Now, highlight the box with the placeholder “(…)” and press A again. 

Add an event handler to the TNT Plunger’s Interact Event. Select the “+” next to onInteract.

You will see three new property boxes appear; Entity, Script and Event. We will use these properties to target a specific entity, target a script attached to that entity, and choose a function within that script. 

Highlight the Entity field and press A. This will display a list of every entity in your scene. 

Pressing A on the Entity Property dropdown will display all of the Entities within your Game World.

Tech Tip: Parents and Children

An Entity in Crayta could be a Mesh, a Voxel Mesh, a Sound or any other item that is added to your game. 

When you add an Entity to your game, Crayta will make it a “Child” of another Entity so that it is attached to something in your game. 

For example, a table is added to the game. Then a cup is placed on that table. Because the cup is on the table, Crayta will add the cup as a child of the table. Then, if we move or rotate the table, the cup will move or rotate with it.

Parent/child relationships exist in most game engines, and are shown using lists:

  • World
    • Terrain
      • Table
        • Cup
      • House
        • Door
        • Television

When we added our TNT to the door, Crayta renamed it to tNT1, so that we can distinguish between that specific TNT, and any other ones we might add to our game later on. 

To find tNT1, press DOWN D-PAD to highlight the Terrain Entity. Press RIGHT D-PAD to expand the list of children added to the Terrain Entity. Do the same with BankVault and you should see BankVault-VaultDoor. Continue expanding the lists to find tNT1. In this tutorial, the tNT1 was here:

Use the dropdown menu to find the TNT Entity you placed on the vault door.

World > terrain > bankVault1 > BankVault-VaultDoor > tNT1

Highlight tNT1 and press A

When you select the TNT, the Event Property should automatically fill with the tntDetonator Script.

Our TNT only has one script attached to it, so the Script Property is automatically filled with our tntDetonator script. If there was more than one, we could use this box to determine the exact script.

Finally, highlight the arrow next to Event and press A. You will be given the choice of two functions that exist in the tntDetonater Script; Detonate() and Init(). Select Detonate().

Press B to close the Entity Editor. You have now hooked up the TNT Plunger to run the Detonate() function on the TNT that is attached to the bank vault door.

Preview your game.

During the game Preview, interact with the TNT Plunger by looking at it and pressing X. You will notice that the TNT detonates, as expected, but the door to our bank vault remains firmly locked. We can fix that by adding another Event Listener onto the TNT Plunger’s onInteract Event.

Return to Edit mode, open the Entity Editor for the TNT Plunger once again. Navigate down the Properties and press the “+” next to onInteract, underneath the previous function we added. Using the same method that we used when adding the Detonate function, add the following function:

  • Entity: bankVaultDoor
  • Script: LockedDoor
  • Event: DestroyDoor()
Select the “+” under onInteract to add another event listener.
Select the BankVault Door and choose the Script: LockedDoor and the DestroyDoor() function.

You should now see two items in the onInteract field; tNT1 / tntDetonator and BankVault-VaultDoor / LockedDoor.

Preview your game again and interact with the TNT plunger. You should find that the TNT explodes, and the door is destroyed. ACCESS GRANTED.

Preview the game, and blow open the door with TNT.

We can add as many functions as we like to this event listener, or to the other event listeners. If you choose to program your own functions you can use this Event Property to make them run.

Gaining Entry: Unlocking The Door

So far we have a bank vault where players can gain entry through the use of explosives. Great! What happens next? Well, usually once you have got the goods you need to escape without getting caught. We are going to use a new instance of just the Vault Door to create another obstacle. This obstacle will get in the way of the player escaping.

Add a different door Mesh to your hotbar and add it to the Game World.

Add door from the Meshes Library to your game world
Build a bank around your bank vault and vault door.

Now your player will have to gain entry into the bank first, then the vault and then escape out of the building.

Creative Control: What’s Your Game About?

This tutorial covers adding two doors, but you can use the same techniques to add more doors, change the scenario and change the direction of the game. 

For example, the player could start in a dungeon and have to escape a castle, or rescue someone from a prison. Requiring obstacles to be solved in different ways keeps your players guessing and makes the game more interesting. Get creative!

Don’t forget you can change the Mesh Asset Property of a Template. So you could change the bank vault door to a jail cell door, or a door to a townhouse.

In Edit mode, open the Library and add the Keycard Template to your hotbar. Then close the Library

Add the Keycard Template to your Hotbar.

Place the keycard in your game world. Preview your game and adjust the position of the Keycard using the Entity Editor if necessary.

Creative Control

You could place your keycard somewhere obvious, or you could place it somewhere devious. You could also consider where someone might leave a keycard by accident, such as on a table (look in the Meshes tab in the Library for inspiration). If you’re more of the trickster type, be sure to give your player clues so that they don’t get frustrated!

Return to Edit mode and open the Entity Editor for the Keycard.

At the bottom of the Entity Editor you will find a script attached to this Entity; HideShowScript. The next step in this tutorial will show you how to use the Event Properties to unlock the door and make the keycard disappear, simulating that you have picked it up.

Add the following to the Keycard’s onInteract Event Property:

Entity: Keycard1

Script: HideShowScript

Event: Hide()

Edit the Properties for keyCard1.
Select keyCard1 as the Entity.
Select the Hide event.

Preview your game and interact with your keyCard. You will find that it disappears, simulating that you have “Picked it up”. 

Return to Edit mode.

To make the outer door unlock, you will need to add a Script to it. The Script is the same Script used on the bank vault door.

Open the Entity Editor for the outer door.

Open the Entity Editor for the outer door.

At the bottom of the Entity Editor click the Add to Entity button. Select Script > LockedDoor and press A to add the LockedDoor Script to this door.

Add the LockedDoor Script to the outer door.

Check the locked checkbox to ensure that the door starts locked.

Lock the outer door using the locked checkbox.

Click the + on the onInteract and choose the Door instance > LockedDoor > ToggleOpen(). This will mean when you interact with the door it will open, but only if it’s unlocked.

Add the OpenDoor() Event Listener to the onInteract Event Property of the front door.

Unlocking the door is the last piece of this puzzle.

Open the Entity Editor for the Keycard once again.

Return to the onInteract field. This time we will also add the unlock function to the onInteract event. Select the following:

  • Entity: outer door (make sure to select the right door here)
  • Script: LockedDoor
  • Event: UnlockDoor()

Note: Make sure that you have both the key1 / HideShowScript and bankVaultDoor1 / LockedDoor in the onInteract field.

Select the UnlockDoor as the additional Event Handler to the onInteract Event Property of the Key.
Select your door as the entity, then the LockedDoor script, and the UnlockDoor event.

Close the Entity Editor for the Keycard. You have created a way to pick up the key and unlock the door. 

Preview your game. Interact with the Keycard and you should find it disappears (and behind the scenes we know the door has unlocked). Then, interact with the outer door and the door should swing open. 

Tech Tip: Testing

Testing is a vital part of making games as it ensures that the game you have made is doing what you expect it to do. 
Most of the time, developers test the game as they develop new features, but sometimes adding a new feature, or changing a part of the gameplay, may cause unexpected or unwanted things to happen to other parts of the game. Unwanted behaviour in a game is called a “bug” and needs to be fixed before continuing with the game development.
For example, in our situation, selecting the wrong door to “open” when the player interacts with the keycardReader might cause the vault door to open, rather than the exit. This would be very confusing to the player, and they won’t be able to get out!
Test your game regularly to make sure your game is doing what you want it to do, and make sure to fix any problems when they come up.

Recap

Congratulations, you have created a bank heist game. In this tutorial you have looked at:

  • What are Events and how do we use them
  • Using the Event Properties to add interactivity to the game
  • Changing a mesh and adding more interactivity to craft new puzzles

How did you get on? If there were moments which didn’t work how you wanted, now is a good time to revisit your game and fine-tune it, and practice what you have discovered in this tutorial.

Adding Polish

If you want to carry on adding to this game, here are some ideas that you can explore using the techniques we have looked at in this tutorial:

  • Hide the keycard in the bank vault itself, so that the player has to get in the bank vault before they can leave
  • Give your player the choice to either blow up the vault door, or use a keycard hidden somewhere else in your game
  • Create another obstacle, where the player has to pick up some TNT before it appears outside the bank vault door.
  • Make a dungeon “escape room” by linking multiple obstacles that need to be solved before the player can escape

Next Up: UI

The next tutorial will look at how we can display information to your players using the inbuilt UI system. This will allow you to add written narrative elements and dialog, show player health or points, and show the player a win or lose message. 

Combining communication with events will enable you to create completely unique and exciting narratives that reward and challenge your players.

Basic Tutorials 3: UI