Learn

The arcade stacker game on two LED matrices

Advanced

Or see every lesson.

  • 455parts on the bench
  • 43boards running now
  • 1.00xreal time, on every board
ESP32-C3: the arcade stackerlive0.000 s 0.00x
Press Run, then press the big button to drop the row
The Stacker example: two cascaded MAX7219 matrices for an 8x16 field and one arcade button. Press it to drop the row.

Stacker is the arcade cabinet with the tall column of lights: a row slides back and forth, you press the button to drop it, and anything that hangs over the row below is cut off. Each row is narrower and faster than the last, and if you trim it to nothing the game is over. It is the most opened example in Mokxi, and it makes a great build because the whole cabinet is one button and two cheap LED modules.

The circuit above runs it on an ESP32-C3 in Arduino code. Two MAX7219 8x8 matrix modules stand one above the other for a field eight wide and sixteen tall. Press Run and a block three dots wide starts sliding along the bottom. Press the big button to drop it. Land a block on the top row and you win: the finished tower holds, the whole field fills from the floor up and flashes, and a new game starts. Leave the game alone for four seconds and it plays itself, now and then missing on purpose, until someone presses the button again.

What you need

  • An ESP32-C3 board (or an Arduino Uno; see below)
  • Two MAX7219 8x8 LED matrix modules
  • A 30 mm arcade button, or any pushbutton
  • A breadboard and jumper wires

Wiring

Part and pinGoes toNote
Top matrix DINGPIO 7Data goes to the top module only
Top matrix DOUTBottom matrix DINThe cascade
Both matrices CLKGPIO 5Shared
Both matrices CSGPIO 6One chip select for the chain
Matrices VCC and GND5V pin and GNDNot 3V3: the MAX7219 wants 4 V or more
Arcade buttonGPIO 3Other leg to GND, the pin’s own pull-up

The cascade: two modules, three wires

Each MAX7219 has a 16-bit shift register and a DOUT pin at its far end. Chain DOUT of the top module into DIN of the bottom one and share the clock and the chip select, and the two act as one 32-bit register. Send 32 bits with CS low and the first 16 bits you sent end up in the second chip. One rising edge of CS latches both at once.

So every write is a pair: the bottom module’s packet first, because it has the furthest to travel, then the top module’s. That is all write_chain() does. It costs one pin less than a chip select per module, and it is how the cheap four-in-one matrix boards are wired inside.

The sketch drives the chips with its own short functions rather than a library, so the cascade is in plain sight: one packet is four unused bits, a four-bit register address and a data byte, shifted out most significant bit first. On a real board LedControl does the same with LedControl lc(DIN, CLK, CS, 2).

One register in each module, latched together
static void shift_packet(uint8_t address, uint8_t data) {
  uint16_t packet = ((uint16_t)(address & 0x0f) << 8) | data;
  for (int8_t bit = 15; bit >= 0; bit--) {
    digitalWrite(CLK_PIN, LOW);
    digitalWrite(DIN_PIN, (packet >> bit) & 1u ? HIGH : LOW);
    digitalWrite(CLK_PIN, HIGH);
  }
}

static void write_chain(uint8_t address, uint8_t bottom, uint8_t top) {
  digitalWrite(CS_PIN, LOW);
  shift_packet(address, bottom);  // pushed through the top chip
  shift_packet(address, top);
  digitalWrite(CS_PIN, HIGH);     // both latch here
}

How the game is played in code

The stack is sixteen bytes, one per level, with one bit per column. Dropping the block is a single AND: the block’s columns AND the row below. What survives is the new row, and its width is the new block width. If nothing survives, the game is over. The floor catches anything, so the first drop always lands.

The block starts three wide. From level 7, the top row of the bottom module, it is at most two wide, and on the top three levels it is one. The step time falls with height, from 210 ms per column at the bottom to 70 ms at the top, worked out as 210 minus 140 times the level over 15.

The button counts on its edge: the sketch remembers whether it was down last time, so holding it drops one block, not one per loop. Between steps the sketch sleeps 2 ms at a time, which still reads the button 500 times a second.

On an Arduino Uno instead

Nothing in the sketch is ESP32 only: it uses digitalWrite, digitalRead, millis, delay and random. To run it on an Uno, change the four pin numbers (for example DIN 11, CLK 13, CS 10 and the button on 2) and power the modules from the Uno’s 5 V. Open it in the editor, swap the board, and rewire.

Common mistakes

The bottom half stays dark. The cascade wire from the top module’s DOUT to the bottom module’s DIN is missing or on the wrong pin. Pull it in the circuit above and the block, which starts at the bottom, disappears; the top half still works, as you see once the stack climbs into it.

The halves are swapped or show each other’s picture. The packets are in the wrong order. The first one sent lands in the far module.

Nothing lights at all. A MAX7219 comes up shut down, scanning one row, at zero brightness. The sketch writes shutdown, scan limit, decode mode and intensity at the start; leave any of them out and the panel stays dark.

Powering the modules from 3.3 V. They need 4 V or more, so use the board’s 5V pin.

The button drops every block while held. Count the change from up to down, not the level.

Questions

How do I make a stacker game with Arduino?

Use two MAX7219 8x8 matrices chained for an 8x16 field and one button. Keep one byte per row, slide the block with millis(), and when the button is pressed AND the block with the row below. Whatever is left is the new row.

Can I make it on one 8x8 matrix?

Yes, with eight levels instead of sixteen. Set LEVELS to 8, move the narrowing levels down, and drop the second packet from each write.

Why does the game play by itself?

After four seconds with no press it goes into attract mode, like an arcade cabinet: it aims at the row below and now and then misses by one column on purpose. One real press takes the game back.

Can I use a WS2812 LED strip instead?

Yes. A 16x8 grid of WS2812 LEDs works the same way with the Adafruit NeoPixel library. The game logic does not change, only the drawing.

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.