Skip to content
Currently booked
· 4 min read

Building a browser game: how Onigiri Hop works

The little game hidden in this site's footer: a plain 2D canvas, physics that feel the same at any frame rate, gaps that are always reachable, and a game that only loads when someone wants to play.

Request an AI summary

In the footer of this site, a link says “Don’t play with my favorite food”. Behind it is Onigiri Hop: a small arcade game in which the onigiri hops through an endless row of gaps. Tap, click or press Space to hop; touch a pipe or the ground and the round is over.

It’s a small game, but the same questions that matter in any interactive web project show up in it: how it feels, how fast it loads, and whether it behaves the same on every device. Here’s how it’s built.

1. Canvas: a plain 2D drawing surface

The game draws on a single 2D canvas. Every frame it paints the pipes as one path and the onigiri as one sprite; the score sits in the page around it. That’s all a game like this needs, and a 2D canvas is lighter to start than a 3D graphics context.

The game lives in a native <dialog> element. While it’s open, the page behind it doesn’t scroll, and closing it puts the game back on its start screen.

2. World units: the same game on every screen

Screens come in every size, but the game shouldn’t get easier on a large monitor or harder on a small phone. So everything happens in world units: the world is always 640 units tall, and the canvas scales that world to whatever space it has. Gravity, hop strength, gap sizes and speeds are all defined in those units. A hop is the same height on every screen.

3. Physics: the same arc at any frame rate

Screens also refresh at different rates: 60 frames per second, 120 on many newer phones, 30 in power-saving mode. A naive game moves things a fixed amount per frame and so runs faster on faster screens.

Onigiri Hop computes each step from the actual time since the last frame, and it does so with the exact formula for falling under constant gravity. The result: the hop follows the same arc whether the screen draws 30 or 120 frames per second.

Frame timing on phones can be uneven, especially right after a tap. The game smooths that out with a running average of recent frame times, so a single late frame doesn’t make the pipes jump, while a lasting change, such as a switch to 120 Hz, is picked up within a fraction of a second.

4. Fairness: every gap is reachable

Randomly placed gaps can create impossible situations: a gap at the very top right after one at the very bottom. In Onigiri Hop, each new gap stays within a set distance of the previous one and never gets too close to the edges.

That rule is checked by a test that generates ten thousand gaps in a row and confirms each one stays on screen and within reach of the one before. It runs with every push.

Two more details make it feel fair:

  • A forgiving hitbox: the collision area is a little smaller than the sprite, whose corners are transparent anyway.
  • Gentle difficulty: with every point, gaps get slightly narrower and pipes slightly faster, levelling out after a while instead of growing endlessly.

5. Loading: only when someone plays

Most visitors never open the game, so it shouldn’t cost them anything. The game code and its sprites load only the first time someone opens the dialog. The animation loop runs only while the dialog is open and a round is in progress; after a crash, it stops until the next tap.

6. Touch: feeling right on phones

Taps have to feel instant. On touch screens, browsers often add extra behaviour to a tap: a highlight flash and simulated mouse events afterwards. The game handles touch input directly, so a tap is a hop and nothing else.

7. High score: kept on the device

The best score is stored in the browser’s local storage, so it’s still there on the next visit. If storage isn’t available, for example in a private window, the game keeps the best score for the current visit only. No account, no server, nothing leaves the device.

The short version

  • 2D canvas in a native dialog: one path and one sprite per frame.
  • World units make the game the same on every screen.
  • Exact physics give the same hop at any frame rate, smoothed against uneven frames.
  • Fair gaps, checked by a test with ten thousand rounds, plus a forgiving hitbox.
  • Loads on demand and runs only while someone is playing.
  • High score stays on the device.

Want a game or an interactive experience for your brand? Get in touch.