Inspiration

The theme was the early 2000s, so we wanted something that felt like an old Flash game or a Wii party night: everyone in one room, shouting at the same screen. We liked the idea of one person physically dodging while everyone else gangs up on them, using the phones already in their pockets as controllers. No app, no install, just scan and throw.

What it does

One player stands on a balance board and leans left and right to steer a snowboarder down a ski slope on the big screen. Everyone else scans a QR code and flicks their phone to throw snowballs.

  • Snowballs take a moment to fly, so a quick rider can lean out of the way. A hit only counts if the rider is still there when it lands.
  • A harder flick throws a faster snowball.
  • Every hit costs the rider 10 health. Survive 60 seconds and the rider wins; hit zero and the throwers win.
  • Each phone has a recharge bar between throws, so nobody can just spam.

How we built it

The board. An ESP32 with an ADXL345 accelerometer is taped to a skateboard deck balanced on a rolled-up mat. The firmware works out the tilt from the direction gravity pulls:

$$\theta = \operatorname{atan2}\left(-a_x,\ \sqrt{a_y^2 + a_z^2}\right)$$

It smooths that, subtracts the calibrated "level" angle, and sends a steering value between $-1$ and $1$ to the laptop over USB about 50 times a second.

The host screen. It runs in Chrome and reads the board through the Web Serial API. It draws a pseudo-3D slope like an old arcade racer, with a Y2K HUD: a WordArt timer, a chrome score pill and an XP-style health bar.

The phones. They connect through a Node.js + Socket.IO server, which checks every message against a schema and rate-limits spam. The phone uses its motion sensors to aim (left/right tilt) and to detect the flick (a spike in acceleration).

The rules. The game rules are pure TypeScript functions with no screen or network code, so we covered them with 65 automated tests. Snowball flight time depends on how hard you flick, with power $p \in [0, 1]$:

$$t_{\text{flight}} = 800 - 350\,p \ \text{ms}$$

To keep things fair as more people join, each player's cooldown grows with the square root of the number of throwers $n$, capped:

$$t_{\text{cooldown}} = \min\left(4.5\,\text{s},\ 1.5\,\text{s} \cdot \sqrt{n}\right)$$

So more players still means more snowballs overall, but the rider never gets completely buried.

We started from a boilerplate we set up on Friday evening (networking, phone and host pages, and a first firmware sketch). The game itself, the hardware rig, the visuals and all the tuning were built over the weekend.

Challenges we ran into

  • Uni Wi-Fi blocked everything. Phones couldn't reach the laptop directly, and our first tunnelling tool was blocked too, so we switched to ngrok.
  • Our planned sensor wasn't available, so we swapped to an ADXL345 from the hardware desk and made the firmware detect either sensor automatically.
  • The board couldn't steer once someone stood on it. With nobody on it, the seesaw rests tipped onto one end, and the firmware was calibrating "level" at that angle on power-up. A perfectly balanced rider looked like a hard lean. We changed it so calibration only happens when the rider is actually balanced, and it refuses obviously tilted readings.
  • Phone aim felt random. By the time the phone detects a flick, the throw has already swung it, so the aim it read was junk. We fixed it by keeping a short history of the aim and using where the phone was pointing about $250\,\text{ms}$ before the flick.
  • Merging two people's work. One of us built the game logic while the other built the visuals in parallel, and combining them without losing either took careful git work.

What we learned

  • Hardware always behaves differently once a real person stands on it: test with the real rig early.
  • Phone sensors are tricky. They need https, permissions on iPhone, and you have to account for the throw's own motion.
  • Pure, tested game logic made it safe to change things quickly, right up to the last hour.
  • How to keep one shared codebase working while two people change it at once.

What's next

  • A vibration motor on the board, so the rider feels every hit.
  • Teams, power-ups and a leaderboard across rounds.
  • A proper wobble-board rig to replace the rolled-up mat.

What it does

How we built it

Challenges we ran into

Accomplishments that we're proud of

What we learned

What's next for Snow Day: Dodge or Get Snowed

Built With

Share this project:

Updates

Submission history