import { ItemType, get_item_key } from "../logic.js"; const update_style = (map, style) => { const css = ` * { --scale: 100; --aspect: ${map.width/map.height}; --scaleX: calc(var(--scale) * 1vw); --scaleY: calc(var(--scale) * 1vh); } #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; vertical-align: top; line-height: 0; } @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); } }`; style.innerHTML = css } 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 } /** * @param {CanvasRenderingContext2D} context */ const draw_tile = (context, x, y, w, type) => { let atlas_index, rotation; switch(type) { case Direction.EMPTY: return case Direction.WALL_HZ: atlas_index = [1, 1] rotation = 0 break case Direction.WALL_VT: atlas_index = [1, 1] rotation = 90 break case Direction.TURN_Q1: atlas_index = [2, 0] rotation = 0 break case Direction.TURN_Q2: atlas_index = [2, 0] rotation = 270 break case Direction.TURN_Q3: atlas_index = [2, 0] rotation = 180 break case Direction.TURN_Q4: atlas_index = [2, 0] rotation = 90 break case Direction.TEE_NORTH: atlas_index = [1, 0] rotation = 180 break case Direction.TEE_EAST: atlas_index = [1, 0] rotation = 270 break case Direction.TEE_SOUTH: atlas_index = [1, 0] rotation = 0 break case Direction.TEE_WEST: atlas_index = [1, 0] rotation = 90 break case Direction.CROSS: atlas_index = [0, 0] rotation = 0 break case Direction.DOT: atlas_index = [2, 1] rotation = 0 break case Direction.WALL_END_NORTH: atlas_index = [0, 1] rotation = 0 break; case Direction.WALL_END_EAST: atlas_index = [0, 1] rotation = 90 break; case Direction.WALL_END_SOUTH: atlas_index = [0, 1] rotation = 180 break; case Direction.WALL_END_WEST: atlas_index = [0, 1] rotation = 270 break; } 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() } 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++) { 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 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 } const update_canvas = (map, canvas) => { let context = canvas.getContext("2d"); for (let y = 0; y < map.height; y++) { for (let x = 0; x < map.width; x++) { draw_tile(context, x, y, map.tile_width, map.walls[y * map.width + x]) } } } 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]} } } } return items } export class Map { static data static walls constructor(width, height, data) { this.width = width this.height = height this.data = data this.walls = gen_walls(width, height, data) this.items = gen_items(this) this.visible = false this.tile_width = 32 canvas.width = this.width * this.tile_width canvas.height = this.height * this.tile_width } show() { let container = document.getElementById("container") container.style.display = "" let canvas = document.getElementById("canvas") canvas.style.display = "" let style = document.getElementById("style") update_canvas(this, canvas) update_style(this, style) this.visible = true } hide() { let canvas = document.getElementById("canvas") canvas.style.display = "none" container.style.display = "none" this.visible = false } }