game-layer
Repeating bitmap sampled into a canvas on demand. The first direct img supplies the texture and accessible alternative. A missing, failed or loading image leaves the authored fallback. Put inside a game-screen. Layer resolution defaults to 128 by 96 and is stretched to the viewport. A direct game-screen layer containing a game-tilemap scrolls the map with CSS. Extend the layer beyond the screen when scrolling should reveal more tiles. In a game-world, the perspective mode projects a CSS ground plane and scenery layers use factor and drift for parallax.
Examples
Bitmap scrolling
Plain mode repeats the Violet Citadel runway texture. Change either scroll position in logical pixels.
<game-screen>
<game-layer id="plain-runway" mode="plain" amplitude="12">
<img src="/games/aether-wing/citadel-runway.png" width="64" height="24" alt="Violet Citadel runway texture">
</game-layer>
</game-screen>
Parallax layers
Move the camera to see the Emerald Reach forest travel four times as far as the mountains. The tilemaps extend past the screen so scrolling can reveal more scenery.
<game-screen id="parallax-camera" width="128" height="96" camera-x="0">
<game-tileset id="parallax-camera-reach-mountains" tile-width="16" tile-height="16"><img src="/games/aether-wing/reach-mountains-tiles.png" alt=""></game-tileset>
<game-layer factor="0.25" drift="0.04" style="right:-50%">
<game-tilemap tileset="parallax-camera-reach-mountains" columns="12" rows="5" style="--sheet-columns:16;--sheet-rows:3" role="img" aria-label="Emerald Reach mountains">
<game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="6" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="7" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="8" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="10" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="11" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="12" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
<game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="6" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="14" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="15" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="16" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="17" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
<game-tile index="25" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="26" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="27" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="28" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="29" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="30" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
<game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="36" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="37" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="38" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
<game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
</game-tilemap>
</game-layer>
<game-tileset id="parallax-camera-reach-forest" tile-width="16" tile-height="16"><img src="/games/aether-wing/reach-forest-tiles.png" alt=""></game-tileset>
<game-layer factor="1" drift="0.1" style="right:-50%">
<game-tilemap tileset="parallax-camera-reach-forest" columns="12" rows="5" style="--sheet-columns:16;--sheet-rows:3" role="img" aria-label="Emerald Reach forest">
<game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile>
<game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile>
<game-tile index="6" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="7" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="8" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="10" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="11" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="12" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="13" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="14" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="15" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="16" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="17" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile>
<game-tile index="26" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="27" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="28" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="29" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="30" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="31" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="32" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="33" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="34" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="35" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="36" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="37" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile>
<game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile><game-tile index="41" style="background-image:url('/games/aether-wing/reach-forest-tiles.png')"></game-tile>
</game-tilemap>
</game-layer>
</game-screen>


Affine rotation
Rotate and scale the whole repeating texture, a technique used in the SNES Mode 7 effect.
<game-screen>
<game-layer id="affine-runway" mode="affine" amplitude="12">
<img src="/games/aether-wing/citadel-runway.png" width="64" height="24" alt="Violet Citadel runway texture">
</game-layer>
</game-screen>
Scanline offsets
Offset each horizontal row. Phase moves the wave through the texture.
<game-screen>
<game-layer id="row-runway" mode="scanlines" amplitude="12">
<img src="/games/aether-wing/citadel-runway.png" width="64" height="24" alt="Violet Citadel runway texture">
</game-layer>
</game-screen>
Column offsets
Offset each vertical column to make the lane markings appear to twist.
<game-screen>
<game-layer id="column-runway" mode="columns" amplitude="12">
<img src="/games/aether-wing/citadel-runway.png" width="64" height="24" alt="Violet Citadel runway texture">
</game-layer>
</game-screen>
Perspective road
Rows grow wider toward the bottom. Bend the road with phase and scroll the texture to move the lane markings. Violet Citadel uses the same bitmap on its CSS-projected ground.
<game-screen style="--game-screen-background:linear-gradient(#191e42 33.33%, #4b527d 33.33%)">
<game-layer id="road-texture" mode="road" amplitude="12">
<img src="/games/aether-wing/citadel-runway.png" width="64" height="24" alt="Violet Citadel runway texture">
</game-layer>
</game-screen>
Projected ground
Launch to see a CSS perspective plane and its palette cycle. The bitmap road mode above uses separate scanline rendering.
<game-world aria-label="Flight demonstration">
<game-tileset id="training-pilot" tile-width="32" tile-height="32"><img src="/games/aether-wing/pilot.png" alt=""></game-tileset>
<game-tileset id="training-moth" tile-width="32" tile-height="32"><img src="/games/aether-wing/moth.png" alt=""></game-tileset>
<game-tileset id="training-pine" tile-width="32" tile-height="48"><img src="/games/aether-wing/pine.png" alt=""></game-tileset>
<game-tileset id="training-ground" tile-width="8" tile-height="8">
<game-tile index="0">3 3 3 3 3 3 3 3
3 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0</game-tile>
<game-tile index="1">3 3 3 3 3 3 3 3
3 1 1 1 1 1 1 1
3 1 1 1 1 1 1 1
3 1 1 1 1 1 1 1
3 1 1 1 1 1 1 1
3 1 1 1 1 1 1 1
3 1 1 1 1 1 1 1
3 1 1 1 1 1 1 1</game-tile>
</game-tileset>
<game-input deadzone="0.18" fire-button="0">
<form>
<fieldset data-native-controls><legend>Course controls</legend>
<label><input type="checkbox" data-native-run>Run course</label>
<label><input type="checkbox" data-native-pause>Pause motion</label>
</fieldset>
<fieldset data-native-controls><legend>Move horizontally</legend>
<label><input type="radio" name="training-x" data-axis="x" value="-1">Left</label>
<label><input type="radio" name="training-x" data-axis="x" value="0" checked>Center</label>
<label><input type="radio" name="training-x" data-axis="x" value="1">Right</label>
</fieldset>
<fieldset data-native-controls><legend>Move vertically</legend>
<label><input type="radio" name="training-y" data-axis="y" value="1">Up</label>
<label><input type="radio" name="training-y" data-axis="y" value="0" checked>Middle</label>
<label><input type="radio" name="training-y" data-axis="y" value="-1">Down</label>
</fieldset>
<fieldset data-native-controls><legend>Sector</legend>
<label><input type="radio" name="training-stage" data-stage-choice="0" checked>Training range</label>
</fieldset>
<game-screen data-world-viewport width="320" height="200" tabindex="0" role="group" aria-label="Training world viewport">
<game-stage id="training-sector" data-stage-index="0" name="Training range" length="120" speed="12" sky="#213959" haze="#b0d5ce">
<game-tileset id="training-reach-mountains" tile-width="16" tile-height="16"><img src="/games/aether-wing/reach-mountains-tiles.png" alt=""></game-tileset>
<game-layer factor="0.18" drift="0.04">
<game-tilemap tileset="training-reach-mountains" columns="12" rows="5" style="--sheet-columns:16;--sheet-rows:3">
<game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="6" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="7" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="8" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="10" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="11" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="12" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
<game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="0" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="6" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="14" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="15" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="16" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="17" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
<game-tile index="25" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="26" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="27" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="28" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="29" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="30" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
<game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="36" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="37" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="38" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
<game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile><game-tile index="9" style="background-image:url('/games/aether-wing/reach-mountains-tiles.png')"></game-tile>
</game-tilemap>
</game-layer>
<game-palette id="training-palette-1" colors="#296b72 #48a99a #81cfb3 #b8e8c5" cycle-start="2" cycle-rate="5"></game-palette>
<game-layer mode="perspective" cell-size="4" style="--palette-0:#296b72;--palette-1:#48a99a;--palette-2:#81cfb3;--palette-3:#b8e8c5;--cycle-rate:5">
<game-tilemap palette="training-palette-1" tileset="training-ground" columns="2" rows="2">
<game-tile index="0"></game-tile><game-tile index="1"></game-tile><game-tile index="1"></game-tile><game-tile index="0"></game-tile>
</game-tilemap>
</game-layer>
<game-sprite actor="scenery" aspect="0.666667" tileset="training-pine" x="-4" size="4" spacing="16"><img src="/games/aether-wing/pine.png" alt=""></game-sprite>
<game-sprite actor="scenery" aspect="0.666667" tileset="training-pine" x="4" size="4" spacing="16" offset="8"><img src="/games/aether-wing/pine.png" alt=""></game-sprite>
<game-sprite actor="enemy" frames="8" fps="10" tileset="training-moth" at="8" interval="30" count="4" x="0" y="1.1" z="32" behavior="straight"
health="1" score="100" fire-rate="1.1" fire-delay="0.2" shot-speed="24"><label data-native-target><input type="checkbox" aria-label="Shoot moth"><span><img src="/games/aether-wing/moth.png" alt=""></span></label></game-sprite>
<div data-native-cleared>Sector cleared. Choose the next sector.</div></game-stage>
<game-sprite actor="player" tileset="training-pilot" frames="5" fps="0" max-health="3" speed="3.2" radius="0.18"
size="0.8" fire-rate="0.14" shot-speed="75" recovery="1.2" start-x="0" start-y="1.1"><img src="/games/aether-wing/pilot.png" alt=""></game-sprite>
</game-screen>
<p data-native-controls>Run the course, steer with the radio controls, and select an approaching enemy to shoot. Clear the targets in each sector.</p>
<button type="reset" data-native-controls>Reset course</button>
<p data-native-victory role="status">All sectors cleared.</p>
<div data-world-hud aria-label="Flight instruments">
<label>Shield <output data-world-shield aria-label="Shield" aria-live="off">3</output></label>
<label>Score <output data-world-score aria-label="Score" aria-live="off">000000</output></label>
<label>Sector <output data-world-sector aria-label="Sector" aria-live="off">Training range</output></label>
<label>Route <output data-world-progress aria-label="Route progress" aria-live="off">0%</output></label>
</div>
<p role="status" aria-label="Flight status" data-world-status>Run the course and select an approaching target to shoot.</p>
<div data-world-controls role="group" aria-label="Game controls">
<button type="button" data-action="start" disabled>Launch</button>
<button type="button" data-action="pause" disabled>Pause</button>
<button type="button" data-action="restart" disabled>Restart flight</button>
</div>
<div data-world-controls role="group" aria-label="Flight controls">
<button type="button" data-action="left" aria-label="Fly left" disabled>←</button>
<button type="button" data-action="up" aria-label="Fly up" disabled>↑</button>
<button type="button" data-action="down" aria-label="Fly down" disabled>↓</button>
<button type="button" data-action="right" aria-label="Fly right" disabled>→</button>
<button type="button" data-action="fire" disabled>Fire</button>
</div>
<p data-world-controller>Keyboard / touch</p>
</form>
</game-input>
</game-world>



API
| Name | Type or default | Behavior |
|---|---|---|
mode |
"plain" | "affine" | "scanlines" | "columns" | "road" | "perspective"
Default plain |
Plain repeats the image. Affine applies one centered transform. Scanlines offset each row; columns offset each column. Road leaves the top third transparent and increases zoom by row toward the viewer, repeating along the texture’s vertical axis. Unknown modes use plain. |
width |
number
Default 128 |
Canvas width. Rounded and clamped to 1–512. |
height |
number
Default 96 |
Canvas height. Rounded and clamped to 1–512. |
scroll-x |
number
Default 0 |
Local horizontal scroll in logical pixels. Positive values move the layer left. |
scroll-y |
number
Default 0 |
Local vertical scroll in logical pixels. Positive values move the layer up in orthographic modes, or advance texture depth in road mode. |
camera-x |
number
Default 0 |
Camera offset in logical pixels. Managed by the screen when directly nested in one. |
camera-y |
number
Default 0 |
Camera offset in logical pixels. Managed by the screen when directly nested in one. |
factor |
number
Default 1 |
Multiplier for both camera offsets. Applied before adding local scroll. |
scale |
number
Default 1 |
Base texture scale, clamped to 0.125–16. Road mode multiplies this by depth. |
angle |
number
Default 0 |
Clockwise degrees around the center. Affine mode only. |
amplitude |
number
Default 0 |
Maximum strip offset in logical pixels. Scanlines, columns, and road only. |
phase |
number
Default 0 |
Position within the offset wave in degrees. Scanlines, columns, and road only. |
drift |
number
Default 0.05 |
Forward parallax drift used when this layer is a direct child of a world stage. |
cell-size |
number
Default 4 |
World width and depth of a tile in a perspective layer. |
Emitted events
None.
Listened-for events
None.
| Name | Type or default | Behavior |
|---|---|---|
--palette-0 |
First floor color on a perspective layer. | |
--palette-1 |
Second floor color on a perspective layer. | |
--palette-2 |
First cycling grid color on a perspective layer. | |
--palette-3 |
Second cycling grid color on a perspective layer. | |
--cycle-rate |
Default 5 |
Number of palette changes per second on a perspective layer. |