Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
lilray/web/index.html
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
164 lines (154 sloc)
7.85 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <script src="./liblilray.js"></script> | |
| <style> | |
| .keys > div { | |
| border: 1px solid #cccccc; | |
| width: 4em; | |
| text-align: center; | |
| user-select: none; | |
| } | |
| a { | |
| color: coral; | |
| } | |
| a :visited { | |
| color: coral; | |
| } | |
| </style> | |
| </head> | |
| <body style="background: black; color: #cccccc; font-family: monospace"> | |
| <div style="width: 640px; margin: auto;"> | |
| <canvas id="canvas" width="640" heigh="480" tabindex="-1" style="width: 640px; height: 480px; user-select: none; border: none; outline-style: none;"></canvas> | |
| <div class="keys" style="display: flex; justify-content: center; width: 100%; font-size: 4em;"> | |
| <div id="up">↑</div> | |
| <div id="down">↓</div> | |
| <div id="left">←</div> | |
| <div id="right">→</div> | |
| </div> | |
| <p>'lilray' is small recreational project to learn about raycasting, sub pixel precision rendering, fixed point math, and other 80ies and 90ies style game technologies, transplanted into the year 2022.</p> | |
| <p>It's implemented as a simple (shoddy) C++ library with a C wrapper so it can be exposed to other platforms, like this very JavaScript/WASM demo.</p> | |
| <h3><a href="https://github.com/badlogic/lilray">GitHub</a></h3> | |
| </div> | |
| </body> | |
| <script> | |
| let lib; | |
| let canvas = document.getElementById("canvas"); | |
| canvas.focus(); | |
| canvas.width = canvas.clientWidth; | |
| canvas.height = canvas.clientHeight; | |
| let keyW = false, keyS = false, keyA = false, keyD = false; | |
| canvas.addEventListener("keydown", (event) => { | |
| if (event.key === "w") keyW = true; | |
| if (event.key === "s") keyS = true; | |
| if (event.key === "a") keyA = true; | |
| if (event.key === "d") keyD = true; | |
| }, false); | |
| canvas.addEventListener("keyup", (event) => { | |
| if (event.key === "w") keyW = false; | |
| if (event.key === "s") keyS = false; | |
| if (event.key === "a") keyA = false; | |
| if (event.key === "d") keyD = false; | |
| }, false); | |
| canvas.focus(); | |
| document.getElementById("left").addEventListener("mousedown", () => keyA = true); | |
| document.getElementById("left").addEventListener("mouseup", () => keyA = false); | |
| document.getElementById("left").addEventListener("touchstart", () => keyA = true); | |
| document.getElementById("left").addEventListener("touchend", () => keyA = false); | |
| document.getElementById("right").addEventListener("mousedown", () => keyD = true); | |
| document.getElementById("right").addEventListener("mouseup", () => keyD = false); | |
| document.getElementById("right").addEventListener("touchstart", () => keyD = true); | |
| document.getElementById("right").addEventListener("touchend", () => keyD = false); | |
| document.getElementById("up").addEventListener("mousedown", () => keyW = true); | |
| document.getElementById("up").addEventListener("mouseup", () => keyW = false); | |
| document.getElementById("up").addEventListener("touchstart", () => keyW = true); | |
| document.getElementById("up").addEventListener("touchend", () => keyW = false); | |
| document.getElementById("down").addEventListener("mousedown", () => keyS = true); | |
| document.getElementById("down").addEventListener("mouseup", () => keyS = false); | |
| document.getElementById("down").addEventListener("touchstart", () => keyS = true); | |
| document.getElementById("down").addEventListener("touchend", () => keyS = false); | |
| let loadImage = async (url) => { | |
| let response = await fetch(url) | |
| if (!response.ok) throw new Error("Couldn't load image: " + url); | |
| let data = new Uint8Array(await response.arrayBuffer()); | |
| let ptr = lib._malloc(data.byteLength); | |
| lib.HEAPU8.set(data, ptr); | |
| let image = lib._lilray_image_create_from_memory(ptr, data.byteLength); | |
| lib._free(ptr); | |
| return image; | |
| } | |
| let initialize = async function () { | |
| lib = await liblilray(); | |
| const resX = 640, resY = 480; | |
| const rotationSpeed = 70; | |
| const movementSpeed = 2.5; | |
| let textures = await Promise.all([ | |
| loadImage("assets/STARG2.png"), | |
| loadImage("assets/STARG3.png"), | |
| loadImage("assets/STARGR2.png"), | |
| loadImage("assets/TEKWALL1.png"), | |
| loadImage("assets/TEKWALL2.png"), | |
| loadImage("assets/TEKWALL3.png"), | |
| loadImage("assets/TEKWALL4.png"), | |
| ]); | |
| let texturesPtr = lib._malloc(textures.length * 4); | |
| lib.HEAPU32.set(textures, texturesPtr / 4); | |
| let cells = [ | |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 2, 2, 2, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, | |
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
| ]; | |
| let cellsPtr = lib._malloc(cells.length * 4); | |
| lib.HEAPU32.set(cells, cellsPtr / 4); | |
| let grunt = await loadImage("assets/grunt.png"); | |
| let sprites = [ | |
| lib._lilray_sprite_create(4.5, 2.5, 0.7, grunt), | |
| lib._lilray_sprite_create(4.5, 1.5, 0.7, grunt), | |
| lib._lilray_sprite_create(5.5, 2.0, 0.7, grunt) | |
| ]; | |
| let spritesPtr = lib._malloc(sprites.length * 4); | |
| lib.HEAPU32.set(sprites, spritesPtr / 4); | |
| let map = lib._lilray_map_create(21, 21, cellsPtr); | |
| let camera = lib._lilray_camera_create(2.5, 2.5, 0, 66); | |
| let renderer = lib._lilray_renderer_create(resX, resY, texturesPtr, textures.length, textures[1], textures[1]); | |
| let lastFrameTime = Date.now(); | |
| function render() { | |
| let time = Date.now(); | |
| let delta = (time - lastFrameTime) / 1000; | |
| lastFrameTime = time; | |
| if (keyW) lib._lilray_camera_move(camera, map, movementSpeed * delta); | |
| if (keyS) lib._lilray_camera_move(camera, map, -movementSpeed * delta); | |
| if (keyA) lib._lilray_camera_rotate(camera, -rotationSpeed * delta); | |
| if (keyD) lib._lilray_camera_rotate(camera, rotationSpeed * delta); | |
| lib._lilray_renderer_render(renderer, camera, map, spritesPtr, sprites.length, 6); | |
| let frame = lib._lilray_renderer_get_frame(renderer); | |
| lib._lilray_image_to_rgba(frame); | |
| let framePixels = new Uint8ClampedArray(lib.HEAPU8.buffer, lib._lilray_image_get_pixels(frame), resX * resY * 4); | |
| let imageData = new ImageData(framePixels, resX, resY); | |
| this.canvas.getContext("2d").putImageData(imageData, 0, 0); | |
| requestAnimationFrame(render); | |
| } | |
| render(); | |
| } | |
| initialize(); | |
| </script> | |
| </html> |