2023-06-15 03:22:26 +00:00
|
|
|
import { ItemType, get_item_key } from "../logic.js";
|
|
|
|
|
2023-06-15 21:17:48 +00:00
|
|
|
const update_style = (map, style) => {
|
2023-06-13 03:47:43 +00:00
|
|
|
const css = `
|
|
|
|
* {
|
|
|
|
--scale: 100;
|
|
|
|
--aspect: ${map.width/map.height};
|
|
|
|
--scaleX: calc(var(--scale) * 1vw);
|
|
|
|
--scaleY: calc(var(--scale) * 1vh);
|
2023-06-14 01:18:01 +00:00
|
|
|
}
|
2023-06-13 03:47:43 +00:00
|
|
|
|
|
|
|
#container {
|
|
|
|
width: calc(var(--scaleY) * var(--aspect));
|
|
|
|
height: var(--scaleY);
|
|
|
|
margin-top: calc((100vh - var(--scaleY))/2);
|
|
|
|
margin-left: calc(50vw - var(--scaleY)*var(--aspect)/2);
|
|
|
|
position: relative;
|
2023-06-14 01:18:01 +00:00
|
|
|
vertical-align: top;
|
|
|
|
line-height: 0;
|
2023-06-13 03:47:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@media (max-aspect-ratio: ${map.width}/${map.height}) {
|
|
|
|
#container {
|
|
|
|
width: var(--scaleX);
|
|
|
|
height: calc(var(--scaleX) / var(--aspect));
|
|
|
|
margin-left: calc((100vw - var(--scaleX))/2);
|
|
|
|
margin-top: calc(50vh - var(--scaleX)/var(--aspect)/2);
|
|
|
|
}
|
|
|
|
}`;
|
|
|
|
|
2023-06-14 01:18:01 +00:00
|
|
|
style.innerHTML = css
|
2023-06-13 03:47:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Direction = {
|
|
|
|
EMPTY: 0,
|
|
|
|
WALL_HZ: 1,
|
|
|
|
WALL_VT: 2,
|
|
|
|
TURN_Q1: 3,
|
|
|
|
TURN_Q2: 4,
|
|
|
|
TURN_Q3: 5,
|
|
|
|
TURN_Q4: 6,
|
|
|
|
TEE_NORTH: 7,
|
|
|
|
TEE_EAST: 8,
|
|
|
|
TEE_SOUTH: 9,
|
|
|
|
TEE_WEST: 10,
|
|
|
|
CROSS: 11,
|
|
|
|
DOT: 12,
|
|
|
|
WALL_END_NORTH: 13,
|
|
|
|
WALL_END_SOUTH: 14,
|
|
|
|
WALL_END_EAST: 15,
|
|
|
|
WALL_END_WEST: 16
|
|
|
|
}
|
|
|
|
|
2023-06-15 21:17:48 +00:00
|
|
|
/**
|
|
|
|
* @param {CanvasRenderingContext2D} context
|
|
|
|
*/
|
|
|
|
const draw_tile = (context, x, y, w, type) => {
|
2023-06-13 03:47:43 +00:00
|
|
|
|
2023-06-15 21:17:48 +00:00
|
|
|
let atlas_index, rotation;
|
2023-06-13 03:47:43 +00:00
|
|
|
switch(type) {
|
|
|
|
case Direction.EMPTY:
|
2023-06-15 21:17:48 +00:00
|
|
|
return
|
2023-06-13 03:47:43 +00:00
|
|
|
case Direction.WALL_HZ:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [1, 1]
|
|
|
|
rotation = 0
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.WALL_VT:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [1, 1]
|
|
|
|
rotation = 90
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.TURN_Q1:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [2, 0]
|
|
|
|
rotation = 0
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.TURN_Q2:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [2, 0]
|
|
|
|
rotation = 270
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.TURN_Q3:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [2, 0]
|
|
|
|
rotation = 180
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.TURN_Q4:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [2, 0]
|
|
|
|
rotation = 90
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.TEE_NORTH:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [1, 0]
|
|
|
|
rotation = 180
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.TEE_EAST:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [1, 0]
|
|
|
|
rotation = 270
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.TEE_SOUTH:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [1, 0]
|
|
|
|
rotation = 0
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.TEE_WEST:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [1, 0]
|
|
|
|
rotation = 90
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.CROSS:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [0, 0]
|
|
|
|
rotation = 0
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.DOT:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [2, 1]
|
|
|
|
rotation = 0
|
2023-06-13 03:47:43 +00:00
|
|
|
break
|
|
|
|
case Direction.WALL_END_NORTH:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [0, 1]
|
|
|
|
rotation = 0
|
2023-06-13 03:47:43 +00:00
|
|
|
break;
|
|
|
|
case Direction.WALL_END_EAST:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [0, 1]
|
|
|
|
rotation = 90
|
2023-06-13 03:47:43 +00:00
|
|
|
break;
|
|
|
|
case Direction.WALL_END_SOUTH:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [0, 1]
|
|
|
|
rotation = 180
|
2023-06-13 03:47:43 +00:00
|
|
|
break;
|
|
|
|
case Direction.WALL_END_WEST:
|
2023-06-15 21:17:48 +00:00
|
|
|
atlas_index = [0, 1]
|
|
|
|
rotation = 270
|
2023-06-13 03:47:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-06-15 21:17:48 +00:00
|
|
|
let atlas = document.getElementById("atlas")
|
|
|
|
context.save()
|
|
|
|
context.translate((x+.5)*w, (y+.5)*w)
|
|
|
|
context.rotate(rotation * Math.PI / 180)
|
|
|
|
context.drawImage(atlas, atlas_index[0]*w, atlas_index[1]*w, w, w, -w/2, -w/2, w, w)
|
|
|
|
context.restore()
|
2023-06-13 03:47:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const get_point = (width, height, data, x, y) => {
|
|
|
|
if (x < 0 || x >= width || y < 0 || y >= height) {
|
|
|
|
return 0
|
|
|
|
} else {
|
|
|
|
return data[y * width + x]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const gen_walls = (width, height, data) => {
|
|
|
|
|
|
|
|
let walls = Array(width * height)
|
|
|
|
for (let y = 0; y < height; y++) {
|
|
|
|
for (let x = 0; x < width; x++) {
|
|
|
|
|
2023-06-15 03:22:26 +00:00
|
|
|
let north = get_point(width, height, data, x, y-1) == 1
|
|
|
|
let south = get_point(width, height, data, x, y+1) == 1
|
|
|
|
let east = get_point(width, height, data, x+1, y) == 1
|
|
|
|
let west = get_point(width, height, data, x-1, y) == 1
|
|
|
|
let current = get_point(width, height, data, x, y) == 1
|
2023-06-13 03:47:43 +00:00
|
|
|
|
|
|
|
let point = Direction.EMPTY
|
|
|
|
|
|
|
|
if (!current) {
|
|
|
|
walls[y * width + x] = point
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if (north && south && east && west) {
|
|
|
|
point = Direction.CROSS
|
|
|
|
} else if (east && west && north) {
|
|
|
|
point = Direction.TEE_NORTH
|
|
|
|
} else if (east && west && south) {
|
|
|
|
point = Direction.TEE_SOUTH
|
|
|
|
} else if (north && south && east) {
|
|
|
|
point = Direction.TEE_EAST
|
|
|
|
} else if (north && south && west) {
|
|
|
|
point = Direction.TEE_WEST
|
|
|
|
} else if (east && west) {
|
|
|
|
point = Direction.WALL_HZ
|
|
|
|
} else if (north && south) {
|
|
|
|
point = Direction.WALL_VT
|
|
|
|
} else if (west && south) {
|
|
|
|
point = Direction.TURN_Q1
|
|
|
|
} else if (south && east) {
|
|
|
|
point = Direction.TURN_Q2
|
|
|
|
} else if (east && north) {
|
|
|
|
point = Direction.TURN_Q3
|
|
|
|
} else if (north && west) {
|
|
|
|
point = Direction.TURN_Q4
|
|
|
|
} else if (north) {
|
|
|
|
point = Direction.WALL_END_NORTH
|
|
|
|
} else if (east) {
|
|
|
|
point = Direction.WALL_END_EAST
|
|
|
|
} else if (south) {
|
|
|
|
point = Direction.WALL_END_SOUTH
|
|
|
|
} else if (west) {
|
|
|
|
point = Direction.WALL_END_WEST
|
|
|
|
} else {
|
|
|
|
point = Direction.DOT
|
|
|
|
}
|
|
|
|
|
|
|
|
walls[y * width + x] = point
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return walls
|
|
|
|
}
|
|
|
|
|
2023-06-15 21:17:48 +00:00
|
|
|
const update_canvas = (map, canvas) => {
|
|
|
|
let context = canvas.getContext("2d");
|
2023-06-13 03:47:43 +00:00
|
|
|
for (let y = 0; y < map.height; y++) {
|
|
|
|
for (let x = 0; x < map.width; x++) {
|
2023-06-15 21:17:48 +00:00
|
|
|
draw_tile(context, x, y, map.tile_width, map.walls[y * map.width + x])
|
2023-06-13 03:47:43 +00:00
|
|
|
}
|
|
|
|
}
|
2023-06-15 03:22:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const gen_items = (map) => {
|
|
|
|
|
|
|
|
let width = map.width
|
|
|
|
let height = map.height
|
|
|
|
|
|
|
|
let items = {}
|
|
|
|
|
|
|
|
for (let y = 0; y < height; y++) {
|
|
|
|
for (let x = 0; x < width; x++) {
|
|
|
|
let tile = get_point(width, height, map.data, x, y)
|
|
|
|
if (tile != 0) continue
|
|
|
|
|
|
|
|
let item_key = get_item_key(x, y, width)
|
|
|
|
items[item_key] = {type: ItemType.DOT, pos: [x, y]}
|
|
|
|
|
|
|
|
let tile_south = get_point(width, height, map.data, x, y + 1)
|
|
|
|
if (tile_south == 0) {
|
|
|
|
item_key = get_item_key(x, y + .5, width)
|
|
|
|
items[item_key] = {type: ItemType.DOT, pos: [x, y + .5]}
|
|
|
|
}
|
|
|
|
|
|
|
|
let tile_east = get_point(width, height, map.data, x + 1, y)
|
|
|
|
if (tile_east == 0) {
|
|
|
|
item_key = get_item_key(x + .5, y, width)
|
|
|
|
items[item_key] = {type: ItemType.DOT, pos: [x + .5, y]}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-06-13 03:47:43 +00:00
|
|
|
|
2023-06-15 03:22:26 +00:00
|
|
|
return items
|
2023-06-13 03:47:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export class Map {
|
|
|
|
|
2023-06-15 03:22:26 +00:00
|
|
|
static data
|
|
|
|
static walls
|
|
|
|
|
2023-06-13 03:47:43 +00:00
|
|
|
constructor(width, height, data) {
|
2023-06-14 01:18:01 +00:00
|
|
|
|
2023-06-13 03:47:43 +00:00
|
|
|
this.width = width
|
|
|
|
this.height = height
|
|
|
|
this.data = data
|
2023-06-14 01:18:01 +00:00
|
|
|
this.walls = gen_walls(width, height, data)
|
2023-06-15 03:22:26 +00:00
|
|
|
this.items = gen_items(this)
|
|
|
|
this.visible = false
|
2023-06-15 21:17:48 +00:00
|
|
|
this.tile_width = 32
|
|
|
|
|
|
|
|
canvas.width = this.width * this.tile_width
|
|
|
|
canvas.height = this.height * this.tile_width
|
|
|
|
|
|
|
|
|
2023-06-13 03:47:43 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-06-14 01:18:01 +00:00
|
|
|
show() {
|
|
|
|
|
|
|
|
let container = document.getElementById("container")
|
2023-06-15 21:17:48 +00:00
|
|
|
container.style.display = ""
|
|
|
|
|
|
|
|
let canvas = document.getElementById("canvas")
|
|
|
|
canvas.style.display = ""
|
2023-06-14 01:18:01 +00:00
|
|
|
|
|
|
|
let style = document.getElementById("style")
|
2023-06-15 21:17:48 +00:00
|
|
|
|
|
|
|
update_canvas(this, canvas)
|
|
|
|
update_style(this, style)
|
2023-06-15 03:22:26 +00:00
|
|
|
|
|
|
|
this.visible = true
|
2023-06-13 03:47:43 +00:00
|
|
|
}
|
|
|
|
|
2023-06-14 01:18:01 +00:00
|
|
|
hide() {
|
2023-06-15 21:17:48 +00:00
|
|
|
|
|
|
|
let canvas = document.getElementById("canvas")
|
|
|
|
canvas.style.display = "none"
|
|
|
|
container.style.display = "none"
|
2023-06-15 03:22:26 +00:00
|
|
|
|
|
|
|
this.visible = false
|
2023-06-14 01:18:01 +00:00
|
|
|
}
|
2023-06-13 03:47:43 +00:00
|
|
|
}
|