Instructions to use ahpah/YokoCoder-4B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use ahpah/YokoCoder-4B with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf ahpah/YokoCoder-4B:Q4_K_M # Run inference directly in the terminal: llama cli -hf ahpah/YokoCoder-4B:Q4_K_M
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf ahpah/YokoCoder-4B:Q4_K_M # Run inference directly in the terminal: llama cli -hf ahpah/YokoCoder-4B:Q4_K_M
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf ahpah/YokoCoder-4B:Q4_K_M # Run inference directly in the terminal: ./build/bin/llama cli -hf ahpah/YokoCoder-4B:Q4_K_M
Use Docker
docker model run hf.co/ahpah/YokoCoder-4B:Q4_K_M
- Llama new
- LM Studio
- Jan
- vLLM
How to use ahpah/YokoCoder-4B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "ahpah/YokoCoder-4B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "ahpah/YokoCoder-4B", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/ahpah/YokoCoder-4B:Q4_K_M
- Ollama
How to use ahpah/YokoCoder-4B with Ollama:
ollama run hf.co/ahpah/YokoCoder-4B:Q4_K_M
- Unsloth Desktop
- Pi
How to use ahpah/YokoCoder-4B with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ahpah/YokoCoder-4B:Q4_K_M
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "ahpah/YokoCoder-4B:Q4_K_M" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use ahpah/YokoCoder-4B with Docker Model Runner:
docker model run hf.co/ahpah/YokoCoder-4B:Q4_K_M
- Lemonade
How to use ahpah/YokoCoder-4B with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull ahpah/YokoCoder-4B:Q4_K_M
Run and chat with the model
lemonade run user.YokoCoder-4B-Q4_K_M
List all available models
lemonade list
- Hermes Agent
How to use ahpah/YokoCoder-4B with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ahpah/YokoCoder-4B:Q4_K_M
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default ahpah/YokoCoder-4B:Q4_K_M
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use ahpah/YokoCoder-4B with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf ahpah/YokoCoder-4B:Q4_K_M
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "ahpah/YokoCoder-4B:Q4_K_M" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
|
Download HTML_CSS_JS_AND_THREEJS_GAMEDEV_GUIDE.md from ahpah/YokoCoder-4B: direct link, hf CLI and curl.
- Browser
- Download file 15.7 kB
-
https://huggingface.co/ahpah/YokoCoder-4B/resolve/main/HTML_CSS_JS_AND_THREEJS_GAMEDEV_GUIDE.md
- Command line
-
hf download hf://ahpah/YokoCoder-4B/HTML_CSS_JS_AND_THREEJS_GAMEDEV_GUIDE.md
-
curl -L -o HTML_CSS_JS_AND_THREEJS_GAMEDEV_GUIDE.md https://huggingface.co/ahpah/YokoCoder-4B/resolve/main/HTML_CSS_JS_AND_THREEJS_GAMEDEV_GUIDE.md
15.7 kB
| # The YokoCoder:4B Master Guide to HTML/CSS/JS (2D Canvas) & Three.js (3D WebGL) Video Game Engineering | |
| This guide serves both as a **reference manual for game developers** and as a **core architectural specification distilled into the `YokoCoder:4B` dataset**. Every pattern below is engineered to eliminate the most common failure modes in browser-based 2D and 3D gamesβsuch as `ReferenceError: dt is not defined`, stacked `requestAnimationFrame` loops, variable-framerate physics drift, hitbox mismatches, and Three.js memory leaks. | |
| --- | |
| ## 1. Single-File HTML/CSS/JS Game Architecture | |
| A production-quality single-file HTML game must be 100% self-contained (zero external image or audio file dependencies that could fail to load via CORS) and strictly ordered into five deterministic layers inside `<script>`: | |
| ```text | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| β 1. CONFIGURATION & CONSTANTS (Immutable tuning parameters, colors) β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ | |
| β 2. RUNTIME STATE & INPUT REGISTRY (Single source of truth, lexical) β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ | |
| β 3. PROCEDURAL ASSETS & WEB AUDIO SYNTH (Lazy AudioContext, sprites) β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ | |
| β 4. PURE UPDATE(dt) & COLLISION SOLVERS (Deterministic math, no DOM) β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ | |
| β 5. RENDER(dt, alpha) & RAF SCHEDULER (Canvas/WebGL draw, single loop)β | |
| ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ``` | |
| ### 1.1 The Responsive Canvas Shell (Smooth Vector vs. Crisp Pixel Art) | |
| Always prevent mobile pinch-zoom, double-tap selection, and Space/Arrow page scrolling: | |
| ```html | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> | |
| <title>YokoCoder Arcade Engine</title> | |
| <style> | |
| *, *::before, *::after { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| user-select: none; | |
| -webkit-user-select: none; | |
| } | |
| html, body { | |
| width: 100%; | |
| height: 100%; | |
| overflow: hidden; | |
| background: #0b0f19; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-family: system-ui, -apple-system, sans-serif; | |
| touch-action: none; | |
| } | |
| canvas { | |
| display: block; | |
| touch-action: none; | |
| box-shadow: 0 20px 50px rgba(0, 0, 0, 0.7); | |
| /* Enable for low-res 8-bit pixel art games: */ | |
| /* image-rendering: pixelated; image-rendering: crisp-edges; */ | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <canvas id="game"></canvas> | |
| <script> | |
| // Game engine code goes here | |
| </script> | |
| </body> | |
| </html> | |
| ``` | |
| ### 1.2 HiDPI Scaling for Vector Games vs. Integer Scaling for Pixel Art | |
| - **Smooth Vector Games (`400x600` logical space)**: | |
| Scale the physical canvas backing store by `dpr = Math.min(window.devicePixelRatio || 1, 2)` and call `ctx.setTransform(dpr, 0, 0, dpr, 0, 0)` so all game logic uses fixed logical coordinates (`W = 400`, `H = 600`) regardless of screen resolution. | |
| - **Native Pixel-Art Games (`144x256` or `160x288` logical buffer)**: | |
| Keep `canvas.width = 144` and `canvas.height = 256`, set `ctx.imageSmoothingEnabled = false`, and scale the CSS width/height by an integer multiplier `scale = Math.max(1, Math.floor(Math.min(window.innerWidth / 144, window.innerHeight / 256)))`. | |
| --- | |
| ## 2. The Golden Game Loop & Why `ReferenceError: dt is not defined` Happens | |
| ### 2.1 Root Cause of `Uncaught ReferenceError: dt is not defined` | |
| One of the most frequent bugs generated by small coding models is computing `const dt = ...` as a block-scoped local variable inside `loop(now)`, and then referencing `dt` inside `draw()` or `update()` **without passing `dt` as a function parameter**: | |
| ```javascript | |
| // β BROKEN: dt is block-scoped inside loop(), so draw() throws ReferenceError! | |
| function draw() { | |
| wingPhase += dt * 10; // π₯ Uncaught ReferenceError: dt is not defined | |
| } | |
| function loop(now) { | |
| const dt = Math.min(0.1, (now - lastTime) / 1000); | |
| lastTime = now; | |
| update(dt); | |
| draw(); // β Forgot to pass dt! | |
| requestAnimationFrame(loop); | |
| } | |
| ``` | |
| ### 2.2 The Invariant Fix: Explicit `update(dt)` and `draw(dt)` Signatures + Fixed-Step Accumulator | |
| To guarantee that `dt` is **never** undefined and physics is **100% identical on 60Hz, 120Hz, 144Hz, and 240Hz monitors**: | |
| 1. Declare timing variables (`lastTime`, `accumulator`, `rafId`) in the module scope before `loop`. | |
| 2. Guard the first frame (`if (!lastTime) lastTime = now;`) so `now - lastTime` is never `NaN` or huge on startup. | |
| 3. Clamp `frameDt = Math.min(0.1, Math.max(0, (now - lastTime) / 1000))` so switching browser tabs never causes physics tunneling. | |
| 4. Step physics in fixed `FIXED_DT = 1 / 120` increments and pass `FIXED_DT` explicitly into `update(dt)` and `frameDt` explicitly into `draw(dt)`. | |
| ```javascript | |
| const FIXED_DT = 1 / 120; | |
| let lastTime = 0; | |
| let accumulator = 0; | |
| let rafId = null; | |
| function update(dt = FIXED_DT) { | |
| // Pure physics & collision using explicit parameter `dt` | |
| } | |
| function draw(dt = FIXED_DT, alpha = 1) { | |
| // Visual animation timers (wing flap, particles, shaders) use explicit `dt` | |
| } | |
| function loop(now = performance.now()) { | |
| rafId = requestAnimationFrame(loop); | |
| if (lastTime === 0) lastTime = now; | |
| const frameDt = Math.min(0.1, Math.max(0, (now - lastTime) / 1000)); | |
| lastTime = now; | |
| accumulator += frameDt; | |
| while (accumulator >= FIXED_DT) { | |
| update(FIXED_DT); | |
| accumulator -= FIXED_DT; | |
| } | |
| draw(frameDt, accumulator / FIXED_DT); | |
| } | |
| // Start the single persistent RAF loop once: | |
| rafId = requestAnimationFrame(loop); | |
| ``` | |
| --- | |
| ## 3. State Machine & Input Discipline | |
| ### 3.1 Never Spawn Duplicate `requestAnimationFrame` Loops on Restart | |
| A classic bug occurs when `startGame()` or `resetGame()` calls `loop()` while a previous `requestAnimationFrame(loop)` is still runningβdoubling or tripling game speed after every death! | |
| **Rule**: Either keep **one persistent `requestAnimationFrame` loop** running across all states (`READY`, `PLAYING`, `GAMEOVER`) and branch on `state` inside `update(dt)`, OR always call `if (rafId !== null) cancelAnimationFrame(rafId);` before scheduling a new frame. | |
| ### 3.2 Time-Based Game-Over Grace Period (Never Use `frames % 10 === 0`!) | |
| Checking `if (frames % 10 === 0)` inside a click/keydown handler to "debounce" restarts drops **90% of user clicks** because input events fire asynchronously relative to frame ticks! Instead, track a time-based cooldown `gameOverLockTimer`: | |
| ```javascript | |
| const STATE = { READY: 'READY', PLAYING: 'PLAYING', GAMEOVER: 'GAMEOVER' }; | |
| let state = STATE.READY; | |
| let gameOverLockTimer = 0; // Seconds remaining before restart input is accepted | |
| function enterGameOver() { | |
| if (state === STATE.GAMEOVER) return; | |
| state = STATE.GAMEOVER; | |
| gameOverLockTimer = 0.35; // 350ms grace period prevents accidental instant skip | |
| bestScore = Math.max(bestScore, score); | |
| saveHighScore(bestScore); | |
| } | |
| function handleAction() { | |
| if (state === STATE.READY) { | |
| resetMatch(); | |
| state = STATE.PLAYING; | |
| bird.flap(); | |
| } else if (state === STATE.PLAYING) { | |
| bird.flap(); | |
| } else if (state === STATE.GAMEOVER && gameOverLockTimer <= 0) { | |
| resetMatch(); | |
| state = STATE.PLAYING; | |
| bird.flap(); | |
| } | |
| } | |
| ``` | |
| --- | |
| ## 4. 2D Collision Detection Mathematics | |
| ### 4.1 AABB vs. AABB (Axis-Aligned Bounding Box) | |
| Two rectangles $A = (x_A, y_A, w_A, h_A)$ and $B = (x_B, y_B, w_B, h_B)$ intersect if and only if projections on both axes overlap: | |
| ```javascript | |
| function aabbOverlap(ax, ay, aw, ah, bx, by, bw, bh) { | |
| return ax < bx + bw && ax + aw > bx && ay < by + bh && ay + ah > by; | |
| } | |
| ``` | |
| ### 4.2 Forgiving Circle-vs-AABB Collision (Ideal for Rotating Sprites & Birds) | |
| When a sprite rotates visually (like the Flappy Bird tilting between $-25^\circ$ and $+90^\circ$), an axis-aligned rectangle has sharp invisible corners that feel unfair to players. A **circle** of center $(c_x, c_y)$ and radius $r$ is invariant under rotation. Clamp $(c_x, c_y)$ to the rectangle $[x, x+w] \times [y, y+h]$ to find the closest point $(p_x, p_y)$: | |
| ```javascript | |
| function circleIntersectsAABB(cx, cy, r, rx, ry, rw, rh) { | |
| const closestX = Math.max(rx, Math.min(cx, rx + rw)); | |
| const closestY = Math.max(ry, Math.min(cy, ry + rh)); | |
| const dx = cx - closestX; | |
| const dy = cy - closestY; | |
| return (dx * dx + dy * dy) < (r * r); | |
| } | |
| ``` | |
| ### 4.3 Preventing the "Fly Over Top Pipe" Bypass Bug | |
| In scrolling obstacle games, if the player flaps near $y = 0$ and the pipe collision check only tests `bird.y < pipe.top` while `bird.y` is allowed to go negative (or if top pipe caps start at $y = 0$), always: | |
| 1. Clamp the player ceiling: `if (bird.y - bird.r < 0) { bird.y = bird.r; bird.vy = 0; }`, **and** | |
| 2. Treat any horizontal overlap with a pipe while `bird.y - bird.r < pipe.gapTop` as a collision, even if `bird.y < 0`. | |
| --- | |
| ## 5. Three.js 3D Game Engineering Guide | |
| ### 5.1 Modern Import Map & Scene Setup | |
| Use ES Module Import Maps or explicit CDN script tags with a locked Three.js version (`0.160.0`) so `THREE` is reliably available without a bundler: | |
| ```html | |
| <script type="importmap"> | |
| { | |
| "imports": { | |
| "three": "https://unpkg.com/three@0.160.0/build/three.module.js", | |
| "three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/" | |
| } | |
| } | |
| </script> | |
| <script type="module"> | |
| import * as THREE from 'three'; | |
| </script> | |
| ``` | |
| ### 5.2 Preventing the Three.js "Black Screen" Bug | |
| Four mistakes cause a blank or black Three.js canvas: | |
| 1. **Using `MeshStandardMaterial` or `MeshPhysicalMaterial` without lights**: PBR materials require at least an ambient/hemisphere light (`THREE.HemisphereLight`) and a directional/point light (`THREE.DirectionalLight`). Only `MeshBasicMaterial` renders without lights. | |
| 2. **Camera inside the geometry or looking the wrong way**: Always set `camera.position.set(x, y, z)` and `camera.lookAt(targetX, targetY, targetZ)` explicitly. | |
| 3. **Zero-height container**: Ensure `html, body { width: 100%; height: 100%; margin: 0; }` and size the renderer via `renderer.setSize(window.innerWidth, window.innerHeight)`. | |
| 4. **Missing `camera.updateProjectionMatrix()` on resize**: | |
| ```javascript | |
| window.addEventListener('resize', () => { | |
| camera.aspect = window.innerWidth / window.innerHeight; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| }); | |
| ``` | |
| ### 5.3 Hierarchical Joint Rigging (`THREE.Group` Pivot Pattern) | |
| By default, Three.js primitives (`BoxGeometry`, `CylinderGeometry`) rotate around their geometric center $(0, 0, 0)$. To animate limbs, wings, or doors around a **joint hinge** (shoulder, hip, wing root): | |
| 1. Create a `const joint = new THREE.Group()` positioned at the hinge coordinates on the parent body. | |
| 2. Create the limb mesh and offset its local position by half its length (`limbMesh.position.y = -limbLength / 2`). | |
| 3. Rotate `joint.rotation.x`βnever the offset child mesh directly! | |
| ### 5.4 Preventing WebGL GPU Memory Leaks (`dispose()` Lifecycle) | |
| Unlike JavaScript objects, Three.js `BufferGeometry`, `Material`, and `Texture` instances allocate GPU buffers in WebGL that are **not** freed by the browser's garbage collector when removed from a `Scene`. | |
| - **Rule 1**: Pre-allocate shared geometries and materials once at startup and reuse them across spawned obstacles, bullets, and particles (`const sharedPipeGeo = new THREE.CylinderGeometry(...)`). | |
| - **Rule 2**: For high-count particles or voxel chunks, use `THREE.InstancedMesh` or merged face buffers. | |
| - **Rule 3**: Whenever a unique mesh is permanently destroyed, dispose its GPU resources if not shared: | |
| ```javascript | |
| function removeAndDispose(scene, mesh) { | |
| scene.remove(mesh); | |
| if (mesh.geometry && !mesh.userData.sharedGeo) mesh.geometry.dispose(); | |
| if (mesh.material && !mesh.userData.sharedMat) { | |
| if (Array.isArray(mesh.material)) mesh.material.forEach(m => m.dispose()); | |
| else mesh.material.dispose(); | |
| } | |
| } | |
| ``` | |
| --- | |
| ## 6. Zero-Asset Procedural Web Audio Synthesizer | |
| Browsers block audio until the first user gesture (`keydown` or `pointerdown`). Use a lazy-initialized `AudioContext` helper to synthesize crisp retro arcade sound effects in pure code: | |
| ```javascript | |
| const SFX = (() => { | |
| let ctx = null; | |
| function unlock() { | |
| if (!ctx) { | |
| const AC = window.AudioContext || window.webkitAudioContext; | |
| if (AC) ctx = new AC(); | |
| } | |
| if (ctx && ctx.state === 'suspended') ctx.resume(); | |
| return ctx; | |
| } | |
| function tone(type, fStart, fEnd, duration, gainVal = 0.12) { | |
| const c = unlock(); | |
| if (!c) return; | |
| const now = c.currentTime; | |
| const osc = c.createOscillator(); | |
| const gain = c.createGain(); | |
| osc.type = type; | |
| osc.frequency.setValueAtTime(fStart, now); | |
| osc.frequency.exponentialRampToValueAtTime(Math.max(20, fEnd), now + duration); | |
| gain.gain.setValueAtTime(gainVal, now); | |
| gain.gain.exponentialRampToValueAtTime(0.0001, now + duration); | |
| osc.connect(gain).connect(c.destination); | |
| osc.start(now); | |
| osc.stop(now + duration); | |
| } | |
| return { | |
| flap: () => tone('sine', 320, 640, 0.09, 0.12), | |
| score: () => { tone('triangle', 587.33, 587.33, 0.07, 0.12); setTimeout(() => tone('triangle', 880, 880, 0.14, 0.12), 65); }, | |
| hit: () => tone('sawtooth', 160, 38, 0.26, 0.18), | |
| }; | |
| })(); | |
| ``` | |
| --- | |
| ## 7. Pre-Flight Verification Checklist for Every Game | |
| Before emitting the final `</html>` tag, verify all 8 invariants: | |
| 1. **Scope Audit**: Every parameter used in `update(dt)` and `draw(dt)` is either declared in its signature or in module-level state. | |
| 2. **First-Frame Timestamp Guard**: `if (!lastTime) lastTime = now;` prevents `NaN` or huge initial `dt`. | |
| 3. **Tab-Switch Clamp**: `frameDt = Math.min(0.1, (now - lastTime) / 1000)` prevents teleporting through walls. | |
| 4. **Single RAF Loop**: Restarting a match resets state variables without spawning a second concurrent `requestAnimationFrame(loop)`. | |
| 5. **Input Responsiveness**: Restart works reliably after a short time-based grace period (`0.35s`), never gated on `frames % N === 0`. | |
| 6. **Zero-Allocation Hot Loop**: Particle and projectile pools use swap-and-pop (`pool[i] = pool[pool.length - 1]; pool.pop()`) instead of `Array.shift()` or `Array.filter()` inside 60fps loops. | |
| 7. **Safe Storage**: All `localStorage.getItem` / `setItem` calls are wrapped in `try { ... } catch {}` so sandboxed iframes and `file://` origins never throw `SecurityError`. | |
| 8. **Three.js Resource Hygiene**: Geometries and materials are shared across obstacle instances, lights are present for PBR materials, and window resize updates both `camera.aspect` and `camera.updateProjectionMatrix()`. | |