JSFiddle - React, Tailwind, and code Playground
HTML
<canvas id="canvas"></canvas>
CSS
canvas {
width: 640px;
image-rendering: pixelated;
}
JavaScript
"use strict";
const CW = 160;
const CH = 100;
const CH_2 = CH / 2;
const CYCLE = 256;
const FOV = CW / 2;
let sint = [];
let map = [];
let ctx;
let pat = [];
let car;
let keys = [];
onload = function() {
// 三角関数テーブル
for (let i = 0; i < CYCLE; i++) {
let t = 2 * Math.PI * i / CYCLE;
sint[i] = Math.sin(t);
}
// 地図
map[7] = 0xff;
map[6] = 0x81;
map[5] = 0xa5;
map[4] = 0x81;
map[3] = 0x81;
map[2] = 0x81;
map[1] = 0x81;
map[0] = 0xff;
canvas.width = CW;
canvas.height = CH;
ctx = canvas.getContext("2d");
car = { x:4, y:4, d:0 };
for (let bits of [9, 5, 15, 0, 1]) {
pat.push(getPattern(bits));
}
draw();
onkeydown = function(e) {
keys[e.keyCode] = true;
};
onkeyup = function(e) {
keys[e.keyCode] = false;
};
};
function draw() {
// let v = 0;
let dir = 0;
// if (keys[88]) v = .05; // X
// if (keys[90]) v = -.05; // Z
if (keys[100]) dir = -1; // Num4
if (keys[102]) dir = 1; // Num6
let t = car.d;
let st = sint[t];
let ct = sint[mod(t + CYCLE / 4, CYCLE)];
// car.x += sint[t] * v;
// car.y += cost[t] * v;
car.d = mod(car.d + dir, CYCLE);
//
ctx.fillStyle = pat[3];
ctx.fillRect(0, 0, CW, CH_2);
ctx.fillStyle = pat[4];
ctx.fillRect(0, CH_2, CW, CH_2);
const WH = CH / 8;
for (let i = 0; i < FOV; i++) {
let x = (i * 2 - FOV) / FOV;
let rd = { x:ct * x + st, y:-st * x + ct };
let { d, wall } = rayBlock(car, rd);
if (d >= 0) {
let h = Math.min(Math.floor(WH / d), CH_2);
ctx.fillStyle = pat[wall];
ctx.fillRect(i * 2, CH_2 - h, 2, h * 2);
}
}
requestAnimationFrame(draw);
}
function rayBlock(ro, rd) {
let p = { ...ro };
let v = { ...rd };
let s = { x:1, y:1 };
let a = { x:0, y:0 };
if (v.x < 0) {
p.x = -p.x;
v.x = -v.x;
s.x = -1;
a.x = 1;
}
if (v.y < 0) {
p.y = -p.y;
v.y = -v.y;
s.y = -1;
a.y = 1;
}
let c = {};
c.x = s.x * (Math.floor(ro.x) + a.x);
c.y = s.y * (Math.floor(ro.y) + a.y);
let d = 0;
let wall = 0;
while (true) {
let q = {};
q.x = s.x * (c.x + a.x);
q.y =...