Tutorial 12: Structures

Welcome back! Get your thinking hats on for this tutorial - we'll be looking at a slightly more advanced concept.

This project will be covering structures. What a structure is, how we can use one in our programs, and a couple of examples.

Structures are incredibly useful tools for programming, and they make reading code much easier.

What is a Structure?

A structure is a lot like an array. We use it to store information.

Where an array uses a number to access a piece of information, a structure uses a name.

We might use one to store all the information for a player character in a side-scrolling style game. A player character might have a position on screen, a health value, a speed, an attack and defense value, etc. All of this information could be stored in a structure which would make it very easy and convenient to access.

Let's take a step back, and create a very simple structure which stores some information about a person. Copy the code below into the FUZE4 Nintendo Switch code editor. Of course, feel free to change the information!

  1. person = [
  2.     .name = "Luke",
  3.     .likes = "Chocolate",
  4.     .dislikes = "Vegetables",
  5.     .skills = "Coding"
  6. ]

There we have it. This program simply sets up a structure we can use. We could access any of this information with something like: print( person.name ) or print( person.dislikes ). Simple enough!

Formatting

Let's quickly address the strange way this code is laid out. To somebody new to coding, this may look quite strange.

The important parts are the square brackets and commas. First, we name the strcture. We have called ours person. Then, we open square brackets to begin the structure, and define the properties we would like it to have. Each of these properties must be separated by a comma. Finally, we close the square brackets to finish the structure.

It's very important to realise that this is not the only way to lay out a structure. You might want to do it like this:

  1. person = [.name = "Luke",
  2.           .likes = "Chocolate",
  3.           .dislikes = "Vegetables",
  4.           .skills = "Coding"]

Which would work exactly the same. You could even write it all on one line, like this:

  1. person = [.name = "Luke", .likes = "Chocolate", .dislikes = "Vegetables", .skills = "Coding"]

As mentioned before, the important parts are the square brackets and commas. It's up to you how you want to lay out your code in FUZE4 Nintendo Switch.

Creating an Array of Structures

This is all well and good, but what if you want to store the information for multiple people?

Here we might use an array of structures. This is simply an array, where each element of the array is a structure itself. Take a look below, we've added someone new to the program:

  1. people = [
  2.     [    
  3.         .name = "Luke",
  4.         .likes = "Chocolate",
  5.         .dislikes = "Vegetables",
  6.         .skills = "Coding"
  7.     ],
  8.     [
  9.         .name = "Colin",
 10.         .likes = "Trains",
 11.         .dislikes = "Brussels Sprouts",
 12.         .skills = "Dancing"
 13.     ]
 14. ]

Now we have something a little more complicated. Try not to be put off by the square brackets!

Our first line no longer creates a structure called person. Now it creates an array called people with two elements. Each of these elements is a structure, just like the single structure before.

The first structure is stored in people[0] and the second in people[1].

Let's say we wanted to print Colin's likes. We would do that with print( people[1].likes ). Let's say we wanted to print Luke's name. We could do that with print( people[0].name ).

Using an array of structures gives us a convenient and powerful method of storing information to use in our programs. With a combination of structures, arrays and for loops, you can achieve some incredible things.

Using a Structure in a simple Game

For the main part of this tutorial, we'll use an array of structures to make a simple racing game, where 3 shapes will race across the screen. It's up to us to guess who might win!

We will use three shapes, a triangle, a circle and a pentagon. Each one needs a name, an x and y position, a number of sides (more on this later), a colour and a speed to move across the screen.

Our speed will be a randomly chosen number out of 50. This way, every time we run the program we'll get a different outcome!

Let's build the structure first. This will be quite a lot of code, so it's recommended to copy and paste this into the FUZE4 Nintendo Switch code editor.

  1. shapes = [
  2.     [
  3.         .name  = "Triangle",
  4.         .x     = 0,
  5.         .y     = gheight() / 2 - gheight() / 3,
  6.         .sides = 3,
  7.         .col   = red,
  8.         .speed = random( 50 )
  9.     ],
 10.     [
 11.         .name  = "Circle",
 12.         .x     = 0,
 13.         .y     = gheight() / 2,
 14.         .sides = 32,
 15.         .col   = green,
 16.         .speed = random( 50 )
 17.     ],
 18.     [
 19.         .name  = "Pentagon",
 20.         .x     = 0,
 21.         .y     = gheight() / 2 + gheight() / 3,
 22.         .sides = 5,
 23.         .col   = blue,
 24.         .speed = random( 50 )
 25.     ]
 26. ]

Phew! There we go. Take a good look at this array of structures. We created an array called shapes with 3 elements. Each of these elements is a structure with 6 properties.

Just like before in our people example, we could access any of these with a statement like print( shapes[1].name ), for example.

Let's now add the code which uses this information. We'll need a loop to animate the screen, and a for loop to count over our array of shapes.

 28. loop
 29.     clear()
 30.     for i = 0 to len( shapes ) loop
 31.         circle( shapes[i].x, shapes[i].y, 100, shapes[i].sides, shapes[i].col, false )
 32.     repeat
 33.     update()
 34. repeat

Here's where the usefulness of our array of structures really shines. Lines 30 to 32 create a for loop which repeats 3 times. We create a variable called i which increases from 0 to 1, to 2.

Notice we are using the len() function to give us the length of an array. Our array is 3 elements, so this gives us a 3.

This i variable is used as an index into the shapes array to draw a circle on the screen for each shape, at the x and y positions stored in the structure. Because of the way the circle() function works in FUZE4 Nintendo Switch, we can just change the number of sides and create a different shape! This is why we store the number of sides as a property of the structure.

Once the for loop is complete, we update() the screen, and repeat the loop.

Now let's move them across the screen!

By adding one more line of code into the for loop, we can move each shape:

 28. loop
 29.     clear()
 30.     for i = 0 to len( shapes ) loop
 31.         shapes[i].x += shapes[i].speed
 32.         circle( shapes[i].x, shapes[i].y, 100, shapes[i].sides, shapes[i].col, false )
 33.     repeat
 34.     update()
 35. repeat

Line 31 now increases the x position of each shape by that shape's speed. Run the program to see all the shapes move at different speeds!

All that's left is to create a victory screen when a shape wins the race!

This is the perfect time to create our own function! We can pass the name and colour of the winning shape to our function and use that information in a victory screen. Enter the code below at the bottom of the program, after the repeat on line 35.

 37. function victoryScreen( name, col )
 38.     text = name + " Wins!"
 39.     tsize = 100
 40.     textSize( tSize )
 41.     loop
 42.         clear()
 43.         drawText( gwidth() / 2 - textWidth( text ) / 2, gheight() / 2, tSize, col, text )
 44.         update()
 45.     repeat
 46. return void

Here we have our user-defined function. This is a section of code which will run when we call the function.

The purpose of this function is to print the name of the winning shape in the correct colour on the screen. For that, we need two pieces of information. The name and colour of the winning shape!

In the first line, we name the function as victoryScreen() and give it two arguments. The first argument is stored in a variable called name and the second is stored in a variable called col. We can now use these variables in our function.

First we define a new variable called text. This will store the entire line of text we want to print. We take the name variable from our function's arguments and add it to the text "Wins!". This text variable will be very useful when making our text appear in the right place on screen.

Next up we define a variable to store the size of the text. Doing this allows us to get the position of the text on screen perfect.

On line 40 we use the textSize() function to set the size of the text with our tSize variable.

Now on to the main part of our victory screen, the loop. We need a loop because we want our screen to display the text until the program is stopped. Of course, we'll need a clear() and an update() because we want to display something on screen.

The main instruction in our loop is the drawText() function which we use to display text on screen with more details than a simple print(). We can position the text by pixels, set a size for the text and even a colour.

As you can see, the x position of the drawText() function looks a little strange:

 43.        drawText( gwidth() / 2 - textWidth( text ) / 2 

We want the text to be exactly in the centre of the screen, no matter how long the text is. If we positioned our text at a fixed set of coordinates, we would get very different results if the console was in TV or handheld mode. We would also get different results depending on which shape won, because we get a longer or shorter victory message depending on the winning shape.

Due to these reasons, we must use adjust the position based on the length of our text. This is where our text variable comes in!

We use the textWidth() function to give us the width of a piece of text in pixels. We can then divide this number by two to give us half the length. If we subtract this from the middle of the screen (gwidth() / 2) we will always have our text perfectly in the middle of the screen!

It seems like a lot of trouble, but this is a very useful technique for positioning text! Be sure to remember it for your other projects!

Alright. That's our user-defined function completed. We end the function with return void because we do not need to return anything here.

All that's left is to actually call the function in the main loop!

Adjust the main loop to look like the one below. We're just adding a simple if statement to check if a shape has reached the finish line.

 28. loop
 29.     clear()
 30.     for i = 0 to len( shapes ) loop
 31.         shapes[i].x += shapes[i].speed
 32.         if shapes[i].x > gwidth() then
 33.             victoryScreen( shapes[i].name, shapes[i].col )
 34.         endif
 35.         circle( shapes[i].x, shapes[i].y, 100, shapes[i].sides, shapes[i].col, false )
 36.     repeat
 37.     update()
 38. repeat

Lines 32 to 34 contain our if statement. We simply check if the current shape in the for loop has reached the edge of the screen. If it has, we call the victoryScreen() function and pass it the current shape's name and colour as arguments.

That's it! Have fun with this one! Perhaps you could add a couple more shapes to the race? Because of how our main game is written, to achieve this you would only need to add more shapes to the array!

Recap

A structure is a tool for storing data. It is very similar to an array, except each element has a name rather than a number. You can freely mix and match these techniques for the task at hand. You can store arrays within structures, and store structures within arrays!

Try setting up your own and accessing the values to really get your head around how they work!

As always, well done for making it this far and see you in the next tutorial!

Functions and Keywords used in this tutorial

else, endIf, circle(), clear(), drawText(), for, if, loop, repeat, textSize(), then, update()