0% found this document useful (0 votes)
116 views20 pages

Pixel Arcade Tutorial 2025

Uploaded by

266597
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
116 views20 pages

Pixel Arcade Tutorial 2025

Uploaded by

266597
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

Pixel Arcade Tutorial

Names: Person Person Person

Setting Up your Matrix


● There is a connector included in your box. Connect it appropriately.
● Pull the wires apart a little bit and then use the wire strippers to expose about a centimeter of wire.
There are three wires; 5V (red), GND (white), and Data (green).
● Cut off three foot-and-a-half sections of hookup wire in three colors. I used red, black and green.
● Solder these wires to the ends of the wires from the matrix; red to red, white to black, green to green.
● Wrap the exposed wires individually with electrical tape.

Connecting to the Arduino


● Connect the ends of the hookup wires to the arduino.
○ Red to 5V
○ Black to GND
○ Green to Pin 6

Adafruit’s NeoMatrix Library


Here is the link to the library guide.
Here is a link to a reference for the class (functions) definitions.
Here is a link to the reference for matrix functions.

You will need to install three libraries; Adafruit_NeoPixel, Adafruit_NeoMatrix, and Adafruit_GFX. Using the
Arduino IDE, here are the steps to install the libraries.
1. Open the Arduino IDE
2. Goto Tools / Manage Libraries

3. Search “neomatrix” and install the Adafruit NeoMatrix library. It will ask if you want to also install
Adafruit NeoPixel, BusIO and Adafruit GFX. Do it.
Create a Folder for Your Files
Create a new folder on your laptop’s desktop entitled, “Pixel Arcade - YOURNAME”. Also create a folder in
your google drive and give editing permission to your partners. After each class, you will upload your new files
to your google folder so that they are saved and accessible by all partners.

Lighting Up your First Pixel


Download this file to your desktop and move it to your desktop folder. Open it with the Arduino IDE. When you
try to open it, the IDE will tell you that it needs to make a new folder for it. Let it happen.

Take a look at the code. Note first that some lines begin with the double backslash (//). This is the comment
operator. We want to write clean, understandable code and that means commenting.

Program Description
Every program should have a description in the code. At the top of your program, you should leave comments
that describe what your program does.

Including your Libraries


Libraries must be explicitly included using the #include operator. Note that we have included the
Adafruit.NeoPixel, Adafruit.NeoMatrix, and Adafruit.GFX libraries.

Defining Constants
We use the const keyword, a data type keyword, a name and a value to define a constant. A constant is like
a variable but has a value that can not be changed. When we define a variable we have to tell the software
what data type it is. Data types come in many shapes and sizes, but we will be most interested in integers.
Integers get the keyword int. We will also use unsigned 16 bit integers for some variables. These get the type
uint16_t.
In our code, we want to set the data pin that we use to pin 6, so we make it a constant with the following code
sentence.

Take note of the punctuation at the end of this code sentence. We end our code sentences with semicolons!!
Since our matrix is a 16x16 pixel matrix, we can also define a constant for its size.

Naming Constants and Variables


Constants and variables can be named pretty much whatever you want as long as they are one word (or linked
with an underscore). You will want to make your names descriptive, but short (because you’ll be typing them
again later). So PIN is better than ArduinoDataInputPin.
Defining the Matrix
This part of the code is creating our matrix. There will be 256 cells in our matrix. Each cell corresponds to a
pixel. We can pick any pixel by selecting the corresponding cell (0-255) of our matrix. The number (0-255) is
called the index. This is important because we will want particular pixels to light in specific ways for our game.
In each matrix cell information such as brightness and color is stored. You do not need to understand what the
code means for defining this matrix, but do note that we used the constants that we defined above while
creating it.

Setup()
The setup section of the code only runs once. In this case, we start our defined matrix so that it can be
accessed in the program. Mostly, we won’t use this section beyond what is below.

Variables for our Loop


In the section of code between the setup and the main loop, we define and initialize our global variables.
There are variables that will be used throughout the program. Initializing is the process of giving the variables
their first value so that they are not undefined when the program starts. Here we create variables for the
horizontal and vertical position of our pixel. Note that the variables are of the type, integer. I’ve created two
sets of variables so that we can independently draw two pixels.

Neopixel Color
One way to set the color of our pixels is to use the Red, Green, Blue (RGB) color system. In this system we
can set how much of each color that we want (from 0-255) and add them together. We use the
matrix.Color(R,G,B) function to do this. As you can see in the code, we define two color variables, col and
col2 to blue and red, respectively. Note also that we need to use the uint16_t type for color.

Loop()
The loop function is the main part of the program. Whatever is inside of the squiggly brackets { } will run
continuously once the program starts.
matrix.fillScreen(0)
This is going to be a useful function. It can fill the matrix with any color, but the real genius is using it to clear
the screen after every write, so the argument is 0 here.

matrix.drawPixel(x position, y position, color)


You can use this to draw one pixel. Note that the pixel doesn’t show up on the screen until the matrix.show()
function.

We can use independent variables for each of our pixels or we can reference the other pixels variables and
draw at an offset.

matrix.show()
Another necessary function which sends any drawings that you have done to the screen. These will remain
until written over.

delay(time in milliseconds)
The loop goes forever and will repeat right away. If we want our drawings to last for any amount of time, we’ll
have to delay them.

Challenge 01
Save the file with a new name, such as “Challenge_01”.
Modify the program to make a yellow, 3x3 square near the center of the display. Be sure to modify the
comments in the header to reflect your changes. Remember to save your progress frequently.

One possible solution

Flash through a Set of Colors


Download this file, move it to your desktop folder and open it in your IDE. We might want to change the color
of our pixel every time that we go through the loop. We can do this by building an array for our colors.
Neopixel colors are of an unsigned 16 bit type, so we’ll need the uint16_t keyword while defining our array. An
array is very much like the matrix that we are using for our pixels. To define an array we’ll need to use the
square brackets [ ] . Take a look below where an array is defined with three colors; red, white, and blue.
After the matrix is defined, we define our array constant. I’ve called it color_list. Note the brackets in the
definition and the squiggly brackets after the equals sign.

We need a new index variable, that I’ve called col. It can just be an integer type.

When we use the array in the code, we will also use the square brackets when indexing the array. Here we
can see that we use the array for the color argument in the drawPixel function. After we send to the display
and delay, we increment the index to choose the next color. We also have to put a limit on the index. If it goes
past 2, we enter an undefined region of the array. To do this we use an if statement.

if(condition) action
The if statement is a staple of programming. Here it is in its simplest form. The statement says that if the
condition is met, do the action. If not, don’t do it and move on. We use it to ask if the index has surpassed the
length of the array. Since our array has three values, the index goes from 0 to 2 (we start at 0). So if the index
is equal to or greater than 3, we need to start over. The action is to set the index back to 0, the start.

Challenge 02
Add a color to your color list array and make the colors cycle at half the rate.
Optional - add a 2nd pixel at a different location and make it cycle through the same list of colors backwards.
Remember to update your comments.

One possible solution


One possible solution to the optional
Making your Pixel Move
Making your pixels move around the grid is very important for your game. Here we will look at a couple of
ways to do that.

Random Motion
Download this file, move it to your folder and open it in your IDE. One thing that we may want to do is move a
pixel randomly around the display. To do this, we will want to utilize the random function. We will also look at
how to write our own functions that we can call within the main loop to make our programming easier.

random(min, max)
The random function returns a random integer between the values min and max - 1, or min inclusive, max
exclusive. We want to use this to give us a random x or y position, so we will use random(0,16).

Writing Our Own Functions


The drawPixel function takes x and y positions as arguments. We could paste that random function from
above into each spot that we need it. We could be pasting it several times. Instead, we could call a
user-defined function at each of these spots in the code that would then call the random function. The
advantage to this is that if we make a mistake or want to change something, we only have to do it in the
user-defined function and not at every location in the code. Here is our function, rand_pos.

Note that we need to declare the data type that is returned to the code. Since the random function itself
returns an integer, we will retain that type for our function. Note also all of the brackets. We have no
arguments, so the brackets on rand_pos are blank. The function definition is inside curly brackets. Lastly, note
the return keyword. It tells the function what to output. In this case we want to return the result of the random
function.

Now take a look at how we use rand_pos in our main loop.

Instead of a variable or a value for our drawPixel arguments, we use our function. Nice! You may also note
that the main program, loop() is a function that doesn’t return anything, so its return type is void.

Challenge 03
Make two pixels move randomly around the screen. Make them change colors randomly. Remove the delay.

One possible solution


Contiguous Motion
That last one was fun, but what if we want to make the pixel move to only one of the adjacent 8 pixels? Let’s
take a look.

Random Contiguous Motion


Download this file, move it to your folder and open it in your IDE. In this program, we will create four pixels of
different color that will randomly move to one of the adjacent 8 pixels each time through the loop. We will use
arrays and functions as well as a for loop to do this efficiently.

We define a new color list with four colors. We will not be changing these values, so we make it a constant.

We also create two new arrays, one for our x-positions and one for our y-positions. Since we will be changing
these values, we leave off the const keyword to make it a variable.

Note that we are using the random function to initialize each pixel to a random location.

We want to make each pixel move +/- 1 unit in both the x and y directions (or stay put), randomly. To do this
we can add a random number between -1 and +1 to the old positions. Random(-1,2) does this (remember that
the max is exclusive). But what if we are against the wall (position 15)? If we add to that, we would move off
of our display. We will use if statements to prevent it. Take a look at the following function.

This function has an argument, old. We need to declare its type and the type for the function. Both are
integers. The first line uses an if statement to check if we are on the max edge. It is better practice to use >=
rather than == just in case we were at 16 or 17. If we are at the max edge, we bounce back one to 14.

The second line uses else if. An else if statement comes after an if statement and checks a second condition.
If the if statement were true, the else if is bypassed. Here we are checking if we are at the min edge. If we
are, we bounce back to 1. In practice, we can have as many else ifs that we want. We want to make sure that
we are checking the most limiting conditions first.

The third line uses else. Else is the “catch all” for any case that doesn’t fit the previous two conditions. Here
we give the new position freedom to be the same pixel or one of the two adjacent pixels in whichever direction
we’re updating (horizontal or vertical). If we do this for both horizontal and vertical, it gives us the current pixel
and the 8 adjacent pixels as possible new positions.

For Loops
For loops are great at doing things a fixed number of times. For this reason, they work well with arrays, which
can have fixed lengths. If we want to draw a pixel for each of our four (x,y) coordinates, we can use a for loop
to iterate through the index from 0 to 3 and get the coordinates from our two arrays. We can also do this for
our color array. Take a look at the code.

The for loop has the following syntax.


for(iterator start value; iterator stop condition; iterator change) {do this}

We declare a temporary integer iterator variable i that is only used inside the loop. Outside, i has no meaning.
This is called scope. We want to cycle through 4 values, 0 to 3, to access the positions in our array. Every
time we go through the loop, we want to change the value for i by +1. I++ achieves this. It is the same as i = i
+ 1.
Look at the drawPixel function. Each argument accesses the appropriate array with the index being the
variable i. When i = 0 we draw the first pixel with the first x, y, and color from the respective arrays. Then we
increase i to 1 and draw the next one and so on.

To get our new positions, we call our new position function for every x and y value in our arrays. We again can
use for loops to do this efficiently and easily. We take the current position from the array, feed it into our
function and write the new position into our array at the same location. We do this for the length of the array.

Challenge 04
Start each pixel at non-random locations. Make 2 of them only move randomly in the vertical direction and the
other 2 only move randomly in the horizontal direction.

One possible solution

Moving Consistently in a Straight Line


Download this file, move it to your folder and open it in the IDE. We’ve been using random a lot here to make
some fun programs, but we might want to have a pixel move consistently in one direction. How do we do that?
Let’s take a look.

Declaring an Unfilled Array


First let’s look at a new way to make our position arrays. We can declare an array without populating it, but we
have to tell it what length we want it to be.
This code snippet creates two arrays with length n. We must declare n as a constant because arrays must be
declared with known length. Then we put the variable n inside the brackets when declaring the arrays. This
has an advantage because we can quickly change the length of our arrays and also populate them with for
loops. Let’s look at that now.

First off, we must run our for loops inside of the setup function. Otherwise we will get an error. The two for
loops populate the position arrays with random positions. Note that the iterator limit is not n, but n-1. We want
it to go from 0 to 3, not 0 to 4. That would be five entries into our array and we only want four. Just by
changing the constant, n, we can make as many pixels as we want.

Note also the randomSeed() function. Arduino uses a pseudo-random sequence and if you don’t tell it where
to start, it will start at the same spot each time. The randomSeed function reads analog input zero, which
varies because of random noise, and uses that random noise to pick a starting point in the pseudo-random
sequence. Try the program with and without and note the difference.

Setting the Initial Direction


If we want our pixels to move in straight lines, we have to tell them which way to move. To do this, we will use
two more arrays for x-direction and y-direction. We will declare these arrays and populate them
simultaneously. We want to be able to move one pixel in either direction both vertically and horizontally. This
means either adding or subtracting one from the current position. By setting our directions to +/- 1, we achieve
this. Look at the code snippet below.

The first pair of x and y directions is (1,1). This means that we will add one to both the x and y position to draw
the next pixel. This corresponds to moving rightward and downward, so this pixel will move diagonally.
Likewise, the next pixels will move rightward, downward, and diagonally leftward and upward.

Assigning the New Pixel Position


To set the new horizontal and vertical positions we want to add the direction to the current position. We do this
for all pixels in our position array. Note that we also iterate the for loop through the length of the array as
defined by the constant we declared at the beginning of our program. This makes changing the number of
pixels easy.

Handling the Walls


We have to handle the walls a little differently this time. We need to know both where the pixel is and which
way it is moving. You can see in the code above that we set a new direction by calling the user-defined
function, new_dir. You can also see that there are two arguments for this function, current position and current
direction. Let’s look at the function.

We send the function the current position and direction. If the pixel is at a max edge AND is moving forward,
we want to turn it around and begin moving backward. If it is at a min edge AND is moving backward we want
it to turn around and begin moving forward. Otherwise, it should continue in the same direction. Note the
double AND symbol (&&) in the condition statements for the if and else if. The function now returns the correct
new direction and we can add that to the current position.

Challenge 05
Add four more pixels with colors cyan, magenta, and yellow and a color of your choice. Make them have
starting directions of downward-left, upward-right, upward, and leftward.
Optional: Modify the program to handle n pixels with random starting positions, directions and colors.

One possible solution


One possible solution optional (note: I use a do/while loop in the solution)
Wall Wrapping
Download this file, move it to your folder and open it in your IDE. This program creates four pixels and has
them move along diagonal lines. When they hit the wall, they pass through and wrap around to the other side.
Their direction and speed remain the same.

Predefined Color Definitions


To make our lives easier, we can define colors using the #define operator. This operator sets up a constant,
just like const, but it does it with less memory usage.

These are hexadecimal numbers that include the amount of R, G and B for the color we want. These colors
are in RGB565 format. You can find lots of internet resources on RGB565 colors to get the ones you want and
then define them as an easy to use constant.

Using a 2-Dimensional Array


It can be useful to use a 2D array instead of multiple 1D arrays to store your information. Here we are using a
2D array to store the {x position, y position, x direction, y direction, color} for each of our four pixels. The first
index chooses the pixel and the second index chooses the quantity. So velocity[1][3] chooses the second
pixel’s y direction.

Wall Wrapping
We have to do a check on our pixels to see if they have gone beyond the wall. If they have we set their
position on the other side, or wrap them.

This function has a return quantity. The int before checkWall says that we will return an integer, in this case
representing the new position. The int p says that we must feed the function an integer, in this case the
prospective new position. If the prospective new position is too big, we return 0; too small, we return 15; just
right, we don’t do anything and give it right back.

This is where we call the checkWall function. Note that we give it the current position + the direction for both
the x and y directions and feed the return into the correct spot in the array for position.

Snake
Download this file and open it in the IDE. Let’s make a snake. As you may have guessed, using an array is a
good idea for a snake. We create arrays for the snake’s x and y positions. This is a snake of length n, so we
need an array of length n. But these arrays are of length n+1. Why? Because I am going to use the last spot
in the array to help control how the snake can move.

The Main Program


The main program goes like this.
● Clear the screen
● Draw the snake
○ Make the colors cool
● Get the next snake position
○ Check to make sure that the snake doesn’t crash into itself
○ Check to make sure that the snake only moves horizontally or vertically
○ Make the snake wrap around the display if it hits the edge
● Loop

Drawing the Snake with Cool Colors


We draw the snake by using a for loop to create each pixel. This for loop has an iterator, i, that goes from 0 to
n-1, where n is the length of the snake. We can use this to our advantage to make a color gradient in our
snake. Take a look at the following code snippet.

Remember that matrix.Color sets the amount of red, green and blue in the pixel. I declared a multiplier
variable, “bright” that I multiply by the iterator. In this case, bright = 16. So the tail has an rgb value of (100, 0,
0) and is red, the next pixel is (92, 0, 16), then (84, 0, 32) and the head (10th pixel) is (20, 0, 160) which is
pretty blue. The for loop makes the gradient easy and fun!!

Getting the Next Position


Getting the next position was easy until I had to think about how to meet the conditions of not crashing, not
moving diagonally and not stopping.

So I made a function called new_pos that is called in the main loop. Notice that the return type is void because
it doesn’t return anything. It just populates the extra slot in the position arrays. Also, there are no arguments
for the function, so the parentheses are empty. The highlighted code shows that we create a new random x
and y direction and add that to the position of the head (n-1) and store it in the empty slot (n).

Checking for a Crash


To check for a crash, I wrote another function called check_array. This function takes the new x and y
positions stored at location n in the array and returns a boolean (true or false) type value. Basically, if there will
be a crash, it will return true and if not it will return false.

The main part of this function is highlighted. It checks the new position (which comes into the function as x and
y) against every old position (0 through n-1). If both the x and (&&) the y values for the new position match any
of the old positions, we change the variable crash to true. If not, we leave it false. The function then returns
this value to the new position function. Note that this could be useful if we wanted to make a real snake game
where a crash ends the game.

Checking for Diagonal Movement


There are four direction combinations for x and y that would result in diagonal movement; (-1,-1), (-1,1), (1.-1)
and (1,1). Note that there are no zeros. Any non-diagonal movement would have a zero in either x or y
direction. So to check for diagonal movement, we can multiply the x direction by the y direction and check if it
is zero or not. A zero would mean non-diagonal movement and any other outcome would mean diagonal
movement. Here is the code.

The != operator means “not equal to” so this is asking, “Is the product of the x and y directions not equal to 0?”
Or in other words, “Is the movement diagonal?”

Checking for Not Moving


Similar to above, not moving would mean that both the x direction and y direction would equal zero. So we
check that.

Putting It All Together with a Do/While Loop


The Do/While Loop is a valuable tool to continue to do something while a set of conditions is true. Here we
keep getting new next positions for the snake until they don’t violate our conditions of crash, diagonal
movement or not moving.

So, while(these things are true) we discard the old new position and get another random one. To do this, we
use the OR operator (||). We translate the code as:

while(there would be a crash OR there would be diagonal movement OR there would be no movement), keep
getting new possible next positions.

Populating the New Snake Arrays


After we get a good new position for the head of the snake, we populate the new positions for the whole snake.
We want it to follow itself, so each pixel should now be located at the position of the pixel that was one ahead
(including the new head location stored in the extra slot at location n).

Enabling Wrap
The display goes from 0-15 in both the vertical and horizontal directions. To wrap, we just check if a position is
greater than 15 and set it to zero and if a position is less than 0 and set it to 15. Observe.
Challenge 06
Make a second snake that starts at a different position and has different colors.

One possible solution

Button Inputs
We want our audience to be able to interact with our game. One way that we can do this is by using button
inputs. The digital inputs on the arduino work on a 5 volt system. A voltage that is close to 5V is interpreted as
a binary 1 or HIGH. A voltage that is close to 0V is interpreted as a binary 0 or LOW.

The Hardware
First we have to create a button circuit that will be able to generate these two values, 0 and 5V. There are two
configurations for this, Active High and Active Low. An Active High configuration means that when the button
is activated (i.e. pressed) the voltage sent to the arduino is 5V, otherwise it is 0V. Similarly, an Active Low
configuration means that when the button is pressed 0V is sent to the arduino, otherwise 5V. This can be
achieved with the circuits shown below.

Active High Active Low

The Active High configuration is typically easier to work with and that is what I suggest.

Simple Start
Download this file and open in with the IDE. Let’s start by taking one pixel, make it move in a straight line and
make it turn left if one button is pressed and right if a second button is pressed. We will only move vertically
and horizontally. We will use pins 4 and 5 for our right and left buttons respectively and have them in the active
high configuration. We will allow screen wrap.

Initializations
Besides the matrix initializations, we create constants for the pins we are going to use for the left and right
buttons, PIN_L and PIN_R. We also create variables to read our button inputs into, left and right. We create x
and y position variables and set their starting values (randomly near the center). But here is where it gets
interesting.

We know a little bit about how turning works here (probably could have used this in the snake code). Say we
start moving to the right on the display. Pushing the right button makes us move down. Pushing again makes
us move left, then up, then back to right. So there are four states and they have a definite order. Pushing the
left button works the same way but opposite. Look at the highlighted code. Together the dirx and diry arrays
chose directions right(1,0), down(0,1), left(-1,0) and up(0,-1) and if we wrap, we’re back at right. So we create
an index variable, or a pointer, called dir that we can increment or decrement to change direction. In our
initialization, we choose a random direction.

pinMode
We have to tell the microcontroller how we are going to use the pins for our buttons. pinMode is the function
that does this. We set them both to inputs.

Using Functions to Clean Up Code


Here is the main loop.

Note how clean it is. It involves calls to four user-defined functions and reads like pseudocode. It can be
helpful to organize your programs like this. The draw_pixel function is pretty standard. Let’s look at the other
three.
get_buttons()
We use the digitalRead function to read the pins. It returns either a HIGH or a LOW. We read them into our
input variables.

set_direction()
We now have our button variables, left and right. We use their states to set the new direction. An if statement
is good for this. We also test the most limiting case first. Here that means both buttons are pressed. If so, we
do nothing. If we left this out, both buttons would still satisfy the left button being pressed and it would turn.
Next, we check left and right. Turning right means incrementing our dir variable and turning left means
decrementing it according to how we defined our direction arrays. Lastly, we keep ourselves in the bounds of
the direction arrays by wrapping if we get outside. Note that 3 and 0 are valid values, so we wait until 4 and -1
to wrap.

set_position()
The set_position function sets the new position by adding the direction to the old position. We check for wrap
by asking if the new position is out of bounds for our display, -1 or 16.

Challenge 07
Add two more buttons and a second pixel.

One possible solution


Capture the Flag Game
Here we are going to make a game in which there will be a number of moving dots on the screen. The green
dot will represent the player. The blue dot will represent the flag. The red dots will represent the baddies. The
blue and red dots will move randomly (even at diagonals). The green dot will be controlled with a joystick. If
the green dot runs into any red dot, the screen will turn red for 1 second and the game will start over with 1
less baddie (minimum 1). If the green dot runs into the blue dot, the screen will turn blue for 1 second and the
game will start over with one more baddie.

Here are a few colors that you can use with matrix.fillScreen().

Download this code and upload it to the IDE.

Using the Joystick


The joystick uses a potentiometer like a voltage divider to give the position of the joystick. The joystick output
is connected to the wiper and that goes to the Arduino. This is an analog voltage, so we’ll need to use analog
inputs on our Arduino.

● We need to connect 5 V to both the L/R+ and U/D+


terminals.
● We need to connect Ground to only one GND terminal.
● Then either L/R output terminal can be connected to A0
on our Arduino.
● Either U/D output terminal can be connected to A1 on our
Arduino.

Setting Up the Analog Inputs


In our constants section, we declare pin names for A0 and A1. In this case, since we connect L/R to A0, we’ll
call A0 LR_PIN. Similarly, we’ll can A1 UD_PIN. Unlike digital inputs, you do not need to set the pinmode in
setup. So you can skip that step.
We’ll also need variables to read the analog input values into the Arduino. I called these LR an UD. The
arduino takes the 0-5V signal and converts that into a 10 bit number (0 - 1023). So in an ideal world, when the
joystick is left alone, the value that is read by the arduino is around 512. This tends to vary a bit and we’ll take
a look at how to calibrate it. The Offset variable defined above allows us to set the sensitivity of our joystick.
We’ll see how below.

The function get_inputs() handles our joystick. Look at the code below. We use analogRead(pin) to read our
inputs into their appropriate variables. Then we send those into an if/else statement. First note that I used
Serial.print to send the values to the serial monitor to see their resting value. This is the calibration that I spoke
of earlier. Look at the second image. It shows (504 and 515). There was some drift from earlier. In the
program, the center values are 502 and 517.
So the if statement says that if the joystick is reading greater than the center value plus the offset, then it must
be pushed to the right, so set the direction to 1 which when added to the position of the pixel will make it move
to the right. Else if the joystick is reading greater than center minus offset, it must be in the center, so set the
direction to 0. Else, it must be left and set the direction to -1.
For up and down, the direction of -1 corresponds to up, so we have to adjust our code appropriately.
Graphics Library (GFX)
The GFX library has a lot of tools. Here is a tutorial if you are interested.

You might also like