Building an LCD Obstacle Dodging Mini-Game

Building an LCD Obstacle Dodging Mini-Game

July 16, 2026 by ThinkRobotics
Share

Who says you need a high-resolution monitor and a powerful processor to play a video game? This code transforms a standard Arduino Nano, an analog joystick, and a basic 16x2 text display into a fully playable, fast-paced arcade game. You control a cursor, dodging incoming blocks while trying to survive and rack up a high score. Code for this project is available here.

The Hardware Setup

Arduino Nano Analog Joystick Module 16x2 I2C LCD (0x27)
  • The Controller: A standard analog joystick module. The vertical axis is wired to analog pin A0 for moving the player, the horizontal axis is on A1 for pausing the game, and the physical click button is on digital pin 2 for restarting after a game over.
  • The Screen: A basic 16x2 I2C LCD (operating at address 0x27) acting as the game engine's display monitor.

Component Pinout Guide

Wire your components to the Arduino Nano using the following connections (note that A4 and A5 are the standard I2C pins for the Nano):

Component Component Pin Arduino Nano Pin Function
Analog Joystick VCC 5V Power supply
Analog Joystick GND GND Ground
Analog Joystick VRy / Y-Axis A0 Vertical movement (Up/Down)
Analog Joystick VRx / X-Axis A1 Horizontal movement (Pause)
Analog Joystick SW / Switch D2 Push button (Restart)
I2C LCD VCC 5V Power supply
I2C LCD GND GND Ground
I2C LCD SDA A4 I2C Data line
I2C LCD SCL A5 I2C Clock line

How It Works: Gameplay Mechanics

You play as an arrow cursor (>) locked to the left side of the screen, restricted to moving between the top row and the bottom row. Every few seconds, solid square obstacles (0xFF) spawn on the far right edge of the display.

Every second, these obstacles shift one column to the left. You must use the joystick to switch rows and avoid them. If an obstacle hits your column while you are in the same row, it is Game Over. If it passes you safely and exits the screen, your score increases by one.

Technical Highlights in the Code

🧩
Multi-Obstacle Array Tracking: To allow multiple enemies on the screen at once, the game utilizes two 16-slot arrays: obstacleX and obstacleRow. This acts as an object pool, effectively keeping track of the specific coordinates of every active block without overflowing the Arduino's limited memory.
⏱️
Non-Blocking Game Engine: Fast-paced games cannot rely on the standard delay() function, or player inputs would be entirely ignored while the game pauses. This code uses millis() to create separate, independent engine timers: one interval for spawning new blocks (4000ms) and another for shifting them left (1000ms). The player can move their joystick instantly at any time between these frame updates.
🛡️
Fair-Play Spawning Logic: To prevent the game from generating an impossible, unavoidable wall of blocks, the spawner includes a strict safety check. Before spawning a new block, a loop checks columns 13, 14, and 15. If any block is currently present in that zone, it aborts the spawn, guaranteeing you always have enough space to dodge.
⏸️
Interrupt-Free Pause System: By flicking the joystick left or right, the game enters a dedicated pause state. It flags the system as paused, immediately halts the rendering engine, and displays "PAUSED" until the stick is safely returned to the center.