Fetching latest headlines…
🕹️ SOLSTICE: Hold the Light Until Dawn - A 3D Browser Game for the June Solstice Jam
NORTH AMERICA
🇺🇸 United StatesJune 14, 2026

🕹️ SOLSTICE: Hold the Light Until Dawn - A 3D Browser Game for the June Solstice Jam

5 views0 likes0 comments
Originally published byDev.to

This is a submission for the June Solstice Game Jam

On the June solstice the sun stays up longer than any other day of the year. Then it sets anyway. SOLSTICE is what happens after that: the longest night, one stone ring, and you holding the last flame.

Play SOLSTICE · no install, runs in the browser

What I Built

SOLSTICE is a 3D action survival game where daylight is not background flavor. It is the mechanic.

You are the Sunbearer, keeper of an ancient ring of standing stones. When the solstice sun goes down, shadow creatures crawl out to snuff your flame. You fight back with a glowing blade, dash through dark bolts, and vacuum up the light they drop when they break apart.

The whole run hangs on two meters:

Light is your health, your urgency, and your fuel. It ticks down over time and falls hard when something hits you. Let it hit zero and the night wins.

Dawn is how close you are to sunrise. It climbs as you survive and as you kill. Fill it to 100% and the sky actually changes: the solstice sun crests the stones, the shadows burn off, you win.

Your light is your life, your weapon, and the clock. When it runs out, the night wins.

I built this for the jam theme on purpose. Light, darkness, and time are not three separate ideas in the UI. They are one loop you feel in your hands: slash, dodge, collect, survive.

The arena is Stonehenge inspired. The real monument lines up with the solstice sunrise, so defending that ring felt right. The toughest wave and the Warden of the Long Night boss show up late, right before first light. Darkest before dawn is not just flavor text here.

Controls (laptop friendly, no gamepad needed):

Input Action
W A S D or arrow keys Move
Space or left click Light Slash
Shift Dash with brief invulnerability
E Solar Flare, charged AoE ultimate
Esc Pause

Three difficulties on the start screen: Acolyte (gentler), Sunbearer (default), Eclipse (two bosses, meaner spawns). You can swap difficulty from pause or the end screen if a run feels wrong.

Video Demo

Full run below: sunset, the swarm, the Warden, and the dawn break.

Playable build (single HTML file). You can try the CodePen embed below, but the web link is the best way to play: fullscreen, proper keyboard focus, and fewer iframe limits.

Play here (recommended): https://longphanquangminh.github.io/sunbearer/

Code

Whole game lives in one file. Repo:

SOLSTICE — Hold the Light

A browser-based 3D action-survival game built for the DEV June Solstice Game Jam (2026). You are the Sunbearer, last keeper of an ancient stone ring. As the solstice sun sets, shadow creatures pour from the dark — your Light is your health, your weapon fuel, and the clock. Survive the longest night and reach dawn.

Play now · Demo video

The hook

Your light is your life, your weapon, and the clock. When it runs out, the night wins.

  • Light drains over time and drops fast when enemies hit you. Slay shadows to collect light fragments and stay alive.
  • Dawn fills as you survive. Hit 100% and the solstice sun crests the horizon — you win.
  • The sky, fog, sun, and stars repaint in real time from sunset through midnight to golden dawn.

Controls

Input Action
W A S D / Arrow keys

Clone and serve locally if you want to poke around (needs HTTP, not file://):

git clone https://github.com/longphanquangminh/sunbearer.git
cd sunbearer
npx serve .

How I Built It

I gave myself a hard constraint: one self contained HTML file, no bundler, no downloaded assets, host it anywhere. Open the page, play. That shaped every decision after it.

Stack in short:

  • Three.js r160 over WebGL, loaded with a native importmap from jsDelivr
  • UnrealBloomPass for glow on the blade, orbs, and dawn light
  • Web Audio only: every sound is synthesized at runtime, zero audio files
  • Procedural canvas textures for the ground and particles
  • No external models or image assets

Three.js comes in clean with an import map, no build step:

<script type="importmap">
{
  "imports": {
    "three": "https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js",
    "three/addons/": "https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/"
  }
}
</script>

Postprocessing loads dynamically inside try/catch. If bloom fails on a weird GPU, the game still renders instead of dying on a black screen.

The sky is the progress bar

The Dawn meter does more than fill a UI bar. One value, dawn from 0 to 1, drives keyframe blending across sky color, fog, sun angle and intensity, ambient light, hemisphere light, and star opacity. You start at hot sunset, sink into violet dusk and deep midnight, then break into gold when you win. You can read how close sunrise is by looking up, not only by checking HUD numbers.

const SKY = [
  // p,    sky,      fog,      sun,    sunInt, amb, hemi, stars
  [0.00, 0xE8743B, 0x6e3a2e, 0xffb060, 1.5, 0.55, 0.60, 0.0],
  [0.50, 0x0c1230, 0x0a1026, 0x6a78c0, 0.35, 0.32, 0.35, 1.0],
  [1.00, 0xFFC56B, 0x9a6a3e, 0xffe0a0, 1.7, 0.70, 0.85, 0.0],
];

function updateDay() {
  const p = dawn / dawnMax;
  const [a, b, t] = segment(SKY, p);
  scene.background.lerpColors(a.sky, b.sky, t);
  scene.fog.color.lerpColors(a.fog, b.fog, t);
  sun.intensity = lerp(a.sunInt, b.sunInt, t);
  stars.opacity = lerp(a.stars, b.stars, t);
}

Combat and waves

Melee uses arc hit detection: range plus facing angle, knockback, combo multiplier on chained kills. Enemies are shades, fast wisps, ranged casters that make you move, and the Warden boss on a wave director that ramps up over the night.

Difficulty is a thin multiplier layer at run start: enemy HP, damage, speed, spawn rate, light drain, dawn duration, orb drops, enemy cap. Three distinct feels from one codebase without forking logic everywhere.

Performance on a laptop

Capped device pixel ratio, recycled sprite particle pool, blob shadows on most things with one real shadow casting sun, hard enemy cap. It should stay smooth on a normal laptop without asking for a gaming rig.

The design change that actually mattered

Early builds had separate HP and a survival timer. Too noisy. Merging them into Light made every choice sharper: dash away and let the meter tick, or push in for fragments that refill you. Tuning that drain vs reward loop took the most iteration, which is why I added selectable difficulty instead of pretending one balance fits everyone.

Prize Category

Submitting for Best Google AI Usage.

I wrote and shipped the game code myself in JavaScript and Three.js. For this submission post I used Google Gemini to help draft sections, tighten explanations, and polish the writeup so judges can follow the theme and technical choices quickly. The game logic, rendering, audio synthesis, and balance tuning are my own work; Gemini assisted with communication around the project, not with generating gameplay systems.

Disclaimer: This DEV post was written with help from Google Gemini for drafting and polishing the submission content. The game itself was built and debugged by hand. I am noting AI usage here for transparency and because it fits the jam's Google AI prize category.

Hold the light until dawn. 🌅

If you try it, I would love your high score and honest feedback in the comments. Happy solstice, whichever hemisphere you are in.

Fancy formatted version of this writeup: longphanquangminh.github.io/sunbearer/post

#DEVChallenge #gamedev #javascript #threejs #webgl

Comments (0)

Sign in to join the discussion

Be the first to comment!