variables


The word "variable" means "able to vary" or "changable". In programming, a variable is a name given to data that can change while your game is running. It's like a container that holds information, and the name of the container is used to refer to the data inside it.

For example, let's say you want to keep track of the score in a game. You could create a variable called "score" and set it with an initial value of 0. Use a single equal sign (=) to set values to variable names. 

score = 0

You can read this as, "Create a variable named 'score' and set it's value to zero."

Then, as the player earns points, you could update the value of the "score" variable to reflect the new total.

score = score + 1

This code can be read from left to right as, "Take the variable named score and set it to the new value of the current score value plus one."


Variable Scopes

"Scope" is the range of something.

Here, "variable scope" refers to the range within a program where a variable can be accessed. In other words, it defines where a variable is visible and can be used in your code.

In Lua, there are two types of variable scopes: global and local.

Global Scope: 

A global variable is visible throughout the entire program, including inside any functions. It can be accessed from any part of the code. Global variables are declared outside of any function by simply assigning a value to a variable name without using the "local" keyword. However, using global variables can lead to naming conflicts and make your code harder to read and keep track of.

health = 10

function attack()
	health = health - 2
end

In this code, we create a global variable named "health" and set it to 10. Then inside of the function named "attack" we decrease health by 2. The attack() function can change the health variable because health has a global scope.

Local Scope: 

A local variable is visible only within a limited area of the program, such as inside a function, loop, or a block of code. It can be accessed only within that area and is not visible to the rest of the code outside of that area. Local variables are declared using the "local" keyword followed by the variable name.

For example, to declare a variable called "x", you would write "local x". You can also assign a value to the variable at the same time by writing "local x = 5" (which assigns the value 5 to the variable named "x").

local x = 5

"X" and "Y" are commonly used variable names for keeping track of a position on the screen, so it is a good idea to make them local variables, so they don't get confused. Here is an example:

function move_player()
	local x = x + 1     
end

function move_enemy()
	local x = x - 1     --different from move_player
end

print(x) --cannot find x

In this example, we have two functions for moving the player and the enemy. Both functions use a variable named X but they are not confused because they are two different local variables and they are only accessed inside of their functions. If we try to print X outside of the functions, it will not work because it is outside of the scope.


Types of Variables

Variables can hold different types of data.

Numbers:

Lua supports both integer and decimal (also referred to as "floating-point" or "float") numbers, which can be positive or negative. Numbers can be stored in variables like this:

defense = 10  --positive
speed = 1.5   --float
money = -30   --negative
Strings:

A string is a sequence of characters, such as "hello world" or "you win!". Strings can be stored in variables like this:

text = "hello world"
Booleans:

Booleans are values that can be either true or false. They can be used to represent "conditions" or "states" in your code, such as if something is on or off, flipped or not flipped, alive or dead, etc.

player_is_alive = true
Tables:

Tables are a fundamental data structure in Lua, used to store collections of values. If you want to group a set of variables together for better organization and easier access, you can use a table like this:

player_table = {
	x = 10,
	y = 20,
	health = 50
}
Functions:

In Lua, functions are "first-class values" which means they can be stored in variables and passed around as arguments to other functions.

print("hello world")  --run print function
write = print         --copy print() to variable write
write("hello world")  --run write function

We can treat function names as variables that hold the function's code as its data. Just pay attention to the use of parentheses. We print "hello world" to the screen by calling the print function and using parentheses. Then we create a new variable named "write" and set its value to whatever print's value is. This copies print's code to write. Write is still a variable but not that it is holding code that can be run, it is also a function. So we can call write now just like we did with print, using parentheses and tell it what to write to the screen.

Nil:

Nil is a special value in Lua that represents the absence of a value. 

potion = nil

Variables can be set to nil to erase their data and indicate that they have no value. Errors will often say that a variable is "nil" which usually means the variable has not been created, or it is out of scope.

663

21 Aug 2023


A string is a sequence of characters that is used to represent text in programming. It can be a symbol, a word, or a whole sentence. For example, you could create a string variable called "name" and assign it a value of "lua" to represent the name of the programming language.

name = "lua"

Strings can contain any combination of letters, numbers, and symbols, and can be manipulated using various string functions to perform tasks such as searching, replacing, and formatting text. The important thing is that they are surrounded by quotes (either single or double) to separate them from other types of data in your code.

abc    --not a string
"abc"  --a string
print(abc)   --fail
print("abc") --success

We can print a string directly:

print("game over")

Or we can store a string in a variable and then print the variable, which will print the string.

text = "game over"
print(text)

Combining Strings

The term we use when we talk about combining strings or variables is "concatenation" or "concat" for short. Let's say you have two strings saved as variables, "player_name" and "level_name":

player_name = "samantha"
level_name = "haunted mansion"

And you want to display a message that greets the player by name and tells them which level they are playing. Here's how you can concatenate the string variables into one long string using double dots (..) like this:

message = player_name.." is playing "..level_Name

print(message)

Prints: "samantha is playing haunted mansion"

You can also concatenate strings with number variables like this:

highscore = 123
message = player_name.." = "..highscore

print(message)

Prints: "samantha = 123"


Overall, strings are an important data type that you will want to use for any text you want to display on the screen.

559

9 Mar 2023


A boolean (often shortened to "bool") is a type of variable that can have one of two values: true or false.

bool = true

It is like a light switch that has only two states: on or off. The term "boolean" is named after George Boole, a 19th-century English mathematician and logician. 

Boolean variables are used in programming to represent logical states or conditions. For example, you might use a boolean variable to check if a certain condition is true or false, and then make a decision based on that condition.

coins = 0
win = false          --set boolean

if coins > 10 then
	win = true         --change boolean
end

if win==true then    --check boolean
	print("you win!")
end


Easy Toggle Switch!

bool = not bool

This is an easy way to flip a boolean variable to true if it is false and back to false if it is true. It uses the not operator to mean the opposite value. This is useful for any kind of toggling that you want to do whether controlled by a player's button press or by a trigger in the game.

Example:

toggle = false

--longform
if btnp(4) then
	if toggle==true then
		toggle=false
	else
		toggle=true
	end
end

--shorthand
if (btnp(4)) toggle = not toggle

The above "shorthand" example of toggling a boolean uses the shorthand if statement and the not operator. This does save on both characters and tokens.

To explain the shorthand single line of code, it first checks if the player presses button #4, and every time they do, then it sets the variable named "toggle" to the opposite value of what it already is. So if toggle is true then it will be set to not true (false), and if it is already false, then it will set to not false (true).


455

19 May 2023


A number is a type of variable that holds a numerical value.

That's a very specific way of saying a number is a number, but it is important to understand that in code, a number can be stored in different ways, and that there is a difference betweeen 5 and "5". Numbers can be integers, floats, negative, or positive:

a = 10      --number value as integer
b = 10.567  --number value as float
c = -10     --number value as negative
d = "10"    --string value, not a number

Even though the string d in the example holds the digits "1" and "0", it is not actually a number when we are talking about variable types.


Converting between Numbers and Strings

PICO-8 is able to assume when it should automatically convert strings to numbers or numbers to strings:

string = "10"
num = 5

print( string + num )   --converted twice

In the above example, we are trying to add a string with a number. Usually, this would give an error: Attempt to perform arithmetic on a string value. But if it can, PICO-8 will convert the string to a number first so that it can properly add the two number type variables 10+5. But it's not finished yet. The print() function requires strings not numbers, so PICO-8 will also convert the sum back into a string so that it can be printed to the screen. 

However, this doesn't always work as you might expect, so be careful not to rely on this automatic conversion too much.

For example, it is common to want to print a line of text that has both numbers and strings. To do this, you must use the ..operator to concatenate the different types of variables into a string. For example:

string = "score= "
num = 50

print( string num )  --error

print( string..num ) --prints: score= 50



422

26 May 2023


tostr( a )
tostr "to string"
a any type of value

This function will return a string value of the data that is provided as a. This does not convert tables or functions the way you might hope, instead it simply overwrites the table with the string "[table]" and the function with the string "[function]".


For example:

a = 10              --number
b = "xyz"           --string
c = true            --boolean
d = { "table" }     --table
e = function() end  --function

? tostr( a )  --prints: 10
? tostr( b )  --prints: xyz
? tostr( c )  --prints: true
? tostr( d )  --prints: [table]
? tostr( e )  --prints: [function]

( The ? is the shorthand for the print() function. )


The table and function variables D and E, do convert to strings with those values that it prints. If you are trying to convert a table to a string, then you will need to write a custom function to do that.


Automatic Conversion

PICO-8 will sometimes try to automatically convert between numbers, strings, and booleans. For example, if you add two strings together, it will first attempt to convert those strings to numbers before adding them. Also, if you try to print numbers or booleans, it will attempt to convert those variables into strings to be printed.  So using tostr() is sometimes unnecessary. For example, we don't have to use tostr() to simply print a single number or boolean:

a = "test"
b = 2
c = true

? a --prints: test
? b --prints: 2
? c --prints: true

However, when you try to concatenate a string, this automatic conversion works for numbers but does not work for booleans. For example:

--merge multiple variables into one string

? a..b           --prints: "test2"
? a..b..c        --error with c!
? a..b..tostr(c) --prints: "test2true" 


426

26 May 2023


tonum( a )
tostr "to number"
a any type of value

This function will return a string value of the data that is provided as a. This does not convert tables or functions.


For example:

--types of variables
a = 10              --number
b = "xyz"           --string
c = true            --boolean
d = { "table" }     --table
e = function() end  --function

--convert to number
a = tonum(a)
b = tonum(b)
c = tonum(c)
d = tonum(d)
e = tonum(e)

--print the type of variable
? type(a)  --num 
? type(b)  --nil
? type(c)  --num
? type(d)  --nil
? type(e)  --nil

( The ? is the shorthand for the print() function. )


The string, table, and function variable types all fail to convert to numbers but does not throw an error, instead the value was converted to nil (nothing, empty). So be careful when trying to convert the wrong variable types, because this will error later in your code saying that the variable you think is a string, table, or function, is now nil.


Strings to Numbers

In the above example, we used a string "xyz", however it is possible to convert number-strings to actual numbers. For example:

a = "xyz"  --letter-string
b = "5"    --number-string

a = tonum(a)  --fail
b = tonum(b)  --success

? type(a)  --prints: nil
? type(b)  --prints: num


Automatic Conversion

PICO-8 will sometimes try to automatically convert between numbers, strings, and booleans. For example, if you add two strings together, it will first attempt to convert those strings to numbers before adding them.  So using tonum() is sometimes unnecessary. For example, we don't have to use tonum() to calculate number-strings:

a = 10   --number
b = "5"  --number-string

? a+b    --prints: 15

However, when you try to concatenate a string, this automatic conversion works for numbers but does not work for booleans. For example:

--merge multiple variables into one string

? a..b           --prints: "test2"
? a..b..c        --error with c!
? a..b..tostr(c) --prints: "test2true" 


379

26 May 2023


chr( a, [ b, c, ... ] )

chr "character"
a an ordinal character code
[b,c,...] (optional) you can provide as many ordinal values as you'd like, and the function will return them in a single string in the same order they were given.

This function will return a string with the single character that is associated with the ordinal number a; or it will return a string with multiple characters if multiple values were given as arguments.


What is an ordinal character code?

An ordinal character code, often referred to as an "ordinal number", is a way to represent the position or order of something in a list or sequence. It's a numerical value that tells you where a particular item stands in relation to others. In this case, the list is of characters (such as letters, numbers, punctuation marks, and some control characters like newline and tab).

You may have heard of something called "ASCII" (American Standard Code for Information Interchange). It is a character encoding standard that uses a sequence of numbers to represent characters in computers. In ASCII, each character is assigned a unique numeric value or "character code". For example, the ASCII code for the uppercase letter 'A' is 65, while the code for the lowercase letter 'a' is 97.

PICO-8 has its own sequence of characters in its own order. We call these "P8SCII" (PICO-8 Standard Code for Information Interchange) for fun. See list of all P8SCII numbers and characters.


For example:

a = 135 --heart

print( chr(a) )

a = 135 --heart
b = 143 --pico-8 diamond

print( chr(a,b) )

You may want to encode a string as ordinal numbers and then decode later. For example:

string = "pico"
a,b,c,d = ord(string,1,#string)

print("chr | ord",12)
print("p  =  "..a,7)
print("i  =  "..b)
print("c  =  "..c)
print("o  =  "..d)

print( chr(a,b,c,d),11 )


417

10 Sep 2023


ord( string, [index], [num_results] )

ord "ordinal" get ordinal character code
string one or more characters that you want to convert
index (optional) the number of characters from the start of the string to start converting.
num_results (optional) a number of total characters in the string to convert.

This function will return a string with the single character that is associated with the ordinal number a; or it will return a string with multiple characters if multiple values were given as arguments.


What is an ordinal character code?

An ordinal character code, often referred to as an "ordinal number", is a way to represent the position or order of something in a list or sequence. It's a numerical value that tells you where a particular item stands in relation to others. In this case, the list is of characters (such as letters, numbers, punctuation marks, and some control characters like newline and tab).

You may have heard of something called "ASCII" (American Standard Code for Information Interchange). It is a character encoding standard that uses a sequence of numbers to represent characters in computers. In ASCII, each character is assigned a unique numeric value or "character code". For example, the ASCII code for the uppercase letter 'A' is 65, while the code for the lowercase letter 'a' is 97.

PICO-8 has its own sequence of characters in its own order. We call these "P8SCII" (PICO-8 Standard Code for Information Interchange) for fun. See list of all P8SCII numbers and characters.



For example:

a = "?"

print( ord(a) )

string = "pico"
a,b,c,d = ord( string, 1, 4 )

print(a)
print(b)
print(c)
print(d)

You may want to encode a string as ordinal numbers and then decode later. For example:

string = "pico"
a,b,c,d = ord(string,1,#string)

print("chr | ord",12)
print("p  =  "..a,7)
print("i  =  "..b)
print("c  =  "..c)
print("o  =  "..d)

print( chr(a,b,c,d),11 )



445

10 Sep 2023


sub( string, first, [last] )
string the string that you want to convert into a table
first the number of characters from the beginning of the string to start pulling as the substring.

*If not given, the full string is returned.
last (optional) the number of characters from the beginning of the string to stop pulling as the substring. (default: full length of string) 

The sub( string ) function is used to separate a part of a string into a smaller string. The first character of the string is 1. 



For example, if we call sub("hello world"), the function will return a character or string from within the full given string.

string = "hello world"
print( sub( string,1 ) )   -- "hello world"
print( sub( string,2 ) )   -- "ello world"
print( sub( string,4,8 ) ) -- "lo wo"
print( sub( string,7,7 ) ) -- "w"

It is also possible to use negative numbers as the first and last arguments. This will count backwards from the end of the string. The last character in the string is -1. However, the substring will only return letters after first, so if you try to get characters from -3 to -6, you must order it from left to right (-6, -3).

string = "hello world"
print( sub( string,-1 ) )      -- "d"
print( sub( string,-3,-6 ) )   -- "" (empty string)
print( sub( string,-5,-1 ) )   -- "world"

Shorthand

If you only want a single character from the string, you can simply use  string[position] where string is the variable name of your string and position is the number of the character's index in the string:

string = "abcdefghij"
position = 4

print( string[position] )  -- "d"


Common Uses


The most common usage of the function sub() is to create a text appearance animation as if it is being typed out one character at a time. Example:

string = "hello world"
first = 1
last = 1


function _draw()
	cls()
	last+=.5	
	print( sub(string,first,last) )
end


Another way to reveal text is to use the clip() function. See the tutorial Text Wipe for a detailed example.

455

24 May 2024


split( string, [separator], [convert numbers] )
string the string that you want to convert into a table
separator (optional) the symbol to split the string by (default: comma ",")
convert numbers (optional) a boolean. True will convert numbers in the string to an actual number type of variable. False will leave any numbers in the strings as strings. (default: true)

The split( string ) function is used to separate a string into a table of elements, separated by commas or the given separator character. It will attempt to convert any digits in the string into number variables unless the third argument is given as false.



For example, if we call split("a,b,c,d"), the function will return a table that has four entries with the values of each letter between the commas.

table = split("a,b,c,d")
print( table[1] ) --"a"
print( table[2] ) --"b"
print( table[3] ) --"c"
print( table[4] ) --"d"

To use a different separator and maintain the commas in your table entries, you can include the separator argument. For example, a common alternative is to use the pipe character "|" found above enter on QWERTY keyboards.

table = split("a,b,c,d|e,f,g,h", "|")
print( table[1] ) --"a,b,c,d"
print( table[2] ) --"e,f,g,h"

To leave individual number entries as strings instead of being converted, use the third argument. For example:

table = split("1,2,3,4") --default true
print( table[1] ) --1
print( table[2] ) --2
print( table[3] ) --3
print( table[4] ) --4

table = split("1,2,3,4", ",", false)
print( table[1] ) --"1"
print( table[2] ) --"2"
print( table[3] ) --"3"
print( table[4] ) --"4"


Common Uses

The most common usage of the function split() is to save tokens. Strings, no matter their length, cost only 1 token. But creating tables and their entries, can cost many tokens. Example:

colors = {8,9,10,11,12,13,14}
--10 tokens

colors = split("8,9,10,11,12,13,14")
--5 tokens

Advanced

Another way to save many tokens is to use split() with another function unpack() to set multiple variables from a single string. Example:

--single assignments
sprite=1
x=10
y=20
w=1
h=1
speed=2
jump=6
atk=10
def=5
--27 tokens

--multiple assignments
sprite,x,y,w,h,speed,jump,atk,def=
1,10,20,1,1,2,6,10,5
--19 tokens

--split and unpack
sprite,x,y,w,h,speed,jump,atk,def=
unpack(split("1,10,20,1,1,2,6,10,5
")
--16 tokens

480

19 Aug 2023


type( a )
type "variable type"
a any type of value

This function will return a string with the name of the type of variable that is provided as a.


For example:

--types of variables
str = "hello world"
num = 1
bool = true
tbl = {}
function funct() end

? type( str )    --prints: string
? type( num )    --prints: number
? type( bool )   --prints: boolean
? type( tbl )    --prints: table
? type( funct )  --prints: function

( The ? is the shorthand for the print() function. )


You may want to ensure that a variable being passed to a function is the correct type, and if it is not, then you would want to convert it to the correct type. For example:

function double_it( a )
	if type(a) ~= "number" then
		a = tonum(a)
	end
	
	return a + a
end

( The ~= is the not equal operator. )



408

14 May 2023


unpack( table, [first], [last] )
table a numbered table of elements (list)
first (optional) the first number of the table to return
last (optional) the last number of the table to return

The unpack( table ) function is used to separate a table and return its values. The table passed as an argument must be a list, a table with numbered keys. Any non-numeric keys in the table will not be returned. 

Use multiple assignment to receive the multiple returns from this function:

a, b, c = 1, 2, 3
a, b, c = unpack( table )



For example, if we call unpack( table ), the function will return each value from within the list. In order to catch each value, we must provide multiple variables separated by commas.

table = {
	"apple",
	"banana",
	"cherry",
}

a,b,c = unpack( table )

print(a) --apple
print(b) --banana
print(c) --cherry


When passing the optional arguments, if we call unpack( table,i,j ), the function will return each value starting with table[i] and end with table[j] . In order to catch each value, we must provide multiple variables separated by commas.

table = {
	"apple",
	"banana",
	"cherry",
	"durian",
	"eggplant",
	"fig",
}

a,b,c,d,e,f = unpack( table,2,5 )

This may not return what you expect. Since we have named the entries in the table in alphabetical order, and the variables to receive the returned values are also alphabetical, it would make sense that a is always apple. However, remember that the first value returned is specified to be entry 2, which is banana.

So this is what is actually returned:

print(a) --banana
print(b) --cherry
print(c) --durian
print(d) --eggplant
print(e) --nil
print(f) --nil

Notice that the value of A is now "banana", because that was specified to be the first entry to be returned. Only 4 elements were returned in total because we also specified to stop after returning the 5th element of the table. And the variables E and F are nil because nothing returned after "eggplant" to be assigned to those variables.



Common Uses

The most common usage of the function unpack() is to save tokens when declaring variables. It is most commonly used with the  split() function to assign multiple variables from a single string. To save the most tokens, we can use split a string into a table, and then immediately unpack that table into separate variables. So you might see both functions nested like this: unpack( split() )

Example:

--single assignments
sprite=1
x=10
y=20
w=1
h=1
speed=2
jump=6
atk=10
def=5
--27 tokens

--split and unpack
sprite,x,y,w,h,speed,jump,atk,def=
unpack(split("1,10,20,1,1,2,6,10,5"))
--16 tokens

357

23 Nov 2023


Font