Categories
Basic Tutorials

Basic Coding 2: Variables and Datatypes

Preface

Now that you have played with Crayta’s Advanced editor, and had a go at coding, you can start to learn how to write your own code.

A lot of the principles of coding are the same regardless of the programming language. Many of the practices you learn in these tutorials will be transferable to other game engines, and to other software development also, so it’s worth investing a bit of time to ensure that you know what the code is doing. Make sure to “add polish” at the end, and play around with what you have learned to cement your understanding.

Introduction

Fundamentally, code is instructions that tells the computer how to manipulate data. By manipulating data in certain ways, we can play games, make barrels explode and fire bazookas.  

This tutorial looks at: 

  • Storing data in variables
  • Types of data we can store

Create A Game

Create a new blank game and enter the advanced editor.

Add A Mesh

Using the library on the left, add a Mesh to the game. I have added the Checkpoint. 

Add a Mesh to your game.

Create A New Script

With the Entity selected in the Entities Explorer on the right hand side, click Entity -> Add -> Script -> New Script. Call your Script InteractionCounter and press OK.

Create a new Script called InteractionCounter, attached to the Checkpoint.

We are going to count the number of times the player interacts with this object, and output the result in the console.

Creative Control: Interaction

Players can “interact” with Entities during gameplay by looking at an object and pressing X. The term interact can mean potentially any action, so it’s up to you as a game designer to decide what that interaction is. For example, interacting with a book Mesh could mean reading it and displaying some text, or picking it up and adding it to the players inventory, or throwing it at another player. If you can code it, then it can happen.

In this tutorial, you will be using code to count the number of times the player interacts with a single Entity.

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

Open the Script for editing by clicking the Edit Script button.

To code a solution to this problem, we need to break the problem down into steps. Then we can code each step, one-by-one, and eventually reach our solution. Sometimes it can be useful to draw a flowchart to do this, so a flowchart for this problem would look like this:

Set Counter To 0

In order to “count” the number of interactions, we will need to use a variable. Variables are a way of storing data, so that we can refer back to it later, or change it. Here are the simplest types of data that variables can store:

Type of dataExample value
Number12, 15.6, 8, 0, -42
String“Hello World”, “My word”
BooleanTrue or False

Let’s look at an example. A variable myVariable, which is a Number might have the value 12:

local myVariable = 12

This means that I can use myVariable in my code like this:

self.position.x = myVariable  — This will move the Entity so that it’s x-coordinate is equal to myVariable, which is 12.

The benefit of using variables is that if we want to change what is stored inside them whilst the game is running. So for example, we can do:

self.myVariable = 12

self.myVariable = 15

self.position.x = self.myVariable -- This will move the Entity to x-coordinate 15

Tech Tips: Naming Variables

A variable can be called almost anything. It can include numbers, but it cannot start with a number. E.g.

local spooky4u = "Yes" -- allowed
local 2spooky4u = "Yes" -- not allowed

A variable name cannot include any spaces, so if you want to use multiple words, a general convention is to use “Camel Case”. Camel Case means every new word starts with a capital letter, but no spaces. For example, rather than

This is my variable name = 12 -- wrong

We would use:

thisIsMyVariableName = 12 -- correct

Be aware that the letter CASE is important in code. A variable all in uppercase MYVARIABLE will not be the same variable as one in camelCase such as myVariable, or in lowercase such as myvariable.

You can see that there is already some code in the InteractionCounter Script. When the game starts, the script’s Init() function is called.

--This function is called on the server when this entity is created
function InteractionCounter:Init()
    -- Any code placed in here will run when this function is called
end

We should use this as our starting point to accomplish the first step of our flowchart.

Replace the Init() function with the following code:

–This function is called on the server when this Entity is created

function InteractionCounter:Init()
	self.counter = 0
end

This means that when the game is started, a variable called “counter” is created, and made to hold the value 0.

Tech Tips: Variable Scope

Accessing a variable you have created may or may not be possible depending on the variable scope.

You can declare a variable in three different ways in Crayta. The way that you have declared it:

self.counter = 0

Means that we can use this variable only in this Script, but we can use it anywhere within this Script .

If we write the variable declaration like this:

local counter = 0

This would mean we could only use the variable in the function, conditional or loop that it is within. It wouldn’t be accessible anywhere else.

If we write the variable declaration in the Properties Bag at the top like this:

InteractionCounter.Properties = {
    {name = "counter", type = "number", default = 0},
}

Then we can access this property anywhere, including the Crayta Level Editor in the Entity Editor, as well as other Scripts.

When User Interacts…

A Crayta Script has different functions that are called when an Event occurs in the game. One of these functions is OnInteract(), which is called when a Player interacts with an Entity.

The Init() function was automatically added to the Script when you created it, but the OnInteract() function was not. You will need to add this yourself. Add the OnInteract function to your code, so that your Script now looks like this:

local InteractionCounter = {}

-- Script properties are defined here
InteractionCounter.Properties = {
	-- Example property
	--{name = "health", type = "number", tooltip = "Current health", default = 100},
	{ name = "thing", type = "string" }
}

--This function is called on the server when this entity is created
function InteractionCounter:Init()
	self.counter = 0
end

function InteractionCounter:OnInteract()

end

return InteractionCounter

Increase Counter By 1

As described earlier, one of the benefits of using a variable to store data is that we can change it whilst the game is running. In our situation, we will need to change the value of the variable that we use to count the number of interactions – we will need to increase the value by 1 each time a Player interacts with the Entity.

We already know that the OnInteract() function is called when a Player interacts with this Entity, so we know that we need to increase the counter within this function.

We don’t necessarily know what value the variable will be when we want to update it, so we will need to change the value relative to whatever it holds at the time.

We can’t do this:

function InteractionCounter:OnInteract()
    self.counter = 1
end

Because the next time this function is called, it will just set the counter to 1 again. This will perform the following:

EventDescription
Game startedself.counter set to 0
Player interacts with Entityself.counter set to 1
Player interacts with Entityself.counter set to 1
Player interacts with Entityself.counter set to 1

Therefore, we need to use it’s own value in the arithmetic. So update your OnInteract() function:

function InteractionCounter:OnInteract()
    self.counter = self.counter + 1
end

Now our script does this:

EventDescription
Game startedself.counter set to 0
Player interacts with Entityself.counter set to self.counter + 1 = 0 + 1 = 1
Player interacts with Entityself.counter set to self.counter + 1 = 1 + 1 = 2
Player interacts with Entityself.counter set to self.counter + 1 = 2 + 1 = 3

Output The Counter To The Console

As a developer, it’s really useful to be able to communicate from the code to the Player testing the code without needing to build the User Interface to do this. Handily, Crayta includes a Console, which is a simple way to send messages from the code to the Player.

To send a message from the code to the player, we can use the Print() function. We will need to call this function to output the value of self.counter. 

Change your OnInteract() function to the following:

function InteractionCounter:OnInteract()
    self.counter = self.counter + 1
    Print("You have interacted " .. self.counter .. " times")
end

Notice that we put what we want to output between the brackets of the Print() function. Also, remember to pay attention to the CASE of the letters.

Tech Tip: Concatenating Strings

Just in case you missed it, a “string” is the term programmers use when talking about words and alphanumeric characters stored in a variable) together.

In most programming languages, you can join multiple strings together, and turn them into one long string. This is called concatenating.

In Lua, to join two strings together you can use the notation .. in between two strings you want to join together. Here, you put this between the count variable and a string. It temporarily transforms the count variable from “number” datatype, into a “string” datatype, so that it can be output to the Console.

Your final code should look like this:

local InteractionCounter = {}

-- Script properties are defined here
InteractionCounter.Properties = {
}

--This function is called on the server when this entity is created
function InteractionCounter:Init()
  self.counter = 0
end

function InteractionCounter:OnInteract()
  self.counter = self.counter + 1
  Print("You have interacted " .. self.counter .. " times")
end

return InteractionCounter

Testing

Save the script (File -> Save) and return the Game tab.

Preview the game. To open the Console press “o” on your keyboard.

Interact with the Entity, and you should see that the Console outputs the value of your counter.

Interact with the Mesh to see the Console print your counter variable.

Recap

In this tutorial we explored the concept of variables. Whilst the game we made is very primitive, it shows how it’s possible to store data within Crayta, and recall that data when necessary. Variables are immensely powerful, and a fundamental building block of coding.

Adding Polish

Try adding the following to cement your understanding of variables:

  • Create a variable called outputString in the Property Bag at the top. Make it of type string. Set the variable to hold “Counter is “ in the Level Editor.
  • Use outputString in the Print() statement that we wrote, so that it outputs the outputString followed by the counter, e.g. Print(self.properties.outputString .. self.counter)

Next steps

The next coding tutorial looks at functions in a bit more depth, and how we can use functions to make a timer.