-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdemo6.ts
More file actions
113 lines (101 loc) · 3.99 KB
/
demo6.ts
File metadata and controls
113 lines (101 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import { PlayerInputs, advanceRay, attachKeyboard, attachMouse, attachTouch, createRay, getCameraPlane, getMapCell, map, mapSize, setPlayerPos, updatePosition } from './demo1';
import { createSky, renderBackground } from './demo2';
import { WallMeasurements, getWallMeasurements, renderWall } from './demo3';
import { FloorMeasurements, getFloorMeasurements, mapFloorTexture, renderFloor } from './demo5';
import { Vec2, attachRenderFunction, initCanvas, loadTextureData } from './util';
export async function initDemo6() {
const playerPos: Vec2 = {x: 2, y: 3};
const playerDir: Vec2 = {x: 1, y: 0};
const playerInputs: PlayerInputs = {
moveForward: false,
moveBackward: false,
turnLeft: false,
turnRight: false,
rotationSpeed: 0,
};
const setPos = (dest: Vec2) => setPlayerPos(playerPos, dest, map, mapSize);
const wallTexture: ImageData = await loadTextureData('wall.png');
const floorTexture: ImageData = await loadTextureData('floor.png');
const ceilingTexture: ImageData = await loadTextureData('ceiling.png');
const [canvas, ctx] = initCanvas('canvas6');
const sky = createSky(canvas, ctx);
const aspectRatio = canvas.width / canvas.height;
const repaint = attachRenderFunction(canvas, dt => {
updatePosition(dt, playerInputs, playerPos, playerDir, setPos);
renderBackground(canvas, ctx, sky);
renderEnv(canvas, ctx, aspectRatio, playerPos, playerDir, wallTexture, floorTexture, ceilingTexture);
});
attachKeyboard(canvas, playerInputs);
attachMouse(canvas, repaint, playerPos, playerDir, setPos);
attachTouch(canvas, repaint, playerPos, playerDir, setPos);
}
export function renderEnv(
canvas: HTMLCanvasElement,
ctx: CanvasRenderingContext2D,
aspectRatio: number,
playerPos: Vec2,
playerDir: Vec2,
wallTexture: ImageData,
floorTexture: ImageData,
ceilingTexture: ImageData,
) {
const cameraPlane = getCameraPlane(playerDir);
for (let x = 0; x < canvas.width; x++) {
const ray = createRay(canvas, aspectRatio, playerPos, playerDir, x, cameraPlane);
const stripe = ctx.getImageData(x, 0, 1, canvas.height);
let yFloor = 0;
let yCeiling = 0;
while (true) {
advanceRay(ray);
const cell = getMapCell(map, ray.mapPos, mapSize)
if (!cell) {
break;
}
const wall = getWallMeasurements(ray, canvas.height, playerPos);
const floor = getFloorMeasurements(ray, wall.wallX);
[yFloor, yCeiling] = renderFloorAndCeiling(canvas, stripe, wall, floor, playerPos, ray.perpWallDist,
yFloor, yCeiling, floorTexture, ceilingTexture);
if (cell.solid) {
renderWall(canvas, stripe, ray, wall, wallTexture);
break;
}
}
ctx.putImageData(stripe, x, 0);
}
}
export function renderFloorAndCeiling(
canvas: HTMLCanvasElement,
stripe: ImageData,
wall: WallMeasurements,
floor: FloorMeasurements,
playerPos: Vec2,
floorDist: number,
yFloor: number,
yCeiling: number,
floorTexture?: ImageData,
ceilingTexture?: ImageData,
): [number, number]{
const cellY = Math.ceil((canvas.height - wall.wallHeight) * 0.5);
yFloor = renderFloor(canvas, stripe, floor, cellY, playerPos, yFloor, floorDist, floorTexture);
yCeiling = renderCeiling(canvas, stripe, floor, playerPos, cellY, yCeiling, floorDist, ceilingTexture)
return [yFloor, yCeiling];
}
export function renderCeiling(
canvas: HTMLCanvasElement,
stripe: ImageData,
floor: FloorMeasurements,
playerPos: Vec2,
cellY: number,
yCeiling: number,
perpWallDist: number,
ceilingTexture?: ImageData,
): number {
if (!ceilingTexture) {
return Math.max(yCeiling, cellY);
}
while (yCeiling < cellY) {
mapFloorTexture(canvas, stripe, yCeiling, floor, playerPos, yCeiling, perpWallDist, ceilingTexture);
yCeiling++;
}
return yCeiling;
}