BINX FORGEALL YOU NEED IS AN IDEA.Support BINX ↗
REIMAGINE A GAME · CHECKED 2026-10-11

Super Mario 64 PC Port: Ghostship Explained, Then Build Your Own Platformer

Meet Lywx and Harbour Masters’ Ghostship, check its real source and release, then build Clockwork Heights: an original collectible platformer with free code and an ambitious 3D development prompt.

What the creator made

Mario beside a Piranha Plant on a suspended platform in Super Mario 64 — actual original-game screenshot, not a verified PC-port capture
Actual Super Mario 64 gameplay screenshot. Original game imagery; not a verified capture of Ghostship. Game imagery © Nintendo. Source: IGDB Super Mario 64 media gallery ↗. Shown for editorial review; not included in the reusable tutorial assets. No affiliation or endorsement is implied.

The separated platforms, pickups and nearby enemy illustrate the 3D platforming design discussed here.

Ghostship

Lywx (KiritoDv), lead developer, with the Harbour Masters team and credited contributors

Ghostship is a Super Mario 64 port from Harbour Masters. Its README identifies Lywx as lead developer and credits collaborators for platform work, fixes and asset extraction.

The project requires a supported user-provided game copy and extracts its game data. Its README documents desktop launch paths, an Android extraction flow, mod archives and several rendering backends.

The checked published release is 3.0.0. This is a more current article choice than assuming every Super Mario 64 PC-port search refers to the older sm64-port repository. The projects and creator credits remain distinct.

Latest published release checked: 3.0.0, 7 September 2026 (UTC) · checked 2026-10-11.

AI involvement is not established by the checked creator README/release. This article does not attribute the project to ChatGPT, Claude or Codex.

Creator media remains at the linked original source. The gallery below clearly labels original concepts and actual independent source renders; it is not a recreation of the featured project’s screenshots.

How it works: a decompilation-based native port

Ghostship builds recovered game source with modern platform/rendering components and processes the user’s supported game data into an archive. That differs from an independent mechanics recreation. Its own original tooling notices do not transfer ownership of Nintendo’s game art, characters or binaries.

  1. Recovered source or language
  2. Compiler and platform layer
  3. Separately acquired game data
  4. Native application

Official README ↗ · Build documentation ↗ · libultraship ↗

Recompilation translates instructions; decompilation aims to recover higher-level structure; a mechanics recreation writes a new implementation. An AI tool can help with inspection or coding, but those terms alone do not establish AI use.

The checked repository LICENSE.md is MIT, credited to Lywx. Commercial game assets and other bundled component notices remain separate; Forge does not reuse its game implementation.. Read the original licence ↗. Open-source tool licensing does not license the commercial game’s art, audio, characters or binaries. Forge supplies no ROMs or commercial game downloads.

Learn reverse engineering using permitted practice code → · Explore AI game mashups and creator examples →

LOVE THIS GAME? BUILD YOUR OWN.

What could your game look like?

Clockwork Heights · collectible exploration platformer

A robot apprentice restores a sunlit greenhouse clock. Brass platforms, paper birds and hexagonal repair crystals create its own world without commercial franchise characters or landmarks.

Original Clockwork Heights AI concept artwork: An original clock-tower greenhouse; not Super Mario 64 gameplay
Original AI-generated concept art. Proposed art direction, not creator gameplay or the playable reference.

Collect at least six repair crystals and reach the beacon. Control jump height, use brief energy-limited acceleration and recover safely at the checkpoint.

The complete MIT reference is a 2D side-view mechanics course adapted from the independent public Skycoil source, with a six-crystal completion gate, movement/jump timing, bounded boost, hazards, checkpoint, three lives, timer, pause/restart and a validated local best. It is not a 3D controller; moving gear platforms, orbit camera, robot rigs and the illustrated greenhouse are later milestones.

Clockwork Heights actual tutorial ready state
Actual original simulation/renderer on native Canvas. Not a browser/input or creator screenshot.
Clockwork Heights actual tutorial progress state
Actual original rules and renderer after scripted input. Concept art is separate.
Clockwork Heights actual tutorial goal state
Actual original completed run and renderer, not an AI-generated gameplay screenshot.

Build your own game: thirteen visual steps

Create your own original game inspired by these gameplay ideas. This tutorial does not reproduce the featured commercial game or imply affiliation with its creators.

  1. Choose the free engine and accepted scope

    Run the independent side-view browser source first to inspect jump and collection rules. For the fuller third-person game choose free Godot with its matching CharacterBody3D documentation. The included ZIP does not contain 3D scenes or a finished orbit camera.

    Actual Forge Build a Game genre choices
    Genuine existing Forge capture, 10 October 2026. Choose the genre; it does not show the creator’s game.
  2. Set up the complete original project

    Download the ZIP and extract clockwork. Serve every file over HTTP, for example python -m http.server 8080, then open index.html. Modules require JavaScript MIME types. Run node check.mjs first. The download includes 8 complete files and an MIT notice; no private engine or commercial game files are required.

  3. Install compatible free resources

    Keep the geometric reference while testing rules. Godot, Kenney UI and covered free KayKit/Quaternius editions offer a later engine/art/animation path. Use original creator downloads; preserve exact licence files, distinguish free/Extra/Source tiers and inspect formats, units, forward axis and skeleton. Import one model or clip into a separate editor scene before adding it to gameplay. These ingredients do not supply the game’s controller, camera or objectives.

  4. Create one player and one rules owner

    Create an independent state with position, velocity, lives and collected IDs. Start/Restart replaces the run while the existing controller keeps one frame owner. Input and rendering cannot secretly award progress. In a 3D adaptation, use the selected engine body and collision API rather than translating JavaScript names into a supposed native project.

  5. Build the environment and reachable objective

    Start with the fixed stepped course and six-crystal objective. Use visible landing zones and a clear finish landmark. For a 3D tower, greybox one landing sequence at player scale before building decorative moving gears.

  6. Implement movement and camera behaviour

    Acceleration, variable-height jump, coyote time and buffering support predictable landings. Tune run speed together with gap/ledge height. For 3D, test camera-relative movement, camera obstruction, air control and moving-platform carry separately; a new mesh does not implement these systems.

    Clockwork Heights actual tutorial progress state
    Actual original rules and renderer after scripted input. Concept art is separate.
  7. Add the main gameplay rule: Precision jumps and collectible objectives

    The beacon requires six accepted crystals as well as arrival. Each crystal awards once, and a failed attempt at the beacon leaves the run active so the player can backtrack. Keep visual effects separate from the collection and completion owner.

  8. Add enemies or hazards without duplicate damage

    The reference uses stationary red hazards, not enemy patrol AI. Damage consumes one life and restores a safe checkpoint while retaining collected crystals. Add one telegraphed clockwork obstacle before adding bosses or advanced platform motion.

  9. Connect menus and desktop/mobile controls

    Use real Start, Pause/Resume and Restart buttons. The reference uses keyboard and multi-pointer touch controls with cancellation/release cleanup. Tab/window leave pauses; resuming is explicit. Keep readable status outside Canvas and verify actual keyboard, touch, focus and mobile layout on the published target.

  10. Add animations and bounded visual effects

    The native Canvas renderer draws original geometry from state; it does not implement the generated concept art. Add a compatible free sprite or 3D rig only in its matching runtime. Inspect exact clips and retargeting, keep root motion and controller ownership consistent, cap effects and provide a low-motion/low-effects option. No included commercial audio or soundtrack is implied.

  11. Save only validated progression where appropriate

    A validated local best uses version1, finite bounded time and bounded crystal count. Each game uses its own storage key. Restart makes a fresh run. A later campaign requires known tower/objective IDs and explicit migration; local records are not trusted online scores.

  12. Test the complete outcome and boundaries

    Run node check.mjs. Ten source checks cover the complete route at four update rates, bounded boost, one-use pickups, checkpoint damage, six-crystal completion, pause, timeout and save validation. The source frames execute the actual renderer. Browser input, real phone performance, clipboard/audio and independently generated AI output need separate acceptance; simulation does not prove them.

  13. Publish a playable build and improve one system

    Upload every Clockwork Heights file to static HTTPS preserving paths. Check the published module MIME types, first load, actual controls, win/loss, tab pause and two restarts. Check denied or corrupt local storage. Then use one upgrade prompt. The complete AI brief defines an ambitious fuller game; it does not assert those future systems have already shipped in this small reference.

Complete original code and download

Download complete MIT source ZIP · Run, test and publish instructions · MIT licence

index.html — complete sourceOpen this file
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Clockwork Heights — original exploration-platformer example</title><link rel="stylesheet" href="game.css"><script type="module" src="main.mjs"></script></head><body><main><a href="/guides/super-mario-64-ghostship-build-platformer">← Tutorial and complete source</a><h1>Clockwork Heights</h1><p>Original 2D tutorial game. Collect at least six original repair crystals, jump over hazards and reach the beacon. Concept artwork in the guide shows a possible future art direction.</p><canvas id="game" width="960" height="480" tabindex="0" aria-label="Clockwork Heights game. A D or arrows move, Space jumps, Shift boosts."></canvas><p id="status" role="status" aria-live="polite">Ready. Press Start.</p><p id="hud">Lives 3 · Energy 100 · Cells 0 · Time 0</p><div class="menu"><button id="start">Start / Resume</button><button id="pause">Pause</button><button id="restart">Restart</button></div><div class="controls" aria-label="Touch controls"><button data-key="left" aria-label="Hold to move left">◀</button><button data-key="right" aria-label="Hold to move right">▶</button><button data-key="jump">JUMP</button><button data-key="boost">BOOST</button></div><label><input id="sound" type="checkbox"> Enable short sound effects</label><p>A/D or arrows · Space to jump · Shift to boost · P to pause. Leaving the tab pauses the game. Restart makes a fresh run; your local best is separate.</p><p id="best">No saved local best yet.</p><p><a href="README.md">Run, test and publish this example</a> · <a href="LICENSE.txt">MIT licence</a></p></main></body></html>
world.mjs — complete sourceOpen this file
// Original, independently written public tutorial. MIT, 2026 BINX Forge.
export const WIDTH=960,HEIGHT=480,GOAL=2260;
export const platforms=[{x:0,y:404,w:620,h:76},{x:620,y:372,w:480,h:108},{x:1100,y:404,w:440,h:76},{x:1540,y:350,w:450,h:130},{x:1990,y:404,w:410,h:76}];
export const hazards=[{x:440,y:380,w:34,h:24},{x:930,y:348,w:34,h:24},{x:1430,y:380,w:34,h:24},{x:1810,y:326,w:34,h:24}];
const overlap=(a,b)=>a.x<b.x+b.w&&a.x+a.w>b.x&&a.y<b.y+b.h&&a.y+a.h>b.y;
export function fresh(){return {status:'ready',time:0,lives:3,energy:100,cells:0,player:{x:70,y:368,w:24,h:36,vx:0,vy:0,grounded:true},checkpoint:70,collected:[],camera:0,coyote:.1,buffer:0,jumpHeld:false,immune:0,message:'Reach the repair beacon. Jump over red drones; collect teal cells.'};}
export function start(s){if(s.status==='ready'||s.status==='paused')s.status='running';}
export function pause(s){if(s.status==='running'){s.status='paused';s.jumpHeld=false;s.buffer=0;}}
export function damage(s){if(s.status!=='running'||s.immune>0)return;s.lives--;if(s.lives<=0){s.status='lost';s.message='Out of lives. Restart the route.';return;}const p=s.player;p.x=s.checkpoint;p.y=s.checkpoint<1000?368:368;p.vx=p.vy=0;p.grounded=false;s.immune=1.4;s.energy=Math.max(s.energy,35);s.message='Checkpoint recovered. Your collected cells are safe.';}
function tick(s,input,dt){
 const p=s.player;s.time+=dt;if(s.time>=60){s.time=60;s.status='lost';s.message='Time expired. Try a cleaner route.';return;}
 s.immune=Math.max(0,s.immune-dt);s.buffer=Math.max(0,s.buffer-dt);s.coyote=p.grounded?.1:Math.max(0,s.coyote-dt);
 const dir=Number(!!input.right)-Number(!!input.left),boost=!!input.boost&&dir!==0&&s.energy>0;
 s.energy=Math.max(0,Math.min(100,s.energy+(boost?-38:16)*dt));
 const target=dir*(boost?390:240),rate=dir?1400:1700;p.vx+=Math.max(-rate*dt,Math.min(rate*dt,target-p.vx));
 if(s.buffer>0&&s.coyote>0){p.vy=-570;p.grounded=false;s.coyote=0;s.buffer=0;}
 if(!input.jump&&p.vy<-260)p.vy=-260;
 p.vy=Math.min(820,p.vy+1500*dt);const oldBottom=p.y+p.h;
 p.x=Math.max(0,Math.min(2370,p.x+p.vx*dt));
 for(const q of platforms){if(overlap(p,q)){if(p.vx>0)p.x=q.x-p.w;else if(p.vx<0)p.x=q.x+q.w;p.vx=0;}}
 p.y+=p.vy*dt;p.grounded=false;
 for(const q of platforms){if(overlap(p,q)){if(p.vy>=0&&oldBottom<=q.y+2){p.y=q.y-p.h;p.vy=0;p.grounded=true;}else if(p.vy<0){p.y=q.y+q.h;p.vy=0;}}}
 for(let i=0;i<12;i++){const c={x:200+i*165,y:(i>=3&&i<=5?280:i>=9&&i<=10?260:316),w:20,h:20};if(!s.collected.includes(i)&&overlap(p,c)){s.collected.push(i);s.cells++;s.energy=Math.min(100,s.energy+24);}}
 if(p.x>=1140&&p.grounded)s.checkpoint=1140;
 if(p.y>HEIGHT+100||hazards.some(h=>overlap(p,h)))damage(s);
 if(p.x>=GOAL&&s.cells>=6&&s.status==='running'){s.status='won';s.message='Repairs complete! '+s.cells+' energy cells, '+s.time.toFixed(2)+' seconds.';}
 if(p.x>=GOAL&&s.cells<6&&s.status==='running')s.message='Collect six crystals before the beacon can be restored. Backtrack safely.';
 s.camera=Math.max(0,Math.min(1440,p.x-280));
}
export function advance(s,input={},elapsed=0){if(s.status!=='running'||!Number.isFinite(elapsed)||elapsed<=0)return;const rising=!!input.jump&&!s.jumpHeld;s.jumpHeld=!!input.jump;if(rising)s.buffer=.13;let left=Math.min(elapsed,.1);for(let i=0;i<12&&left>1e-9&&s.status==='running';i++){const dt=Math.min(left,1/120);tick(s,input,dt);left-=dt;}}
export function readBest(raw){try{const s=JSON.parse(raw);return s?.version===1&&Number.isFinite(s.best)&&s.best>0&&s.best<=60&&Number.isInteger(s.cells)&&s.cells>=0&&s.cells<=12?{version:1,best:s.best,cells:s.cells}:null;}catch{return null;}}
render.mjs — complete sourceOpen this file
import {WIDTH,HEIGHT,platforms,hazards,GOAL} from './world.mjs';
export function render(ctx,s,{reduced=false}={}){
 ctx.clearRect(0,0,WIDTH,HEIGHT);const bg=ctx.createLinearGradient(0,0,0,HEIGHT);bg.addColorStop(0,'#453f38');bg.addColorStop(1,'#82704a');ctx.fillStyle=bg;ctx.fillRect(0,0,WIDTH,HEIGHT);
 for(let i=0;i<8;i++){const x=i*180-s.camera*.22;ctx.fillStyle=i%2?'#215364':'#296577';ctx.beginPath();ctx.moveTo(x,420);ctx.lineTo(x+90,170+(i%3)*38);ctx.lineTo(x+190,420);ctx.fill();}
 ctx.save();ctx.translate(-s.camera,0);
 for(const q of platforms){ctx.fillStyle='#173840';ctx.fillRect(q.x,q.y,q.w,q.h);ctx.fillStyle='#b9a36c';ctx.fillRect(q.x,q.y,q.w,10);for(let i=0;i<q.w;i+=50){ctx.fillStyle='#244b51';ctx.fillRect(q.x+i+12,q.y+30,25,28);}}
 for(let i=0;i<12;i++){if(s.collected.includes(i))continue;const x=210+i*165,y=(i>=3&&i<=5?290:i>=9&&i<=10?270:326);ctx.fillStyle='#f9cf7e';ctx.beginPath();for(let j=0;j<6;j++){const a=j*Math.PI/3;ctx.lineTo(x+12*Math.cos(a),y+12*Math.sin(a));}ctx.closePath();ctx.fill();}
 for(const h of hazards){ctx.fillStyle='#fd7977';ctx.fillRect(h.x,h.y,h.w,h.h);ctx.fillStyle='#271e35';ctx.fillRect(h.x+5,h.y+7,7,7);ctx.fillRect(h.x+22,h.y+7,7,7);}
 ctx.fillStyle='#fbc86e';ctx.fillRect(1140,318,6,86);ctx.fillRect(1146,318,50,26);ctx.fillStyle='#83ffdf';ctx.fillRect(GOAL+20,280,8,124);ctx.beginPath();ctx.arc(GOAL+24,272,24,0,Math.PI*2);ctx.fill();
 const p=s.player,phase=reduced?0:Math.sin(s.time*22)*(p.grounded?Math.min(1,Math.abs(p.vx)/260):.3);ctx.save();ctx.translate(p.x+p.w/2,p.y+p.h/2);if(s.immune>0&&!reduced&&Math.floor(s.time*12)%2)ctx.globalAlpha=.45;
 ctx.fillStyle='#ffb958';ctx.fillRect(-9,-6,18,21);ctx.fillStyle='#adbdc5';ctx.fillRect(-7,-19,14,14);ctx.fillStyle='#1d2933';ctx.fillRect(-8,-20,17,5);ctx.fillStyle='#ff754b';ctx.fillRect(-10,-4,25,5);ctx.fillRect(-22,-4+(reduced?0:phase*2),18,4);ctx.fillStyle='#6bffe8';ctx.fillRect(-9,14,7,7+phase*4);ctx.fillRect(3,14,7,7-phase*4);ctx.restore();ctx.restore();
 ctx.fillStyle='rgba(5,20,29,.85)';ctx.fillRect(18,18,325,70);ctx.fillStyle='#e5fff7';ctx.font='bold 18px sans-serif';ctx.fillText('CLOCKWORK HEIGHTS',32,44);ctx.font='14px sans-serif';ctx.fillText('Energy '+Math.round(s.energy)+' • Cells '+s.cells+' • Lives '+s.lives,32,72);
 if(s.status!=='running'){ctx.fillStyle='rgba(3,15,24,.72)';ctx.fillRect(0,HEIGHT/2-42,WIDTH,84);ctx.fillStyle='#fff5dd';ctx.textAlign='center';ctx.font='bold 25px sans-serif';ctx.fillText(s.status==='ready'?'Ready for a wind-run?':s.status==='paused'?'Paused':s.status==='won'?'Repairs complete!':'Try again',WIDTH/2,HEIGHT/2+8);ctx.textAlign='left';}
}
main.mjs — complete sourceOpen this file
import {fresh,start,pause,advance,readBest} from './world.mjs';
import {render} from './render.mjs';
const canvas=document.getElementById('game'),ctx=canvas.getContext('2d'),status=document.getElementById('status'),hud=document.getElementById('hud'),bestNode=document.getElementById('best'),sound=document.getElementById('sound'),motion=matchMedia('(prefers-reduced-motion: reduce)');
let state=fresh(),last=0,audio=null,saved=false;const keyboard=new Set(),pointers=new Map(),keyMap={ArrowLeft:'left',KeyA:'left',ArrowRight:'right',KeyD:'right',Space:'jump',ShiftLeft:'boost',ShiftRight:'boost'},saveKey='forge.clockwork.best.v1';
let best=null;try{best=readBest(localStorage.getItem(saveKey));}catch{}
function showBest(){bestNode.textContent=best?'Local best: '+best.best.toFixed(2)+'s · '+best.cells+' cells. Stored only in this browser.':'No saved local best yet.';}showBest();
function clear(){keyboard.clear();pointers.clear();state.jumpHeld=false;state.buffer=0;}
function message(){status.textContent=state.message;}
function tone(){if(!sound.checked)return;try{audio??=new AudioContext();if(audio.state==='suspended')return;const o=audio.createOscillator(),g=audio.createGain();o.frequency.value=680;g.gain.setValueAtTime(.035,audio.currentTime);g.gain.exponentialRampToValueAtTime(.0001,audio.currentTime+.07);o.connect(g).connect(audio.destination);o.start();o.stop(audio.currentTime+.08);o.onended=()=>{o.disconnect();g.disconnect();};}catch{sound.checked=false;}}
sound.addEventListener('change',async()=>{if(sound.checked){try{audio??=new AudioContext();await audio.resume();tone();}catch{sound.checked=false;}}});
document.getElementById('start').addEventListener('click',()=>{clear();start(state);state.message='Collect six crystals and reach the beacon. Jump over red hazards.';message();canvas.focus();});
document.getElementById('pause').addEventListener('click',()=>{pause(state);clear();state.message='Paused. Press Resume.';message();});
document.getElementById('restart').addEventListener('click',()=>{clear();state=fresh();start(state);saved=false;message();canvas.focus();});
canvas.addEventListener('keydown',e=>{if(keyMap[e.code]){e.preventDefault();keyboard.add(keyMap[e.code]);}if(e.code==='KeyP'&&!e.repeat){pause(state);clear();state.message='Paused. Press Resume.';message();}});
window.addEventListener('keyup',e=>{if(keyMap[e.code])keyboard.delete(keyMap[e.code]);});
canvas.addEventListener('blur',()=>{keyboard.clear();state.jumpHeld=false;state.buffer=0;});
for(const b of document.querySelectorAll('[data-key]')){b.addEventListener('pointerdown',e=>{e.preventDefault();b.setPointerCapture(e.pointerId);pointers.set(e.pointerId,b.dataset.key);});for(const name of ['pointerup','pointercancel','lostpointercapture'])b.addEventListener(name,e=>pointers.delete(e.pointerId));}
function hidden(){if(document.hidden){clear();pause(state);state.message='Paused while away. Press Resume.';message();}}
document.addEventListener('visibilitychange',hidden);window.addEventListener('blur',()=>{clear();pause(state);message();});window.addEventListener('pagehide',()=>{clear();pause(state);audio?.suspend();});
function frame(now){const dt=last?(now-last)/1000:0;last=now;const input=Object.fromEntries([...keyboard,...pointers.values()].map(k=>[k,true])),cells=state.cells,phase=state.status;advance(state,input,dt);if(state.cells>cells)tone();if(phase!==state.status)message();render(ctx,state,{reduced:motion.matches});hud.textContent='Lives '+state.lives+' · Energy '+Math.round(state.energy)+' · Cells '+state.cells+' · Time '+state.time.toFixed(1)+' / 60s';
 if(state.status==='won'&&!saved){saved=true;if(!best||state.time<best.best){const record={version:1,best:state.time,cells:state.cells};try{localStorage.setItem(saveKey,JSON.stringify(record));best=record;showBest();}catch{bestNode.textContent='Run complete; local storage is unavailable.';}}}requestAnimationFrame(frame);}
message();requestAnimationFrame(frame);
game.css — complete sourceOpen this file
:root{color-scheme:dark;font-family:system-ui,sans-serif;background:#071b25;color:#e0f8f3}body{margin:0}main{max-width:1000px;margin:auto;padding:20px}a{color:#82ffe2}canvas{width:100%;height:auto;display:block;border:1px solid #4b7780;border-radius:16px;outline-offset:4px}button{border:1px solid #77cab6;border-radius:100px;min-width:64px;min-height:52px;background:#163b43;color:#effff8;font:700 14px system-ui;padding:10px 16px;cursor:pointer}button:focus-visible,a:focus-visible{outline:3px solid #ffd578;outline-offset:4px}.menu,.controls{display:flex;gap:10px;flex-wrap:wrap;margin:15px 0}.controls button{touch-action:none;user-select:none}.controls{justify-content:center}.controls button[data-key=jump],.controls button[data-key=boost]{background:#37504a}p{line-height:1.6}#hud{font-variant-numeric:tabular-nums}@media(max-width:500px){main{padding:12px}h1{font-size:26px}.controls{gap:6px}button{padding:8px 12px;min-width:52px}}@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto}}
README.md — complete sourceOpen this file
# Clockwork Heights 1.0

Original MIT exploration-platformer rules, adapted from the independently written public Skycoil Sprint source. No commercial game code or assets. Collect at least six repair crystals and reach the beacon.

# Clockwork Heights

Original independent MIT browser tutorial. No private BINX Engine code, third-party game source or purchased assets.

Download all eight files (including this README and check.mjs), keeping them together. Serve this folder with any local static HTTP server supporting .mjs as JavaScript; for example, if Python 3 is installed, run `python -m http.server 8080`, then open http://localhost:8080/index.html. Opening index.html as file:// does not load modules consistently. Python is only an optional server; the game has no Python dependency.

Run the actual rules checks with Node 24.19.0 or compatible recent Node: `node check.mjs`.

Controls: A/D or arrows, Space jump, Shift boost. Touch hold buttons are provided. Desktop controls require focus on the canvas. Start/Resume restores focus. One 2400px connected course, jump buffering/coyote time, bounded acceleration, boost energy, pickups, four stationary hazard drones, checkpoint recovery, three lives, 60-second outcome, pause/restart, optional short generated tones and validated browser-local best-time record.

Publish the whole folder on a static HTTPS host with MIME support for .mjs. GitHub Pages instructions: https://docs.github.com/en/pages/getting-started-with-github-pages/creating-a-github-pages-site . Check the exact public URL, keyboard and real phone touch, sound opt-in, tab/focus changes, blocked storage, loss/win and two restarts. Simulation/source-rendered frames do not certify browser input, phone, audio or assistive acceptance.

The game renders its own geometric artwork. The guide's AI concept illustration is a proposed higher-fidelity direction, not this game's screenshot or a downloadable art pack. Stationary hazard drones are obstacles, not pathfinding enemy AI or combat. See the guide's separate ambitious build and upgrade prompts for those systems. No multiplayer, cloud save, 3D exporter or franchise recreation.

This is a complete 2D side-view mechanics reference, not a native 3D project. The concept art, 3D follow camera, moving platforms, richer world and adventure systems are later milestones. Keep independent source notices.
LICENSE.txt — complete sourceOpen this file
MIT License

Copyright (c) 2026 BINX Forge

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
check.mjs — complete sourceOpen this file
import assert from 'node:assert/strict';
import {fresh,start,pause,advance,damage,readBest,GOAL} from './world.mjs';
let passed=0;function check(name,fn){fn();passed++;console.log('PASS '+name);}
function drive(rate){const s=fresh();start(s);let held=0;for(let i=0;i<rate*60+1&&s.status==='running';i++){const x=s.player.x,near=[440,620,930,1430,1540,1810].some(a=>a-x>0&&a-x<85);if(s.player.grounded&&near&&held<=0)held=.18;advance(s,{right:true,jump:held>0},1/rate);held-=1/rate;}return s;}
check('actual route wins at 15/30/60/120 simulated updates',()=>{for(const rate of [15,30,60,120]){const s=drive(rate);assert.equal(s.status,'won');assert.ok(s.player.x>=GOAL);assert.equal(s.lives,3);assert.ok(s.cells>=6);assert.ok(s.time<10);}});
check('invalid elapsed time cannot mutate a run; long stalls are capped',()=>{const s=fresh();start(s);const old=JSON.stringify(s);for(const t of [NaN,Infinity,-1,0])advance(s,{right:true},t);assert.equal(JSON.stringify(s),old);advance(s,{right:true},9);assert.ok(s.time<=.100001);assert.ok(s.player.x<90);});
check('boost drains bounded energy and raises movement speed',()=>{const a=fresh(),b=fresh();start(a);start(b);for(let i=0;i<30;i++){advance(a,{right:true},1/120);advance(b,{right:true,boost:true},1/120);}assert.ok(b.player.x>a.player.x);assert.ok(b.energy<a.energy);b.energy=0;advance(b,{right:true,boost:true},.1);assert.ok(b.energy>=0&&b.energy<=100);});
check('jump button hold does not repeatedly jump in midair',()=>{const s=fresh();start(s);advance(s,{jump:true},.05);const before=s.player.vy;advance(s,{jump:true},.05);assert.ok(s.player.vy>before);assert.ok(!s.player.grounded);});
check('pickups award once even after reentering the same cell',()=>{const s=fresh();start(s);s.player.x=200;s.player.y=310;advance(s,{},1/120);assert.equal(s.cells,1);s.player.x=200;s.player.y=310;advance(s,{},1/120);assert.equal(s.cells,1);});
check('damage recovers checkpoint once and preserves collected cells',()=>{const s=fresh();start(s);s.checkpoint=1140;s.cells=2;s.collected=[1,2];damage(s);assert.equal(s.lives,2);assert.equal(s.player.x,1140);assert.equal(s.cells,2);damage(s);assert.equal(s.lives,2);s.immune=0;damage(s);s.immune=0;damage(s);assert.equal(s.status,'lost');});
check('pause, win and loss freeze simulation and restart is independent',()=>{for(const mode of ['paused','won','lost']){const s=fresh();s.status=mode;const old=JSON.stringify(s);advance(s,{right:true,jump:true,boost:true},.1);assert.equal(JSON.stringify(s),old);}const a=drive(60),b=fresh();assert.equal(b.cells,0);assert.equal(b.lives,3);assert.notEqual(a.player,b.player);start(b);pause(b);assert.equal(b.status,'paused');});
check('timeout ends exactly at sixty simulated seconds',()=>{const s=fresh();start(s);s.time=59.99;advance(s,{},.1);assert.equal(s.time,60);assert.equal(s.status,'lost');});
check('local best accepts only versioned bounded values',()=>{assert.deepEqual(readBest('{"version":1,"best":8.8,"cells":9}'),{version:1,best:8.8,cells:9});for(const raw of ['',null,'{}','{"version":2,"best":8,"cells":2}','{"version":1,"best":999,"cells":1}','{"version":1,"best":8,"cells":13}','{"version":1,"best":0,"cells":0}'])assert.equal(readBest(raw),null);});
check('beacon requires six accepted crystals',()=>{const s=fresh();start(s);s.player.x=GOAL;advance(s,{},1/120);assert.equal(s.status,'running');s.cells=6;s.collected=[0,1,2,3,4,5];advance(s,{},1/120);assert.equal(s.status,'won');});
console.log(passed+' rules checks passed; browser/phone/audio/clipboard acceptance is separate.');

Free vs paid resources

Free firstWhat it contributesLicence / compatibility
Godot
Godot Engine contributors
Free, open-source game editor for 2D and 3D projects, with scene, animation and interface tools.MIT · Creator source ↗
Import one compatible file; art is separate from rules.
UI Pack
Kenney
Interface artwork for buttons, panels and sliders.CC0-1.0 · Creator source ↗
Import one compatible file; art is separate from rules.
KayKit Adventurers
Kay Lousberg
Stylised fantasy characters with weapons and basic movement animation.CC0-1.0 · Creator source ↗
Import one compatible file; art is separate from rules.
Universal Animation Library
Quaternius
Humanoid animation library with a free subset and expanded paid editions.CC0-1.0 · Creator source ↗
Import one compatible file; art is separate from rules.

Free source code, artwork, engine licences and commercial game files are separate. Check permissions to sell a finished game, resell files and include them in source/template products. An AI opinion is not licence clearance.

YOUR ORIGINAL GAME

COPY TO MAKE GAME

Paste the complete development brief into your AI. It includes the working source, verified resource facts, milestones and target tests. Review it and adapt the identity to your own idea.

Select and copy the text manually if clipboard access is unavailable.

Review the complete game-making prompt
Customise in the existing game builder

Full article, prompts and source as AI-readable Markdown →

MAKE YOUR GAME EVEN BETTER

Beginner: Readable landings and original animations

UI Pack · Universal Animation Library

Review or select the upgrade text.

Intermediate: A second connected area and traversal tool

Godot · KayKit Adventurers · UI Pack

Review or select the upgrade text.

Advanced: 3D camera, moving terrain and bounded streaming

Godot · Universal Animation Library · KayKit Adventurers

Review or select the upgrade text.

Questions before you start

Is this an AI Super Mario 64 remake or a commercial game download?

No. The original project is a separately credited PC port. Our example and AI prompt create Clockwork Heights, an independent game with its own identity.

Can ChatGPT, Claude or Codex build the full game?

Use an AI tool that can edit and run your chosen project, work through the milestones and review its output. A copied prompt alone is not a tested finished game. Follow the source and licence checks even when the AI sounds confident.

Why free code before paid assets?

A working controller, outcome and restart reveal what the game actually needs. Buy an optional resource only when its files, compatibility and rights solve that need.

More games to build

Sources and creator credit

Project facts checked 2026-10-11. Resource editions carry their own checked dates. No measured search volume, ranking promise or independent AI-output acceptance is claimed. Lywx (KiritoDv), lead developer, with the Harbour Masters team and credited contributors owns the featured project; no endorsement is implied. Corrections and review policy ↗