Categories
Basic Tutorials

Basic Coding 4: Conditionals

Preface

Variables are useful for storing data, which means we can use them for lots of things. One thing that makes them even more interesting is examining the data that is stored, and changing the behaviour of a game based on that data. Introducing…conditionals!

Introduction

A “conditional” is a term used by programmers to refer to a line of code which asks a “yes or no” question, and then runs different code depending on the result. If the result is true, the game might continue in one direction. If the result is false, the game might do something else. Using our flowchart analogy from the previous Code Tutorials, a conditional looks like this:

Developers use conditionals all the time, and they play a crucial role in games that you can win or lose. In this tutorial, you will learn how to write a conditional statement and how to use it in a game.

Create A Game

Create a new blank game and enter the Advanced Editor.

Start with a new blank game.

Add A Prop

Add a Prop to the Game World. Choose a Prop that might explode (we will use a Barrel).

Add a Barrel (Exploding) Prop

Create A New Script

With the Barrel Entity selected, use the Entity Explorer on the right hand side to add a new Script. Entity -> Add -> Script -> New Script. Call your Script TimedExplosive.

Add a Script called TimedExplosive to the barrel.

Open the Script by clicking on the pencil icon in the Entity Editor. 

Click the pencil icon to edit the Script.

Functional Breakdown

The flowchart for a timed explosive device might look something like this:

As you can see, there are a few steps that we need to code. The core of this code will occur on the OnTick function, which gets called every frame.

Creating A Timer

Within the Init() function, create a variable to store the time remaining as a number. Call this variable timeRemaining and set it to 5, which will mean 5 seconds:

function TimedExplosive:Init()
    self.timeRemaining = 5
end

In order to keep the time, you will need to write some code within the OnTick function, which is called every frame. However, like most games, Crayta’s “frames per second” is variable, so we won’t necessarily have the exact same time interval between function calls.

Tech Tips: Frames And Frame Rate

A frame, in this context, is referring to a moment in time when Crayta is drawing the visible aspects of the game on your screen. The speed that Crayta aims to do this is 60 times every second, which is referred to as the Frame Rate. A Frame Rate is measured in “frames per second” or FPS, and whilst Crayta aims to stick to 60 FPS, it is not always possible to rely on this.

The frame rate of a game can vary during gameplay, depending on a variety of factors. These factors include: how complicated the visual components are, how fast your computer is, and whether your computer is trying to run other programs at the same time as Crayta (amongst others).

In order for our timer to be accurate, it cannot rely on the OnTick() method to be called at exactly the same interval. Fortunately, Crayta’s OnTick function gets given a variable that can tell us how much time has passed since the last time OnTick() was called. We can use this variable to reduce the timeRemaining variable.

Add an OnTick function to your Script.

function TimedExplosive:OnTick(deltaTime)

end

By putting deltaTime in the brackets of this function, we can store the value that is passed to this function, which is the amount of time since the last time this function was run. Now you just need to reduce timeRemaining by that value. Add the following code to your OnTick function.

function TimedExplosive:OnTick(deltaTime)
    self.timeRemaining = self.timeRemaining - deltaTime
    Print("Time remaining: ", self.timeRemaining)
end

Tech Tips: deltaTime?

It doesn’t particularly matter what identifier you give a variable (as long as it doesn’t start with a number), but there are some common terms that are used by programmers so that code can be easily read and understood now and in the future. 

Delta is a Greek letter (Δ) that is used in Maths to denote the difference between two values. Here, Delta is used because it stores the difference between the last time this function occurred, and the present time in seconds.

Notice that this code also outputs the time remaining to the Console, so that you can test that this code is working.

Run the game.

Press ‘O’ to Open the Console and ensure that the timeRemaining is decreasing at a steady rate. (Hint: You can press ALT to turn your Console fully opaque).

Check that the time is decreasing at a steady pace (it should be one whole number per second).

Adding A Conditional Statement

At the moment, the timeRemaining continually counts down, into the negative numbers and onwards to negative infinity. If you want the timer to do something when it reaches 0, you will need to use a conditional.

Add the following line of code to your OnTick function:

function TimedExplosive:OnTick(deltaTime)
    self.timeRemaining = self.timeRemaining - deltaTime
    Print("Time remaining", self.timeRemaining)
    if (self.timeRemaining <= 0.0) then
        Print("Time is up!")
    end
end

This code stipulates that if the timeRemaining reaches 0, output that the timer has finished to the console. 

If we want to stop the timer counting down when it reaches 0, to stop it entering the negative numbers, we will need to use an “else”.

Tech Tips: If, Else, Else if

A conditional can check “if” something is true before performing some code, but it can also run different code if the condition is not true using the keyword “else”. This makes sense if you read the code like it’s English:

if conditionA is true then
Do something
else
Do something different

You can add further conditions to the else aspect in order to branch in many different directions. For example:

if conditionA is true then
Do something
else if conditionB is true then
Do something different
else
Neither condition is true, do something different from either

You can chain up as many if…else if…else if… as you like, but bear in mind that the conditions will be checked in the order you write them. So if conditionA was true, then it doesn’t matter if conditionB is true as well, Crayta will only run the code that was specified for conditionA (do something).

Change your timer Script so that it uses an else before it decreases the timeRemaining:

function TimedExplosive:OnTick(deltaTime)
    if (self.timeRemaining <= 0.0) then
        Print("Times up!")
    else
        self.timeRemaining = self.timeRemaining - deltaTime
        Print("Time remaining", self.timeRemaining)
    end
end

Save your Script, and return to the game Editor to test your game.

You should see the message “Time’s up” appear when the countdown has reached 0, instead of negative numbers.

Adding Explosions

Now that you have used a conditional, you can celebrate by making the barrel explode when the timer runs out.

In the game Editor, add an explosion Effect and an explosion Sound to your prop.

Add an explosion Sound and Effect to your barrel (it is about to explode after all).

Return to your Script.

To play a Sound or an Effect, you will need to set it’s active variable to true. In order to set the active variable to true, you will need a way to reference these Entities.

Add two Properties to your Property Bag. Remember, adding Property will show the variable in the Crayta game Editor, so you can change the value there:

TimedExplosive.Properties = {
    { name = "ExplosionEffect", type = "entity" },
    { name = "ExplosionSound", type = "entity" },
}

Go to the game Editor. Click on the Prop Entity set to explode.

Set the ExplosionEffect and ExplosionSound Properties to hold the Explosion Effect and Sound Entities

Hookup your Sound and Effect to the respective Properties on the TimedExplosive Script in the Entity Editor.

Whilst you are in the game Editor, make sure that the Explosion Effect and the Explosion Sound both have their Active checkboxes unticked.

Make sure that the explosion Sound and Effect have their active boxes unticked.

Return to your Script.

To set the active variable on the Sound and the Effect, add the following lines of code underneath your Print(“Times up!”) line:

        self.properties.ExplosionEffect.active = true
        self.properties.ExplosionSound.active = true

Reading through the code, you can see that the active variable is being set to true.

Before continuing, it is also a good idea to remove the barrel once it has exploded (things usually disappear when they explode…). To do this, you need to make your barrel invisible, and turn off collisions. Your final conditional statement in your OnTick function should look like this:

function TimedExplosive:OnTick(deltaTime)
    if (self.timeRemaining <= 0.0) then
        Print("Times up!")
        self.properties.ExplosionEffect.active = true
        self.properties.ExplosionSound.active = true
	self:GetEntity().visible = false
	self:GetEntity().collisionEnabled = false
    else
        self.timeRemaining = self.timeRemaining - deltaTime
        Print("Time remaining", self.timeRemaining)
    end
end

That’s it! Now test your game and wait for the timer to run out. 

Your final code should look like this:

local TimedExplosive = {}

-- Script properties are defined here
TimedExplosive.Properties = {
	{name = "ExplosionEffect", type = "entity"},
	{name = "ExplosionSound", type = "entity"},
	--{name = "health", type = "number", tooltip = "Current health", default = 100},
}

--This function is called on the server when this entity is created
function TimedExplosive:Init()
	self.timeRemaining = 5
end

function TimedExplosive:OnTick(deltaTime)
	
	if (self.timeRemaining <= 0.0) then
		Print("Times up!")
		self.properties.ExplosionEffect.active = true
		self.properties.ExplosionSound.active = true
		self:GetEntity().visible = false
		self:GetEntity().collisionEnabled = false
	else 
		self.timeRemaining = self.timeRemaining - deltaTime
		Print("Time remaining: ",  self.timeRemaining)
	end
	
end

return TimedExplosive

Recap

In this tutorial, you learned about framerates, and how to use a variable to create a timer. You also added a conditional in order to do something when the timer runs out, and to do something else if the timer had not run out.

Adding Polish

You can use this same Script to add timers that do a variety of different things. Based on Scripts that you’ve learned in previous tutorials, experiment by doing the following:

  1. Add an Entity to the game which a player can interact with
  2. When the player interacts with it, it starts a timer that lasts 2 seconds 
  3. When the timer runs out a door opens

Next steps

Conditionals are very powerful, and really useful for making a dynamic and engaging game. The last topic in this series looks at how you can use these fundamental principles of programming with some of the inbuilt systems in Crayta. Next up, physics!