BINX FORGEALL YOU NEED IS AN IDEA.Support BINX ↗
REVERSE ENGINEERING · ORIGINAL SOURCE INCLUDED

Measure a Platformer Jump: Height, Airtime and Gravity

Use a deterministic movement trace to distinguish observations from a physics hypothesis.

Actual Beacon Hop gameplay: a playable BINX reference
Beacon Hop · Actual gameplay · Related playable reference

Thumbnail: an actual related playable BINX demo. It is a gameplay reference, not evidence that a save, inventory, network or native reverse-engineering integration has been demonstrated.

Difficulty: beginner to intermediate. Prerequisites: basic variables, functions and a test copy of your project. Reference: Forge workshop 1.0, browser ES modules and Node 24 checks. Engine-specific translation is a separate integration.

What you will learn

Use a deterministic movement trace to distinguish observations from a physics hypothesis.

Download complete MIT workshop
  1. Extract into a new folder and run node check.mjs from that folder.
  2. For the browser games, run python3 -m http.server 8080 with Python 3 and open http://localhost:8080/index.html. Do not open modules with file://.
  3. Read the full setup instructions and the original code licence. Keep your existing game on a separate test branch.

The JavaScript behaviour checks and native C comparison can run independently of the browser. Ghidra UI, physical-phone and your engine integration are separate checks. This is a small reference, not a certification of your project.

Explore the related game idea · Start with Build a Game · Improve your existing game

Five practical steps

Measure a Platformer Jump: Height, Airtime and Gravity: Record a controlled jump → Estimate before inspecting → Separate camera and player
Original implementation diagram · not gameplay or a tool screenshot
  1. Record a controlled jump

    Use jumpTrace in systems.mjs. It starts at y zero, gives upward velocity -300 and applies gravity 900 at 120Hz. Screen y increases downward. Record time, position and velocity; a video alone may mix camera motion with player motion.

    Expected result: A trace in seconds, pixels and pixels/second.

    Check it: The initial velocity is negative and subsequent gravity increases it toward zero.

    jumpTraceObserve the inputs → check the state → compare the result
  2. Estimate before inspecting

    For constant acceleration, the continuous model predicts height v²/(2g)=50 pixels and airtime 2v/g≈0.667 seconds. A discrete semi-implicit update will differ slightly. Use these predictions as a testable approximation, not proof of the implementation.

    Expected result: An explicit model and tolerances.

    Check it: Run the trace and compare peak and landing time to the predicted values; preserve the timestep in the report.

  3. Separate camera and player

    When measuring a permitted game capture, choose a fixed reference or recover world coordinates from legitimate debug output. Note whether jump release, collisions, acceleration curves or animation offsets change the observed trajectory. Repeat the same input duration.

    Expected result: Comparable samples rather than a guessed constant from one frame.

    Check it: Record held and quickly released jumps separately; different peaks suggest another rule.

  4. Reconstruct one model

    Write an original constant-gravity jump and compare every sampled position to the reference. Then change only gravity or starting speed. If the original has short-hop release or terminal speed, document the gap before adding that rule.

    Expected result: A model with a stated error and known scope.

    Check it: Halving the timestep should reduce integration error; changing gravity should change airtime in the predicted direction.

  5. Turn the study into your own controls

    Choose a target height and time-to-peak for your original game, then solve gravity=2h/t² and speed=2h/t. Test on the actual level and input devices. Similar general mechanics do not grant rights to another game’s characters, code or assets.

    Expected result: Movement tuned to an explicit design goal.

    Check it: Check ceiling hits, landing, coyote time, jump buffering and repeated presses before calling the controller complete.

Read and reuse the actual code

systems.mjs: complete source · Standalone behavioural checks · Shared browser runner and input. Original BINX Forge code, MIT; the package includes every required file and its notice.

Inspect complete systems.mjs
// Original BINX Forge practice code. MIT; see LICENSE.txt.
export function readSave(raw) {
  const s = JSON.parse(raw);
  if (!s || s.version !== 1 || !Number.isInteger(s.coins) || s.coins < 0 || s.coins > 9999 || !['room-a','room-b'].includes(s.room)) throw Error('Invalid save');
  return {version:1, coins:s.coins, room:s.room};
}
export function transfer(from, to, id, count, capacity=10) {
  if (!Number.isInteger(count) || count < 1 || !Number.isInteger(from[id]) || from[id] < count || Object.values(to).reduce((a,b)=>a+b,0)+count > capacity) return false;
  from[id]-=count; to[id]=(to[id]||0)+count; return true;
}
export function pointerInput() {
  const owners=new Map();
  return {press:(id,action)=>owners.set(id,action),release:id=>owners.delete(id),clear:()=>owners.clear(),held:action=>[...owners.values()].includes(action)};
}
export function enemyMode(distance, hp, cooldown) {
  if (hp<=0) return 'dead';
  if (cooldown>0) return 'recover';
  if (distance<24) return 'attack';
  return distance<180?'chase':'idle';
}
export function frameSummary(samples) {
  const s=samples.filter(Number.isFinite).filter(x=>x>=0).sort((a,b)=>a-b);
  if (!s.length) throw Error('No samples');
  return {median:s[Math.floor((s.length-1)*.5)],p95:s[Math.ceil(s.length*.95)-1],count:s.length};
}
export function fixedStep(clock, elapsed, update) {
  clock.carry+=Math.max(0,Math.min(.1,elapsed));
  while(clock.carry>=1/60){update(1/60);clock.carry-=1/60;}
}
// Owned protocol specimen: version:u8, coins:u16 little-endian, room:u8.
export function decodeRecord(bytes) {
  if(bytes.length!==4)throw Error('Expected four bytes');
  const v=new DataView(bytes.buffer,bytes.byteOffset,bytes.byteLength);
  if(v.getUint8(0)!==1||v.getUint8(3)>1)throw Error('Unknown record');
  return {version:1,coins:v.getUint16(1,true),room:v.getUint8(3)};
}
export function applyInput(player, packet) {
  if(!packet||!Number.isInteger(packet.seq)||packet.seq<=player.seq||![-1,0,1].includes(packet.dx))return false;
  player.seq=packet.seq;player.x=Math.max(0,Math.min(100,player.x+packet.dx*2));return true;
}
export function jumpTrace(speed=300,gravity=900,dt=1/120) {
  let y=0,vy=-speed,t=0,peak=0;
  const rows=[{t,y,vy}];
  while(t<3){vy+=gravity*dt;y+=vy*dt;t+=dt;peak=Math.min(peak,y);rows.push({t,y,vy});if(y>=0)break;}
  return {rows,height:-peak,airtime:t};
}

Code rights: the included MIT notice permits use, modification and distribution, including commercial games and source products, with the copyright and licence notice. Added third-party files have their own terms. Read the official licence & usage terms.

Common failures and fixes

The estimate changes with frame rate

Measure real time and record update dt; counting frames alone assumes a refresh rate.

The camera hides the apex

Track a fixed reference or world coordinates, not screen position alone.

The formula does not match

List variable gravity, release rules and integration error as hypotheses; test each separately.

Make Your Game Better

Change one system after the baseline works. Keep the free reference and compare the same inputs before and after.

Licensing summary, not legal advice. Before publishing or selling, check exact terms for finished-game use, reselling files and including files in a source/template product separately.

Learn at the original sources

Sources checked 11 October 2026. The numbered plan is original Forge instruction; linked documentation does not imply every engine or device has been tested.

Take this guide to your AI

Review and copy into your assistant. Nothing is sent automatically. These prompts include the complete focus source, full-package links, checks and compatibility limits.

Review a prompt or select its text manually.

Review build prompt
Review debug prompt
Review upgrade prompt

Read the complete guide and prompts as Markdown →

Keep learning

Original reverse-engineering practice lab · Sonic Unleashed creator-project study · SpaghettiKart creator-project study

Browse every guide and recipe →