Skip to content
ZapskiRetro

Luna Lander

A lunar lander for the original Game Boy: bring the ship down on a pad, in one piece, without much fuel to spare. Gravity is always pulling, the engine is the only thing that beats it, and fuel is the whole clock.

Game Boy (DMG)GBDK-2020Super Game Boy enhancedHomebrew

Emulated by binjgb (WebAssembly). Click the screen to give it keyboard focus. Open full screen.

How to play

ScreenButtons
FlyingLEFT / RIGHT push the ship sideways and hold to keep pushing · A or B thrust, held, and empties the tank the whole time
TitleSTART begins the level the title names · SELECT switches LANDER / DESCENT, keeping your place
LandedSTART goes on to the next level · SELECT back to the title
CrashedSTART tries the same level again · SELECT back to the title
Mission completeSTART replays the twelve from level 1, on a smaller tank · SELECT back to the title
Mid-flightSTART restarts the level · SELECT back to the title

LEFT and RIGHT are held, like the engine, and not one step per press: the ship leans into the push and its sideways speed builds for as long as the direction is down. Let go and it stands upright again immediately, and the drift dies away by itself. There is no separate brake — cancel a drift by pushing the other way and then letting go, rather than steering the nose round at it. Pushing sideways burns fuel at the same rate thrusting does.

Keyboard

  • D-padArrow keys
  • AX
  • BZ
  • STARTEnter
  • SELECTC

Emulator

  • Toggle the SGB borderS
  • Fast-forwardShift
  • PauseSpace
  • Save / load stateF6 / F9
  • RewindBackspace

Landing

Put the ship down on a pad — a flat, lit stretch of ground. Everything else on the ground is unmarked and fatal, however gently you touched it. Three more things have to be true at the moment of touchdown:

  • Come down slowly. Watch VY — a hard descent is a crash even on a pad, and it has to be small by the time ALT reaches 0.
  • Don't drift sideways. VX has to be nearly nothing when you arrive, so the drift is gone before the last few pixels.
  • Keep the nose up. Within about 22.5° of vertical — which mostly means not still pushing when you arrive.

There is a little room in all three, but not much. The way to land well is to arrive already under control rather than to correct at the last instant. The ship starts every level in the air with gravity already pulling it down, so a life with nobody at the controls is a crash.

Every level has one or two pads, and the smaller one pays ×2 against the larger one's ×1. You always start above the ×2 pad, so the tempting one is the one you are already lined up on. The status bar names the pad you are over while flying — X2, X1, or X0 when there is no pad under you at all, which is the spot you do not want.

Super Game Boy

Luna Lander title screen

The border is the game's own: a rocket standing either side of the screen on the lunar surface, and a porthole rim round the window, as if the view is out of the ship. The emulator sees the ROM's SGB flag and starts with the border on — press S to toggle it. Nothing about it changes how the game plays, and on anything that is not a Super Game Boy it is simply not there.

Two modes, twelve levels each

On the title screen SELECT picks between LANDER and DESCENT, and START plays whichever one the title names — at the level number on that line, not from the beginning. SELECT in flight goes back there, so a mode you did not mean to be in is one press from the one you did, and leaving does not cost you your place. The two modes keep their own places.

LANDER is the short world — one 160-pixel screen, wrapping left to right, the whole world on the screen at once. DESCENT is 808 pixels of world with the camera following the ship down it, opening up to a hundred tile rows above the pad. Same ship, same landing rule, same tank; what differs is the world.

Each mode is a fixed chain of twelve levels — the same twelve every time you play them, and the same on the next cartridge. Landing well advances you one; crashing gives you the same level back. Clear the twelfth and the chain replays from level 1 on a smaller tank, one step a lap until it settles at half of what you started with. That is the whole of the difficulty curve: the layouts never get harder, the fuel gets tighter.

Under the hood

Written from scratch in C with GBDK-2020 — no game engine, in the same lineage as GB Protector and GB Checkers. The physics live in a pure header with no GBDK in it, so gravity, the engine and the landing rule are unit-tested on the host before anything touches a ROM, and the built ROM is then driven headless and asserted on. The art is generated from a Python script; the cart is ROM-only at 32 KB with no mapper; sound is three one-shots written where they are made — a burn on channel 1, a landing on channel 2, a crash on channel 4.

A level is a recipe expanded at build time — a shape, an amplitude, a base depth, a pad span and a spawn column, which a generator turns into a 20-byte height profile. The ROM carries only the expanded bytes, so the collision reads a plain array every tick with no expansion at runtime. The generator rejects a bad recipe rather than drawing it: a spawn not over a pad, a shoulder too steep to land on, a profile that breaks its chain's size rule.

Five triangle-wave shapes lay out the ground, each zero at both seam columns by construction, so no choice of depth or amplitude can make the world's left-to-right wrap visible. The descent scrolls by streaming the map a row at a time around the camera, while the status bar sits over the ground rather than beside it and does not move with it.

The Super Game Boy border is generated art too — a PNG turned into tiles and a map, then parked in the cartridge's second bank. The cart has no mapper, so that bank is permanently mapped and the game hands the SGB plain pointers, the same trick GB Checkers uses.

More about Luna Lander

More games