Download index.html from FormaLau/microduck-reachy-simulator: direct link, hf CLI and curl.
- Browser
- Download file 10.2 kB
-
https://huggingface.co/spaces/FormaLau/microduck-reachy-simulator/resolve/9f9cc1c31fbe839ea3ff5020bbf7948043256d7a/index.html
- Command line
-
hf download hf://spaces/FormaLau/microduck-reachy-simulator@9f9cc1c31fbe839ea3ff5020bbf7948043256d7a/index.html
-
curl -L -o index.html https://huggingface.co/spaces/FormaLau/microduck-reachy-simulator/resolve/9f9cc1c31fbe839ea3ff5020bbf7948043256d7a/index.html
10.2 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>Microduck RL playground</title> | |
| <style> | |
| :root { | |
| --ink: #08080c; | |
| --yellow: #ffd23f; | |
| } | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| html, body { height: 100%; } | |
| body { | |
| background: var(--ink); | |
| color: rgba(255, 255, 255, 0.85); | |
| font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; | |
| overflow: hidden; | |
| } | |
| #scene { position: fixed; inset: 0; } | |
| #scene canvas { display: block; } | |
| .halftone { | |
| position: fixed; | |
| inset: 0; | |
| pointer-events: none; | |
| background-image: radial-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1.5px); | |
| background-size: 21px 21px; | |
| mask-image: linear-gradient(to bottom, transparent 30%, black 100%); | |
| -webkit-mask-image: linear-gradient(to bottom, transparent 30%, black 100%); | |
| } | |
| /* Top-left corner: what this is */ | |
| #brand { | |
| position: fixed; | |
| top: 1.4rem; | |
| left: 1.6rem; | |
| z-index: 10; | |
| font-size: 0.72rem; | |
| font-weight: 600; | |
| letter-spacing: 0.14em; | |
| text-transform: uppercase; | |
| color: rgba(255, 255, 255, 0.55); | |
| line-height: 1.8; | |
| } | |
| #brand b { color: var(--yellow); font-weight: 600; } | |
| #loading { | |
| position: fixed; | |
| inset: 0; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 0.8rem; | |
| letter-spacing: 0.14em; | |
| text-transform: uppercase; | |
| color: rgba(255, 255, 255, 0.45); | |
| text-align: center; | |
| padding: 0 2rem; | |
| z-index: 20; | |
| } | |
| /* Bottom edges: controls left, key hints right */ | |
| #hud { | |
| position: fixed; | |
| bottom: 1.4rem; | |
| left: 1.6rem; | |
| right: 1.6rem; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: flex-end; | |
| gap: 1rem; | |
| z-index: 10; | |
| pointer-events: none; | |
| } | |
| #hud .stack { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: flex-start; | |
| gap: 0.45rem; | |
| pointer-events: auto; | |
| } | |
| #hud .row { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| } | |
| #hud button { | |
| appearance: none; | |
| border: 1px solid rgba(255, 255, 255, 0.14); | |
| background: rgba(255, 255, 255, 0.04); | |
| color: rgba(255, 255, 255, 0.8); | |
| font: inherit; | |
| font-size: 0.72rem; | |
| font-weight: 600; | |
| letter-spacing: 0.1em; | |
| text-transform: uppercase; | |
| padding: 0.5rem 1rem; | |
| border-radius: 999px; | |
| cursor: pointer; | |
| transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease; | |
| } | |
| #hud button:hover { background: rgba(255, 255, 255, 0.1); } | |
| #hud button.on { | |
| background: #ffc61e; | |
| border-color: #ffc61e; | |
| color: #08080c; | |
| } | |
| /* Current-state label: quiet line above the telemetry, slot-machine | |
| roll on change */ | |
| .mode { | |
| position: relative; | |
| overflow: hidden; | |
| height: 1.2em; | |
| min-width: 8ch; | |
| font-size: 0.72rem; | |
| font-weight: 600; | |
| letter-spacing: 0.2em; | |
| text-transform: uppercase; | |
| color: rgba(255, 210, 63, 0.8); | |
| text-align: right; | |
| } | |
| .mode .mode-text { | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| line-height: 1.2; | |
| transition: transform 0.3s cubic-bezier(0.2, 0.8, 0.2, 1), opacity 0.3s ease; | |
| } | |
| .mode .mode-text.in { transform: translateY(130%); opacity: 0; } | |
| .mode .mode-text.out { transform: translateY(-130%); opacity: 0; } | |
| /* Colour swatches */ | |
| #swatches { gap: 0.6rem; } | |
| #swatches button { | |
| width: 1.5rem; | |
| height: 1.5rem; | |
| padding: 0; | |
| border-radius: 50%; | |
| border: 2px solid rgba(255, 255, 255, 0.18); | |
| } | |
| #swatches button:hover { transform: scale(1.15); } | |
| #swatches button.on { | |
| border-color: #fff; | |
| transform: scale(1.15); | |
| } | |
| #hud .keys { | |
| font-size: 0.7rem; | |
| letter-spacing: 0.08em; | |
| color: rgba(255, 255, 255, 0.4); | |
| text-align: right; | |
| line-height: 1.9; | |
| pointer-events: auto; | |
| } | |
| /* Corner group captions */ | |
| #hud .caption { | |
| display: block; | |
| font-size: 0.55rem; | |
| font-weight: 600; | |
| letter-spacing: 0.2em; | |
| text-transform: uppercase; | |
| color: rgba(255, 255, 255, 0.28); | |
| } | |
| #hud .keys .caption { margin-bottom: 0.45rem; } | |
| /* Keycap chips in the hints */ | |
| #hud .keys .key { | |
| display: inline-block; | |
| min-width: 1.5em; | |
| padding: 0.12em 0.4em; | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| border-bottom-width: 2px; | |
| border-radius: 5px; | |
| background: rgba(255, 255, 255, 0.05); | |
| color: rgba(255, 255, 255, 0.75); | |
| font-size: 0.62rem; | |
| font-weight: 600; | |
| line-height: 1.35; | |
| text-align: center; | |
| transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; | |
| } | |
| #hud .keys .key.lit { | |
| background: var(--yellow); | |
| border-color: var(--yellow); | |
| color: var(--ink); | |
| } | |
| #pad-hint { display: none; } | |
| body.pad-connected #pad-hint { display: inline; } | |
| /* Mini command sticks: dot = the twist the policy actually receives */ | |
| #sticks { | |
| display: flex; | |
| gap: 0.7rem; | |
| justify-content: flex-end; | |
| margin-bottom: 0.5rem; | |
| } | |
| .stickwrap { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 0.15rem; | |
| } | |
| .stickwrap span { | |
| font-size: 0.55rem; | |
| letter-spacing: 0.14em; | |
| text-transform: uppercase; | |
| color: rgba(255, 255, 255, 0.3); | |
| line-height: 1; | |
| } | |
| .stickbox { | |
| position: relative; | |
| width: 46px; | |
| height: 46px; | |
| border-radius: 50%; | |
| border: 1px solid rgba(255, 255, 255, 0.16); | |
| background: rgba(255, 255, 255, 0.03); | |
| } | |
| .stickdot { | |
| position: absolute; | |
| left: 50%; | |
| top: 50%; | |
| width: 12px; | |
| height: 12px; | |
| margin: -6px 0 0 -6px; | |
| border-radius: 50%; | |
| background: rgba(255, 255, 255, 0.35); | |
| transition: background 0.15s ease; | |
| } | |
| .stickbox.live .stickdot { background: var(--yellow); } | |
| #stats-wrap { | |
| position: fixed; | |
| top: 1.4rem; | |
| right: 1.6rem; | |
| z-index: 10; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: flex-end; | |
| gap: 0.15rem; | |
| } | |
| #stats { | |
| font-size: 0.68rem; | |
| letter-spacing: 0.08em; | |
| text-align: right; | |
| color: rgba(255, 255, 255, 0.4); | |
| line-height: 1.7; | |
| font-variant-numeric: tabular-nums; | |
| } | |
| @media (max-width: 700px) { | |
| #hud { flex-direction: column; align-items: flex-start; } | |
| #hud .keys { display: none; } | |
| #brand .sub { display: none; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="scene"></div> | |
| <div class="halftone"></div> | |
| <div id="brand"> | |
| <b>Microduck</b> · real trained policies<br /> | |
| <span class="sub">MuJoCo + ONNX, live in your browser</span> | |
| </div> | |
| <div id="stats-wrap"> | |
| <div class="mode" id="mode-label"><span class="mode-text">Run</span></div> | |
| <div id="stats"></div> | |
| </div> | |
| <div id="hud" hidden> | |
| <div class="stack"> | |
| <span class="caption">Colour</span> | |
| <div class="row" id="swatches"></div> | |
| </div> | |
| <div class="keys"> | |
| <span class="caption">Controls</span> | |
| <div id="sticks"> | |
| <div class="stickwrap"> | |
| <div class="stickbox"><div class="stickdot" id="dot-move"></div></div> | |
| <span>move</span> | |
| </div> | |
| <div class="stickwrap"> | |
| <div class="stickbox"><div class="stickdot" id="dot-turn"></div></div> | |
| <span>turn</span> | |
| </div> | |
| </div> | |
| <span class="hint"><span class="key" id="key-fwd">↑</span><span class="key" id="key-back">↓</span> move</span> | |
| <span class="hint"><span class="key" id="key-turnl">←</span><span class="key" id="key-turnr">→</span> turn</span> | |
| <span class="hint"><span class="key" id="key-left">A</span><span class="key" id="key-right">E</span> strafe</span><br /> | |
| <span class="hint"><span class="key" id="key-roll">Space</span> roll</span> | |
| <span class="hint"><span class="key" id="key-reset">R</span> reset</span> | |
| drag to orbit · scroll to zoom<br /> | |
| <span id="pad-hint">gamepad: | |
| <span class="hint"><span class="key" id="key-pad-x">X</span> roll</span> | |
| <span class="hint"><span class="key" id="key-pad-sit">⇓</span> sit</span> | |
| <span class="hint"><span class="key" id="key-pad-run">⇑</span> run</span> | |
| <span class="hint"><span class="key" id="key-pad-rt">RT</span> quack</span> | |
| </span> | |
| </div> | |
| </div> | |
| <div id="loading">Compiling physics…</div> | |
| <script type="importmap"> | |
| { | |
| "imports": { | |
| "three": "https://cdn.jsdelivr.net/npm/three@0.164.1/build/three.module.js", | |
| "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.164.1/examples/jsm/" | |
| } | |
| } | |
| </script> | |
| <!-- rl.js is imported dynamically with the private-space ?__sign JWT | |
| appended: a plain src attribute can 401 when the browser blocks the | |
| *.static.hf.space auth cookie inside the hub iframe. --> | |
| <script type="module"> | |
| const V = "5"; // bump on rl.js changes to defeat heuristic caching | |
| const sign = new URLSearchParams(location.search).get("__sign"); | |
| const suffix = sign ? `&__sign=${encodeURIComponent(sign)}` : ""; | |
| import(`./rl.js?v=${V}${suffix}`); | |
| </script> | |
| </body> | |
| </html> | |