chopstickshq.com / arena
ARENA app icon — pixel skull on a dark card

ARENA

FPS for macOS. Every run generates a new 5 × 5 km world of rolling daylight terrain. Raw OpenGL, HDR lighting, software ray tracing, six guns, escalating waves — in a 2.2 MB download.

Download for macOS

macOS 11+ · Apple Silicon · 2.2 MB · no accounts, no telemetry, no network

First launch: the app is self-signed, so macOS will warn on first open. Right-click ARENA.appOpenOpen once; after that it launches normally. The terminal install below handles this for you.

// SCREENSHOTS

ARENA gameplay — generated buildings and pillars across open daylight terrain
Generated buildings, bunkers and pillars. Every run, a new world.
ARENA gameplay — a brick building with a doorway, grunt approaching across the field
Walled buildings you can enter, with stairs to the roof.

// TERMINAL INSTALL

One line, no Xcode or dev tools — downloads the prebuilt app to ~/Applications, clears quarantine and launches:

curl -fsSL https://chopstickshq.com/arena-fps/install.sh | bash

Prefer to read it first? install.sh — 30 lines, curl + ditto + xattr, nothing else.

// WHAT IT IS

A new 5 km world every run

25 km² of terrain generated from a seed — rolling hills, ruins, pillars, crate stacks and braziers, streamed in 64 m chunks as you walk, with the ground meshed finer under your feet than out at the horizon. Die and you wake up somewhere else entirely. The pause screen shows your seed if you find one worth keeping.

Every hillside is walkable

The whole wave spectrum is normalised so the ground can never exceed a walkable grade — measured worst case about 15°, mean 4°. No invisible walls, no ledges that stop you dead. Cliffs only at the 5 km boundary.

Daylight, properly lit

Lighting runs in linear HDR and is filmic-tonemapped on the way out, with sky-and-bounce ambient instead of one flat number — so shadowed ground keeps its colour and bright surfaces roll off instead of blowing out. Hills cast shadows into valleys, baked as the ground is meshed. Distance haze tints toward the sun.

Wave combat

Grunts rush you, imps lob fireballs with a glowing wind-up. Each wave closes in from every direction on wherever you're standing — there's nowhere to run to. Quit anytime, your run auto-saves, right down to the spot you were standing in. Die and it's gone.

Six weapons + shop

Kills pay credits. Press Esc (or B) for the shop: SMG, shotgun, machine gun, chaingun, flamethrower, armor, heals. Credits and gear reset on death — spend or lose it.

Software ray tracing

Real rays traced per pixel in the fragment shader against the world's box soup: sun shadows on High, plus platform reflections and point-light shadows on Ultra. No shadow maps, no screen-space hacks.

Procedural everything

Terrain, brick, tile, wood and metal are generated in-shader (zero texture files). Every sound is synthesized — each gun gets its own report built from muzzle click, gas crack and pressure thump, with a slap-back echo off the terrain. It all plays positionally, so you hear where things are. The icon is rendered by a stdlib-only Python script.

Customise + presets

Crosshair colors, gun finishes, Low→Ultra graphics presets with an FPS counter to compare them. Everything persists between runs.

Build a base

Crates, tables, barricades and lockers are scattered across the world and every one of them can be carried. Press E to lift a piece, walk it where you want it, E again to set it down — it rests on whatever is under it, so walls stack. Placement snaps to right angles, and what you build stays put when you wander out of range and come back.

Hear where it is

Every world sound is positioned and falls off with distance — a grunt behind you, a barrel two hills over, an imp screeching as it picks you up. A brute's charge opens with a roar, which is your cue to move: the lunge is committed, so stepping aside makes it sail past.

Flamethrower

A 40 m cone of burning fuel, 28 ticks a second, cooling from white-hot at the nozzle to smoke at the far end. It respects walls and cover — the fire is traced, not faked.

Explosive barrels

They chain. Fight near them at your own risk.

// CONTROLS

InputAction
WASD + mousemove / look
Left clickfire (shotgun per-click, the rest full-auto)
1–6pistol / SMG / shotgun / machine gun / chaingun / flamethrower
Ecarry / place furniture — build cover
Spacejump
Rreload
Escpause menu — Resume / Shop / Customise / Settings
Bstraight into the shop

// GRAPHICS PRESETS

PresetWhat you get
LOWflat shading, 2 lights — runs on anything
MEDIUMdefault — procedural textures, 4 lights, 4x MSAA
HIGHfull textures, 8 lights, 8x MSAA, ray-traced sun shadows
ULTRA+ ray-traced platform reflections and point-light shadows

Medium holds the vsync cap on Apple Silicon. High and Ultra trace real rays per pixel and cost real frames — the FPS counter is there to help you pick.

// TECH

C++17 · OpenGL 4.1 Core (macOS max) · GLFW + GLM · miniaudio · no engine, ~3.9k lines. The world is a waveform: the seed is stretched into a 1 KB key block, read as pairs that become the heading and frequency of 32 waves, and the amplitude of their sum at a point is the elevation there. It is meshed on the fly with level-of-detail by distance and skirts so the seams can't crack; you walk it by clamping to the surface, so there is no ramp collision to get stuck on. Materials — grass, dirt, rock, concrete, brick, metal, wood — are generated in the fragment shader. The ray tracing is real rays against the structure boxes, traced per pixel in GLSL: a slab test per box is all it takes.