Year 9 Digital Factory · Robotics & Animation

Challenge: Animation

Your entire screen is twenty-five lights. Learn to animate a falling meteor on the SPIKE Prime hub, discover why real screens look smooth when this one cannot, then build an arcade game out of single pixels.

5 × 5Pixel display
25Pixels total
0–100Brightness levels

Hub display · live

1

Where you will code

Everything in this unit is written in the SPIKE Prime website, not the tablet app. You code in the browser, connect your hub over Bluetooth, and your work stays in one place.

Open the web coding environment

Use Chrome, open the lobby below, and start a new project. Turn your hub on, then use the Connect button in the coding window to pair it over Bluetooth. Save your project so you can come back to it next lesson.

Open SPIKE Prime web app ↗

Not the app this time

Previous robotics tasks used the tablet app. This unit is browser-based from start to finish, so do not begin in the app and try to move your work across. If your hub will not appear when you press Connect, check that it is switched on, that you are in Chrome, and that nobody else in the room has already connected to it.

2

Your canvas: twenty-five pixels

A phone screen has millions of pixels. Your hub has twenty-five. That constraint is the whole point of this unit: with so few pixels, every single one has to earn its place, and you have to be clever about how you suggest movement and shape.

The SPIKE Prime hub with its five by five matrix of lit pixels. The four corners are labelled 1 1 at top left, 5 1 at top right, 1 5 at bottom left and 5 5 at bottom right
Every pixel has an address written as (x, y): x counts across from 1 on the left to 5 on the right, and y counts down from 1 at the top to 5 at the bottom. The top-left corner is (1, 1) and the bottom-right is (5, 5). Note that the bottom-left corner is (1, 5), not (5, 1): moving down the display changes the second number, not the first. These are already in the order the block wants, so you can read a position off this diagram and type it straight in.
The SPIKE Prime block that sets a single pixel at a given x and y position to a chosen brightness percentage
The one block that does all the work in this unit. It takes an x position, a y position, and a brightness from 0 to 100 per cent.

Find the coordinates

Click any pixel to switch it on and read the block you would write to light it. Coordinates run 1–5 across and 1–5 down, with (1, 1) in the top-left corner.

Click a pixel to see its block.

Watch what happens to y as you move down the display. Row numbers grow downwards, which is why a falling object counts up from 1 to 5.

3

Animating a falling meteor

Animation is just the right pixels switched on and off fast enough to read as movement. You will build the same meteor three times, and each version replaces effort with cleverness. Copy and test each step before moving to the next one.

The long way: one pixel at a time

Light the pixel at the top of column 3, wait, switch it off, light the one below it, wait, switch it off, and so on down the display. It works, and it is completely rigid: every frame is typed out by hand.

Notice the speed variable at the top. Because every wait block reads that one variable, changing a single number re-times the whole animation.

Step 1 block code: a speed variable, then a forever loop that sets each pixel in column 3 to full brightness, waits, and clears it
Step 1. Repetitive, but easy to follow.

Count the blocks. Adding one more row would mean four more blocks. This is the moment a loop starts to look attractive.

The smart way: a variable and a loop

Replace the hand-written rows with a row variable inside a repeat 5 loop. Each pass lights the pixel at (3, row), waits, clears it, then adds 1 to row. When the loop finishes, row resets to 1 and the meteor falls again.

This is the same animation in a fraction of the blocks, and now the length of the fall is a number you can change rather than a wall of code you have to rewrite.

Step 2 block code: a row variable inside a repeat 5 loop that lights, waits, clears, then increments the row
Step 2. Same result, far less code, and much easier to change.

This is the core trade in programming: spot the repetition, name what changes, and let a loop do the typing.

Add a trail and user input

A single moving dot looks like it is jumping. Light the pixel behind the meteor at a lower brightness, say 50 per cent, and suddenly the eye reads a tail and the motion smooths out. That dimmer pixel is doing exactly the job anti-aliasing does on a real screen, which is Section 4.

Add the additional code on the right side of the image shown below to change speed while the program runs, so the meteor can be sped up or slowed down by turning one of the connected motors, without stopping and re-flashing the hub.

Step 3 block code: the loop now also sets the pixel behind the meteor to 50 per cent brightness, plus a separate stack on the right that continuously sets the speed variable from a motor's position
Step 3. The trail pixel at partial brightness, plus the extra stack on the right that reads a motor's position into speed. This is the version you upload for the Developing standard.

Remember to clear the trail pixel as well as the head. Forget it and your meteor leaves a permanent smear down the display.

Meteor lab

The same animation, running here. Change the speed, switch the trail off and on, and see what your code will look like before you write it.

Column 3 · falling

Class activity

Copy and test the Step 3 code on your own hub, including the trail pixels. Once it runs, modify it so that the animation restarts from the top the instant the speed is adjusted with the motor, rather than finishing the current fall first.

Your solution must use at least one variable and at least one conditional statement. Think about what you would need to store in order to notice that the speed has changed, and what test would tell you it is different from last time.

Photograph of the SPIKE Prime hub running the meteor animation, with one bright pixel and a dimmer pixel above it
What you are aiming for: one bright head, one dim trail, falling smoothly.
4

Resolution and anti-aliasing

That dim trail pixel was not just a nice effect. It is the same trick every screen you own uses to hide the fact that images are built from squares, and it has a name: anti-aliasing.

Resolution is simply how many pixels an image is made from, written as width × height. Your hub is 5 × 5, or 25 pixels. A 1080p video frame is 1920 × 1080, which is 2,073,600 pixels. More pixels means smaller pixels, and smaller pixels mean a curve or a diagonal can be described more accurately.

The problem is that pixels are squares and most interesting shapes are not. Draw a diagonal edge on a grid and you get a staircase, an effect called aliasing or, less politely, "the jaggies".

Resolution lab

The same circle drawn at different resolutions. Slide up for more pixels, and switch anti-aliasing on to let edge pixels take partial brightness instead of being forced fully on or fully off.

Two versions of the same low resolution cube side by side. The left has hard stepped edges. The right uses partly shaded pixels along the edges so they appear smoother
Left: aliased. Every pixel is either object or background, so the edges climb in hard steps. Right: anti-aliased. Pixels that the edge only partly covers are given an in-between shade. The resolution is identical, but the right-hand cube reads as having straight, clean edges because your eye blends those in-between pixels into the impression of a smooth line.

Back to your meteor

Your hub cannot show colour, but it can show brightness from 0 to 100, and that is all anti-aliasing needs. The 50 per cent pixel behind the meteor is a partly-covered pixel: the meteor is not quite there any more, so the pixel is not quite on. Same idea, twenty-five pixels instead of two million.

Optional Everything inside this box is an extension. It is not assessed, and you can skip straight past it to the assessment task if you would rather.

Extra

How JPEG throws pixels away

Take this on if you want to understand what is actually happening when a photo gets "compressed", and why over-compressed images look the way they do.

Storing every pixel of a photo exactly takes a lot of space. JPEG saves space by deciding that some detail will not be missed, throwing it away permanently, and keeping the rest. That is what lossy compression means: you cannot get the original back. Roughly, JPEG:

1

Splits the image into 8 × 8 pixel blocks

Every block is then handled separately, which is why the damage, when it shows, shows up in squares.

2

Describes each block as a set of patterns rather than 64 separate pixels

Broad, gentle changes across the block are recorded strongly; fine, rapid changes are recorded weakly.

3

Rounds the fine detail away

The quality setting decides how brutally. This is the step that loses information, and it cannot be undone.

4

Stores colour more coarsely than brightness

Your eyes are far more sensitive to changes in brightness than in colour, so JPEG quietly keeps less colour data.

Compression lab

One image, saved four times at different quality settings. Watch the file size fall, then look at what it cost.

Test image showing a gradient, sharp text, fine lines and flat colour blocks at the selected JPEG quality
Quality 95 File size 38.1 KB Saving 0%
Magnified view of text edges saved at high quality, showing clean sharp letters
Quality 95, magnified. Letter edges stay crisp and the background stays flat white.
The same magnified text edges saved at very low quality, showing eight by eight blocks and grey noise around the letters
Quality 3, magnified. The 8 × 8 blocks are now obvious, and grey fuzz has appeared around every letter.

What to look for

blocking

Blocking

Flat squares appear across areas that should change smoothly, like skies and gradients. You are seeing the 8 × 8 grid itself.

ringing

Ringing and mosquito noise

A halo of speckled fuzz that clings to sharp edges, especially text. Hard edges need the fine detail JPEG just discarded, so it guesses and gets it wrong.

bleed

Colour bleeding

Strong colours smear past their boundaries, because colour was stored at lower resolution than brightness.

banding

Banding

A smooth gradient breaks into visible stripes, since the subtle steps between shades were rounded away.

The practical lesson

Use JPEG for photographs, where the detail it discards genuinely is hard to notice. Use PNG for screenshots, logos, text and pixel art, where hard edges and flat colour are exactly what JPEG handles worst. And never re-save a JPEG repeatedly: each save throws away a little more, and it never comes back.

End of optional section

6

Assessment task: build an arcade game

Now use everything above to build something playable on 25 pixels. The focus of this assessment is whether your code works. You are free to use whatever blocks, loops, variables and structures you need to get the job done.

Pac-Man

Start here
Animated Pac-Man opening and closing its mouth beside a pellet
  • A chomping head, animated as a repeating loop of frames
  • At least three frames so the mouth moves convincingly
  • A button press makes a pellet appear, which disappears at the next chomp
  • The chomp keeps its rhythm while the pellet comes and goes

Pong

Two motors
Animated Pong game with two paddles and a bouncing ball
  • Two motors, each driving one paddle up and down the display
  • A ball travelling along the horizontal; no angles required (it will be a simplified version of the example shown above, as the low resolution makes it too tricky to show angles)
  • Collision detection: does the ball reach a paddle, or miss it?
  • Optional: a button to start, a game-over screen, a score

Space Invaders

Alternative
Pixel art row of space invader aliens
  • A motor moves the player left and right along the bottom row
  • A button fires a shot that travels up the display
  • A shot landing on an alien destroys it and adds a point
  • Your player and aliens can be single pixels; the resolution is too low for complicated shapes

Everything is a coordinate

These games look very different but they are the same problem underneath. Something has a position, a variable holds that position, user input changes it, and each pass of a loop redraws the display. A paddle is a row variable, a Pac-Man mouth is a frame number, and a shot is a y that keeps decreasing until it hits something.

Frame planner

Sketch your animation here before you build it in blocks. Click a pixel to cycle its brightness, use the tabs to design up to four frames, then press play to check the movement. The block list underneath updates as you draw.

Blocks for the frame you are editing. Pixels left at 0 do not need a block unless you are clearing something from the frame before.

Rubric

Developing

The meteor works
  • The Step 3 meteor code is copied, running on the hub, and uploaded
  • The animation includes the anti-aliased trail pixel at reduced brightness
  • The speed variable responds to the motor movement while the program runs

Consolidating

Pac-Man, chomping
  • LowAn animation that mimics the chomping head of Pac-Man
  • MidThe Pac-Man animation runs across at least three frames
  • MidA button press makes a pellet appear, which then disappears at the next chomp, with no other noticeable interruption to the animation
  • HighPac-Man and pellet complete, plus either some progression into using the motors for additional control, or a start made on controlling a Pong paddle as a separate program

Extending

An actual game
  • LowTwo motors drive two paddles, with paddle position controlled by motor angle
  • HighA working collision detection system checks whether the ball has hit a paddle
  • AltSpace Invaders instead: motor-controlled player, button to shoot, aliens destroyed on a hit, and points awarded
  • ExtraOptional additions such as a button to start the game, a game-over screen when the ball reaches the side, or a scoring system

Code hint: turning a motor angle into a paddle position

The hard part of Pong is not drawing the paddle, it is converting a motor angle that runs to hundreds of degrees into a row number between 1 and 5. Divide the angle to shrink the range, round it to a whole number, then clamp it so it can never leave the display. Study how this example does all three.

Block code hint: a forever loop reads each motor's relative position, divides and rounds it into a paddle variable, then uses if blocks to clamp the value so the paddle stays on the display
Pong paddle control. Read the motor, scale it down, round it, then use if blocks to trap the value inside the display. Everything after this is drawing pixels and checking whether two numbers match.

Before you submit

0 of 7 complete