In the previous section, I didn't mention any of the lines of code at the top of the sketch. Most of these are just normal global variables and constants that are fairly common. However, this section of code may be new to you.
struct button { uint8_t capPad[2]; uint8_t pixel[3]; uint32_t color; uint16_t freq; } simonButton[] = { { {3,2}, {0,1,2}, 0x00FF00, 415 }, // GREEN { {0,1}, {2,3,4}, 0xFFFF00, 252 }, // YELLOW { {12, 6}, {5,6,7}, 0x0000FF, 209 }, // BLUE { {9, 10}, {7,8,9}, 0xFF0000, 310 }, // RED };
This is defining, and initializing, an array (simonButton[]
) of something called a struct. A struct comes from the C programming language, but is also supported in C++ and thus Arduino. What it basically does is let us create a new variable that is a collection of information associated with something, like a Simon "button". This let's us pass around and access this information from a single reference. We don't need to pass around each individual piece of information separately.
Talking about structs can get pretty complex, and they're a precursor to the more complex class
of C++ and the world of OOP. But they are very useful, and we are using it in a fairly simple way in our Simple Simon code. To better understand why a struct is useful, let's look at a more simple example - a 2D point.
2D Point Example
A 2D point is represented by an x
and y
value. We could create these as separate variables:
float x; float y;
and then use them as normal:
x = 45.3; y = -108.6;
But what if I wanted to pass this 2D point to a function? Or what if I wanted to create another 2D point? Things start getting a little messy. This is where a struct would help out. Instead of two separate variable, we create a single struct to represent the 2D point, and put the variables in there.
struct point { float x; float y; }
And then to create a new point variable:
struct point someLocation;
And assign it values:
someLocation.x = 45.3; someLocation.y = -108.6;
Now all one needs to do is pass the variable someLocation
around. The values come along for the ride. And they don't get confused with some other values. If we need another 2D point, we just create another variable, or better yet, an array of them.
The one fancy thing being done in the Simple Simon code is to create and initialize the values of the struct in one step. For our 2D point example, this would look like:
struct point { float x; float y; } someLocation = { 45.3, -108.6 }
It's just a shortcut way of creating the variable and assigning it some initial values.
The Simple Simon "button"
Getting back to our Simple Simon game, think about what each of the four "buttons" has. Most obvious is a color. But they also make a sound when they are pressed, and each has its own tone. Since we are trying to implement these on our Circuit Playground, we will use a set of NeoPixels to show off the color. Also, we plan to use capacitive touch for the buttons, with each button having a couple of pads. So, we have the following items for each "button":
- 2 x capacitive touch pads
- 3 x NeoPixels
- a color
- a tone
Hey, that should look familiar. Look again at the struct definition:
struct button { uint8_t capPad[2]; uint8_t pixel[3]; uint32_t color; uint16_t freq; }
Just like the list. For each "button" we have the indices for 2 capacitive touch pads, the indices for 3 NeoPixels, the color to use for the NeoPixels, and the frequency of the tone for the button.
We have more than one "button", so we create an array of them and initialize their values:
simonButton[] = { { {3,2}, {0,1,2}, 0x00FF00, 415 }, // GREEN { {0,1}, {2,3,4}, 0xFFFF00, 252 }, // YELLOW { {12, 6}, {5,6,7}, 0x0000FF, 209 }, // BLUE { {9, 10}, {7,8,9}, 0xFF0000, 310 }, // RED };
Each line is an entry in the array and represents one button. Each item in each line corresponds to the value of the struct and is used to define the specific buttons. For example, the first line defines the GREEN button as having the capacitive touch pads #3 and #2, the NeoPixels #0, #1, and #2, the color green (in hex), and the frequency 415Hz.
Then, if we need the frequency for the tone of the GREEN button, the syntax is:
simonButton[0].freq
The color for the BLUE button?
simonButton[2].color
The index of the 2nd NeoPixel for the RED button?
simonButton[3].pixel[1]
etc. etc.
Hopefully that makes some sense and you see how it is useful. If not, meh, just have fun playing the game....for now.
Page last edited March 08, 2024
Text editor powered by tinymce.