Gyda Nawarungruang

Dino Dash

Northwestern CE 205, Winter 2023

View code on GitHub ↗︎
  • ARM Assembly
  • VGA Graphics
  • Game Development
The dinosaur running across the desert, jumping past a cluster of cacti, with a live score counter in the corner

A Chrome-Dino-style runner, written directly in ARM assembly for the DE1-SoC's ARMv7 (Cortex-A9) processor. No game engine or graphics library, just direct writes to the board's memory-mapped VGA pixel buffer and pushbutton input.

Features

  • Gravity: the dinosaur's y-velocity is affected by gravity during a jump, rather than jumping in a fixed arc.
  • Difficulty scaling: the obstacles' and background's scroll speed increases with each level.
  • Power-up: running into a cake makes the dinosaur invincible for a short time.
  • Scrolling background: the background is built from pixmaps and scrolled right-to-left to sell the illusion of running.

Controls

  • Push button 0 to jump
  • Run as long as possible without colliding with an obstacle
  • Push button 3 to restart
The dinosaur mid-run toward a cake power-up
The dinosaur mid-run toward a cake power-up

How it's built

Toolchain and rendering — The game runs in CPUlator, an in-browser ARMv7/DE1-SoC simulator, assembled and linked for a Cortex-A9 target with the standard arm-eabi-as/arm-eabi-ld toolchain. There's no framebuffer library in between: every sprite, background tile, and score digit is plotted by computing a pixel's address directly from its x/y coordinates against the VGA buffer's base address and writing a 16-bit color value to it. The whole screen (dinosaur, obstacles, clouds, cacti, and the live score readout) is redrawn this way every frame.

Input — Pushbutton input is interrupt-driven rather than polled, so a jump or restart is caught as soon as the button is pressed instead of on the next polling pass.

Collision detection — Compares bounding boxes between the dinosaur and each obstacle type, with the hitbox padding on each edge tuned per sprite rather than using one generic box, since the cactus and cake sprites aren't the same drawn width.

Jump physics — A small state machine driven by the dinosaur's y-velocity and y-acceleration, both stored as struct fields. While rising, y-position decreases each frame; past the jump's apex, downward acceleration accumulates into velocity every frame until landing, at which point velocity and the jump flag reset to their initial values.

Debugging

The scrolling background was the hardest part to get right. Six background layers (two ground segments, three clouds, and the cake) each track their own x-position independently, decrementing it every frame and resetting back off-screen once they scroll past the left edge. One of those reset comparisons used an incorrectly defined hex value, which didn't show up as an obvious crash, just a visibly wrong reset point on one layer when the game was running. Finding it meant stepping through CPUlator's register and memory view frame by frame, watching each background sprite's position against its reset condition, until the mismatched comparison value stood out.

The CPUlator simulator mid-debug session
The CPUlator simulator mid-debug session

Result

View the gameplay demo below:

Demo of Dino Dash