crosswind / index.html
Death242's picture
Static site
927b1ea verified
Raw History Blame Contribute Delete
10.9 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, user-scalable=no" />
<title>Crosswind — a flight simulator</title>
<meta name="description" content="Fly a light aircraft over an island: take off, navigate, and try to put it back down on the runway." />
<meta property="og:title" content="Crosswind — a flight simulator">
<meta property="og:description" content="Fly a light aircraft over an island: take off, navigate, and try to put it back down on the runway.">
<meta property="og:type" content="website">
<meta name="twitter:card" content="summary">
<meta name="theme-color" content="#0b1016" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@500;600;700&family=Share+Tech+Mono&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="/static/style.css?v=1790098725" />
<script type="importmap">
{ "imports": { "three": "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.module.min.js" } }
</script>
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 64 64%27%3E%3Crect width=%2764%27 height=%2764%27 rx=%2714%27 fill=%27%230b1d3a%27/%3E%3Cpath d=%27M10 36 54 14l-8 34-12-8-8 10-2-12z%27 fill=%27%23fff%27/%3E%3C/svg%3E">
</head>
<body>
<canvas id="view"></canvas>
<div class="loading" id="loading">
<div class="loading-inner">
<p class="brand">Crosswind</p>
<p class="loading-sub">Building the island…</p>
</div>
</div>
<!-- instruments -->
<div class="hud">
<!-- top: heading ribbon -->
<div class="ribbon-wrap">
<div class="ribbon" id="ribbon">
<span>N</span><span>03</span><span>06</span><span>E</span><span>12</span><span>15</span>
<span>S</span><span>21</span><span>24</span><span>W</span><span>30</span><span>33</span>
<span>N</span><span>03</span><span>06</span><span>E</span><span>12</span><span>15</span>
<span>S</span><span>21</span><span>24</span><span>W</span><span>30</span><span>33</span>
</div>
<div class="ribbon-mark"></div>
<div class="ribbon-read" id="i-hdg">000</div>
</div>
<!-- left: speed -->
<div class="tape left">
<span class="tape-label">Airspeed</span>
<span class="tape-val" id="i-spd">0</span>
<span class="tape-unit">kt</span>
</div>
<!-- right: altitude and vertical speed -->
<div class="tape right">
<span class="tape-label">Altitude</span>
<span class="tape-val" id="i-alt">0</span>
<span class="tape-unit">ft</span>
<span class="tape-sub"><em id="i-vsi">0</em> fpm</span>
</div>
<!-- centre: attitude -->
<div class="attitude">
<div class="horizon" id="horizon-roll">
<div class="horizon-inner" id="horizon-inner">
<div class="sky-half"></div>
<div class="ground-half"></div>
<div class="pitch-ladder">
<i style="--p:-30"></i><i style="--p:-20"></i><i style="--p:-10"></i>
<i style="--p:10"></i><i style="--p:20"></i><i style="--p:30"></i>
</div>
</div>
</div>
<div class="wings"></div>
<div class="stall" id="stall" hidden>STALL</div>
</div>
<!-- bottom left: engine and configuration -->
<div class="panel">
<!-- a lever you can actually grab: click or drag anywhere on it to set the power -->
<div class="throttle-gauge" id="thr-lever" role="slider" aria-label="Throttle"
aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" tabindex="0">
<div class="throttle-fill" id="i-thr-bar"></div>
<div class="throttle-ticks"><i></i><i></i><i></i><i></i></div>
<div class="throttle-knob" id="i-thr-knob"></div>
</div>
<dl>
<div><dt>Throttle</dt><dd id="i-thr">0%</dd></div>
<div><dt>Flaps</dt><dd id="i-flaps">UP</dd></div>
<div><dt>Gear</dt><dd id="i-gear" class="ok">DOWN</dd></div>
<div><dt>Brakes</dt><dd id="i-brakes" class="warn">ON</dd></div>
<div><dt>G</dt><dd id="i-g">1.0</dd></div>
<div><dt>Trim</dt><dd id="i-trim">0</dd></div>
<div><dt>A/P</dt><dd id="i-ap">OFF</dd></div>
</dl>
<div class="fuel"><span id="i-fuel"></span></div>
</div>
<!-- bottom right: map -->
<div class="map">
<svg viewBox="0 0 128 128" aria-label="Island map">
<defs><clipPath id="map-clip"><rect x="0" y="0" width="128" height="128" rx="8" /></clipPath></defs>
<g clip-path="url(#map-clip)">
<rect x="0" y="0" width="128" height="128" fill="#0d2233" />
<!-- painted from the same heightmap the terrain is built from -->
<image id="map-img" x="0" y="0" width="128" height="128" href="" />
<g id="map-fields"></g>
<g id="map-plane" transform="translate(64 64)">
<path d="M0,-5 L3.4,4 L0,2 L-3.4,4 Z" fill="#ffd23f" stroke="#0b1016" stroke-width="0.6" />
</g>
</g>
<rect x="0.5" y="0.5" width="127" height="127" rx="8" fill="none" stroke="rgba(232,244,251,0.18)" />
</svg>
<span class="map-label" id="map-label">Isla Verde · RWY 36</span>
</div>
<div class="lesson" id="lesson" hidden>
<div class="lesson-bar"><span id="lesson-bar"></span></div>
<p class="lesson-step" id="lesson-step"></p>
<h3 id="lesson-title"></h3>
<p class="lesson-say" id="lesson-say"></p>
<p class="lesson-hint"><kbd id="lesson-hint"></kbd></p>
</div>
<div class="wind" id="wind">
<svg viewBox="0 0 40 40" aria-hidden="true"><g id="wind-arrow"><path d="M20 6 L25 22 L20 18 L15 22 Z" fill="currentColor"/></g></svg>
<span id="i-wind">—</span>
</div>
<div class="cam-tag" id="i-cam">Chase</div>
<div class="plane-tag" id="i-plane">Skylark 172</div>
<p class="msg" id="msg" hidden></p>
</div>
<!-- touch controls -->
<div class="touch">
<div class="stick" id="stick"><div class="knob" id="knob"></div></div>
<div class="throttle" id="throttle"><span>THR</span></div>
<div class="touch-btns">
<button type="button" data-key="g">GEAR</button>
<button type="button" data-key="f">FLAP</button>
<button type="button" data-key="b">BRK</button>
<button type="button" data-key="c">VIEW</button>
</div>
</div>
<div class="card" id="lesson-done" hidden>
<h2>First flight done</h2>
<p>That was a full circuit: take-off, a turn, a stall and a recovery, an approach and a landing. Everything else on the island is a variation on it.</p>
<p>Eight aircraft, eight airfields and six places to simply appear — press <kbd>M</kbd> for the pre-flight screen. There is also a carrier out west with a deck you can land on.</p>
<div class="card-btns"><button type="button" onclick="document.getElementById('lesson-done').hidden = true">Go flying</button></div>
</div>
<div class="card" id="crash" hidden>
<h2>Flight over</h2>
<p id="crash-why"></p>
<div class="card-btns">
<button type="button" data-key="r">Back to the runway</button>
<button type="button" data-key="t">Start airborne</button>
</div>
</div>
<!-- One screen for both halves of the decision. Nothing here touches the aircraft until
you press Fly, so you can change your mind as often as you like. -->
<div class="card preflight" id="preflight" hidden>
<h2>Pre-flight</h2>
<p class="pf-lead">Pick an aircraft and a place to start. Nothing moves until you press <strong>Fly</strong>.</p>
<div class="pf-cols">
<section class="pf-col">
<header><h3>Aircraft</h3><span class="pf-chosen" id="pf-plane-name">—</span></header>
<div class="planes" id="plane-list"></div>
</section>
<section class="pf-col">
<header><h3>Start from</h3><span class="pf-chosen" id="pf-place-name">—</span></header>
<div class="pf-tabs">
<button type="button" class="on" data-pf-tab="ground">Airfields</button>
<button type="button" data-pf-tab="air">In the air</button>
</div>
<div class="planes" id="place-list"></div>
</section>
</div>
<div class="pf-weather">
<span class="pf-weather-label">Weather</span>
<div class="pf-weather-btns" id="pf-weather"></div>
</div>
<p class="pf-summary" id="pf-summary"></p>
<div class="card-btns">
<button type="button" class="primary" id="pf-fly">Fly</button>
<button type="button" id="pf-teach">Teach me to fly</button>
<button type="button" id="pf-close">Cancel</button>
</div>
</div>
<div class="card help" id="help">
<h2>Crosswind</h2>
<p class="help-lead">Eight aircraft, eight airfields, one island. New to this? Press <kbd>K</kbd> and I'll talk you through a whole circuit.</p>
<dl>
<div><dt>W / S <em>or</em> ↑ ↓</dt><dd>Pitch</dd></div>
<div><dt>A / D <em>or</em> ← →</dt><dd>Roll</dd></div>
<div><dt>Q / E</dt><dd>Rudder · steering on the ground</dd></div>
<div><dt>Shift / Ctrl</dt><dd>Throttle · tap for 5%, hold to sweep</dd></div>
<div><dt>1 … 9 · 0</dt><dd>Set power directly — 10% a step, 0 is full</dd></div>
<div><dt>Drag the lever</dt><dd>Bottom left, for any setting you like</dd></div>
<div><dt>G · F · B</dt><dd>Gear · flaps · brakes</dd></div>
<div><dt>C</dt><dd>Change view</dd></div>
<div><dt>R · T</dt><dd>Restart on the runway · in the air</dd></div>
<div><dt>M</dt><dd>Pre-flight — choose aircraft and airfield · <em>N</em> next aircraft</dd></div>
<div><dt>J</dt><dd>Same screen, opened on the airfield list</dd></div>
<div><dt>K</dt><dd>Start or stop the tutorial</dd></div>
<div><dt>P</dt><dd>Autopilot · <em>[ ]</em> trim · <em>\</em> trim neutral</dd></div>
<div><dt>V</dt><dd>Weather — calm, breeze, crosswind, gusty</dd></div>
<div><dt>L</dt><dd>Time of day — morning to dusk</dd></div>
<div><dt>H</dt><dd>Show or hide this</dd></div>
</dl>
<div class="card-btns">
<button type="button" data-key="k">Teach me to fly</button>
<button type="button" data-key="m">Aircraft &amp; airfield</button>
<button type="button" data-key="h">Fly</button>
</div>
</div>
<script type="module" src="/static/sim.js?v=1790098725"></script>
<script src="/static/tour.js" data-app="crosswind" defer></script>
<script src="/static/hub.js" data-app="crosswind" defer></script>
</body>
</html>