diff options
Diffstat (limited to 'client/src')
-rw-r--r-- | client/src/editor.ts | 56 | ||||
-rw-r--r-- | client/src/lib/lz-string.ts | 505 | ||||
-rw-r--r-- | client/src/logic/logic.ts | 50 | ||||
-rw-r--r-- | client/src/main.ts | 5 | ||||
-rw-r--r-- | client/src/map.ts | 76 | ||||
-rw-r--r-- | client/src/renderer.ts | 24 | ||||
-rw-r--r-- | client/src/types.ts | 26 |
7 files changed, 636 insertions, 106 deletions
diff --git a/client/src/editor.ts b/client/src/editor.ts index 77088ce..1abaad4 100644 --- a/client/src/editor.ts +++ b/client/src/editor.ts @@ -1,11 +1,11 @@ -import { genMap } from "./map.js" +import { genMap, compressMap, decompressMap } from "./map.js" import { startGraphicsUpdater } from "./renderer.js" import { GameState, Vec2, Tile } from "./types.js" const mapgen = document.getElementById("mapgen") const sidebar = document.getElementById("sidebar") -mapgen.onsubmit = async function(event) { +mapgen.onsubmit = async (event) => { event.preventDefault() const width_str = (<HTMLInputElement>document.getElementById("width")).value @@ -86,31 +86,33 @@ const getTilePos = (width: number, height: number, mousePos: Vec2): Vec2 => { } -const checkInputs = (pressed: {[key: string]: boolean}): Tile => { +const checkInputs = (pressed: {[key: string]: boolean}): [Tile, boolean] => { if (pressed["KeyW"]) { - return Tile.WALL + return [Tile.WALL, false] } else if (pressed["KeyG"]) { - return Tile.GHOST_WALL + return [Tile.GHOST_WALL, false] + } else if (pressed["KeyH"]) { + return [Tile.GHOST_SPAWN, true] } else if (pressed["KeyF"]) { - return Tile.FOOD + return [Tile.FOOD, false] } else if (pressed["Digit1"]) { - return Tile.PLAYER_SPAWN_1 + return [Tile.PLAYER_SPAWN_1, true] } else if (pressed["Digit2"]) { - return Tile.PLAYER_SPAWN_2 + return [Tile.PLAYER_SPAWN_2, true] } else if (pressed["Digit3"]) { - return Tile.PLAYER_SPAWN_3 + return [Tile.PLAYER_SPAWN_3, true] } else if (pressed["Digit4"]) { - return Tile.PLAYER_SPAWN_4 + return [Tile.PLAYER_SPAWN_4, true] } else if (pressed["KeyT"]) { - return Tile.THICC_DOT + return [Tile.THICC_DOT, false] } else if (pressed["KeyI"]) { - return Tile.INITIAL_DOT + return [Tile.INITIAL_DOT, false] } else if (pressed["KeyC"]) { - return Tile.EMPTY + return [Tile.EMPTY, false] } - return undefined + return [undefined, undefined] } const checkBounds = (tilePos: Vec2, width: number, height: number) => { @@ -124,7 +126,7 @@ const runMapEditor = (width: number, height: number) => { let data: number[] = new Array(width * height).fill(0) - genMap(width, height, data, Tile.EMPTY) + let map = genMap(width, height, data, Tile.EMPTY) let state: GameState = { started: true, @@ -145,13 +147,19 @@ const runMapEditor = (width: number, height: number) => { const tilePos = getTilePos(width, height, mousePos) const pressed = getInput() - const tile = checkInputs(pressed) + const [tile, unique] = checkInputs(pressed) if (tile !== undefined && checkBounds(tilePos, width, height)) { let current = data[tilePos.y * width + tilePos.x]; - if (current != tile) { + if (current != tile && (current == Tile.EMPTY || tile == Tile.EMPTY)) { + if (unique) { + data = data.map(t => { + if (t == tile) return Tile.EMPTY + else return t + }) + } data[tilePos.y * width + tilePos.x] = tile - genMap(width, height, data, 0) + map = genMap(width, height, data, 0) } } @@ -162,4 +170,16 @@ const runMapEditor = (width: number, height: number) => { requestAnimationFrame(loop) + document.getElementById("export").onclick = () => { + let encoded = compressMap(map) + document.getElementById("textarea").textContent = encoded + document.getElementById("popup").style.display = 'flex' + + console.log(decompressMap(encoded)) + } + + document.getElementById("copy").onclick = () => { + navigator.clipboard.writeText(document.getElementById("textarea").textContent) + } + } diff --git a/client/src/lib/lz-string.ts b/client/src/lib/lz-string.ts new file mode 100644 index 0000000..68270d0 --- /dev/null +++ b/client/src/lib/lz-string.ts @@ -0,0 +1,505 @@ +export namespace LZString { + // private property + var f = String.fromCharCode; + var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$"; + var baseReverseDic = {}; + + function getBaseValue(alphabet: any, character: any) { + if (!baseReverseDic[alphabet]) { + baseReverseDic[alphabet] = {}; + for (var i = 0; i < alphabet.length; i++) { + baseReverseDic[alphabet][alphabet.charAt(i)] = i; + } + } + return baseReverseDic[alphabet][character]; + } + + export function compressToBase64(input:string) { + if (input == null) return ""; + var res = _compress(input, 6, function (a: any) { + return keyStrBase64.charAt(a); + }); + switch (res.length % 4) { // To produce valid Base64 + default: // When could this happen ? + case 0: + return res; + case 1: + return res + "==="; + case 2: + return res + "=="; + case 3: + return res + "="; + } + } + + export function decompressFromBase64(input:string) { + if (input == null) return ""; + if (input == "") return null; + return _decompress(input.length, 32, function (index: any) { + return getBaseValue(keyStrBase64, input.charAt(index)); + }); + } + + export function compressToUTF16(input:string) { + if (input == null) return ""; + return _compress(input, 15, function (a: any) { + return f(a + 32); + }) + " "; + } + + export function decompressFromUTF16(compressed:string) { + if (compressed == null) return ""; + if (compressed == "") return null; + return _decompress(compressed.length, 16384, function (index: any) { + return compressed.charCodeAt(index) - 32; + }); + } + + //compress into uint8array (UCS-2 big endian format) + export function compressToUint8Array(uncompressed:string) { + var compressed = compress(uncompressed); + var buf = new Uint8Array(compressed.length * 2); // 2 bytes per character + + for (var i = 0, TotalLen = compressed.length; i < TotalLen; i++) { + var current_value = compressed.charCodeAt(i); + buf[i * 2] = current_value >>> 8; + buf[i * 2 + 1] = current_value % 256; + } + return buf; + } + + //decompress from uint8array (UCS-2 big endian format) + export function decompressFromUint8Array(compressed: any) { + if (compressed === null || compressed === undefined) { + return decompress(compressed); + } else { + var buf = new Array(compressed.length / 2); // 2 bytes per character + for (var i = 0, TotalLen = buf.length; i < TotalLen; i++) { + buf[i] = compressed[i * 2] * 256 + compressed[i * 2 + 1]; + } + + var result = []; + buf.forEach(function (c) { + result.push(f(c)); + }); + return decompress(result.join('')); + + } + + } + + + //compress into a string that is already URI encoded + export function compressToEncodedURIComponent(input:string) { + if (input == null) return ""; + return _compress(input, 6, function (a: any) { + return keyStrUriSafe.charAt(a); + }); + } + + //decompress from an output of compressToEncodedURIComponent + export function decompressFromEncodedURIComponent(input:string) { + if (input == null) return ""; + if (input == "") return null; + input = input.replace(/ /g, "+"); + return _decompress(input.length, 32, function (index: any) { + return getBaseValue(keyStrUriSafe, input.charAt(index)); + }); + } + + export function compress(uncompressed:string) { + return _compress(uncompressed, 16, function (a: any) { + return f(a); + }); + } + + function _compress(uncompressed: any, bitsPerChar: any, getCharFromInt: any) { + if (uncompressed == null) return ""; + var i: any, value: any, + context_dictionary = {}, + context_dictionaryToCreate = {}, + context_c = "", + context_wc = "", + context_w = "", + context_enlargeIn = 2, // Compensate for the first entry which should not count + context_dictSize = 3, + context_numBits = 2, + context_data = [], + context_data_val = 0, + context_data_position = 0, + ii: any; + + for (ii = 0; ii < uncompressed.length; ii += 1) { + context_c = uncompressed.charAt(ii); + if (!Object.prototype.hasOwnProperty.call(context_dictionary, context_c)) { + context_dictionary[context_c] = context_dictSize++; + context_dictionaryToCreate[context_c] = true; + } + + context_wc = context_w + context_c; + if (Object.prototype.hasOwnProperty.call(context_dictionary, context_wc)) { + context_w = context_wc; + } else { + if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate, context_w)) { + if (context_w.charCodeAt(0) < 256) { + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + } + value = context_w.charCodeAt(0); + for (i = 0; i < 8; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = value >> 1; + } + } else { + value = 1; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | value; + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = 0; + } + value = context_w.charCodeAt(0); + for (i = 0; i < 16; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = value >> 1; + } + } + context_enlargeIn--; + if (context_enlargeIn == 0) { + context_enlargeIn = Math.pow(2, context_numBits); + context_numBits++; + } + delete context_dictionaryToCreate[context_w]; + } else { + value = context_dictionary[context_w]; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = value >> 1; + } + + + } + context_enlargeIn--; + if (context_enlargeIn == 0) { + context_enlargeIn = Math.pow(2, context_numBits); + context_numBits++; + } + // Add wc to the dictionary. + context_dictionary[context_wc] = context_dictSize++; + context_w = String(context_c); + } + } + + // Output the code for w. + if (context_w !== "") { + if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate, context_w)) { + if (context_w.charCodeAt(0) < 256) { + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + } + value = context_w.charCodeAt(0); + for (i = 0; i < 8; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = value >> 1; + } + } else { + value = 1; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | value; + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = 0; + } + value = context_w.charCodeAt(0); + for (i = 0; i < 16; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = value >> 1; + } + } + context_enlargeIn--; + if (context_enlargeIn == 0) { + context_enlargeIn = Math.pow(2, context_numBits); + context_numBits++; + } + delete context_dictionaryToCreate[context_w]; + } else { + value = context_dictionary[context_w]; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = value >> 1; + } + + + } + context_enlargeIn--; + if (context_enlargeIn == 0) { + context_enlargeIn = Math.pow(2, context_numBits); + context_numBits++; + } + } + + // Mark the end of the stream + value = 2; + for (i = 0; i < context_numBits; i++) { + context_data_val = (context_data_val << 1) | (value & 1); + if (context_data_position == bitsPerChar - 1) { + context_data_position = 0; + context_data.push(getCharFromInt(context_data_val)); + context_data_val = 0; + } else { + context_data_position++; + } + value = value >> 1; + } + + // Flush the last char + while (true) { + context_data_val = (context_data_val << 1); + if (context_data_position == bitsPerChar - 1) { + context_data.push(getCharFromInt(context_data_val)); + break; + } else context_data_position++; + } + return context_data.join(''); + } + + export function decompress(compressed:string) { + if (compressed == null) return ""; + if (compressed == "") return null; + return _decompress(compressed.length, 32768, function (index: any) { + return compressed.charCodeAt(index); + }); + } + + function _decompress(length: any, resetValue: any, getNextValue: any) { + var dictionary = [], + next: any, + enlargeIn = 4, + dictSize = 4, + numBits = 3, + entry = "", + result = [], + i: any, + w: any, + bits: any, resb: any, maxpower: any, power: any, + c: any, + data = { + val: getNextValue(0), + position: resetValue, + index: 1 + }; + + for (i = 0; i < 3; i += 1) { + dictionary[i] = i; + } + + bits = 0; + maxpower = Math.pow(2, 2); + power = 1; + while (power != maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position == 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + + switch (next = bits) { + case 0: + bits = 0; + maxpower = Math.pow(2, 8); + power = 1; + while (power != maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position == 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + c = f(bits); + break; + case 1: + bits = 0; + maxpower = Math.pow(2, 16); + power = 1; + while (power != maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position == 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + c = f(bits); + break; + case 2: + return ""; + } + dictionary[3] = c; + w = c; + result.push(c); + while (true) { + if (data.index > length) { + return ""; + } + + bits = 0; + maxpower = Math.pow(2, numBits); + power = 1; + while (power != maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position == 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + + switch (c = bits) { + case 0: + bits = 0; + maxpower = Math.pow(2, 8); + power = 1; + while (power != maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position == 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + + dictionary[dictSize++] = f(bits); + c = dictSize - 1; + enlargeIn--; + break; + case 1: + bits = 0; + maxpower = Math.pow(2, 16); + power = 1; + while (power != maxpower) { + resb = data.val & data.position; + data.position >>= 1; + if (data.position == 0) { + data.position = resetValue; + data.val = getNextValue(data.index++); + } + bits |= (resb > 0 ? 1 : 0) * power; + power <<= 1; + } + dictionary[dictSize++] = f(bits); + c = dictSize - 1; + enlargeIn--; + break; + case 2: + return result.join(''); + } + + if (enlargeIn == 0) { + enlargeIn = Math.pow(2, numBits); + numBits++; + } + + if (dictionary[c]) { + entry = dictionary[c]; + } else { + if (c === dictSize) { + entry = w + w.charAt(0); + } else { + return null; + } + } + result.push(entry); + + // Add w+entry[0] to the dictionary. + dictionary[dictSize++] = w + entry.charAt(0); + enlargeIn--; + + w = entry; + + if (enlargeIn == 0) { + enlargeIn = Math.pow(2, numBits); + numBits++; + } + } + } +}; diff --git a/client/src/logic/logic.ts b/client/src/logic/logic.ts index 1cca2b7..dd6e21d 100644 --- a/client/src/logic/logic.ts +++ b/client/src/logic/logic.ts @@ -1,10 +1,13 @@ -import { genItems, loadMap, getMap } from "../map.js"; +import { genItems, genMap, getMap, decompressMap } from "../map.js"; import { updatePlayers } from "./players.js" import { updateUI } from "./ui.js" import { updateMovement } from "./movement.js" import { updateItems } from "./items.js" import { GameState, Input } from "../types.js"; +const maps = { + [0]: 'EwRgPqYgNDew+TEuW6AGT2u59mPI/PeLZclSys1AhSgThJcJb2bdq7p5rupV2DYaVFCKI9HwFDiWACyxyK5WpCqArOPSCeuqfUnzDwaGbMyT3FAGZT0ABznD9ybWv0LLq61kz4S0M9WRMANnVVDUi1AHYdQxt+dyNEhJNiNk8A3npkiVSmcUEM6E5C/wL86rlivLqxaVymltggA=' +} export const InitialState: GameState = { started: false, @@ -32,7 +35,7 @@ export const onLogic = ( } if (startPressed && !data.started) { - initMap(data) + initMap(data, 0) data.started = true; } @@ -40,41 +43,16 @@ export const onLogic = ( } -const initMap = (data: GameState) => { - - document.getElementById("lobby").style.display = "none" - - data.mapId = 0 +const initMap = (gameData: GameState, mapId: number) => { - if (getMap(0)) return + gameData.mapId = mapId - let width = 21 - let height = 21 - let m_data = [ - 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,1,0,0,0,0,0,0,0,0,0,1, - 1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1, - 1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1, - 1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1, - 1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1, - 1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,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,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,1, - 1,0,0,0,0,0,1,0,1,2,2,2,1,0,1,0,0,0,0,0,1, - 1,0,1,1,1,0,1,0,1,2,2,2,1,0,1,0,1,1,1,0,1, - 1,0,0,0,0,0,1,0,1,2,2,2,1,0,1,0,0,0,0,0,1, - 1,1,1,0,1,0,1,0,1,1,2,1,1,0,1,0,1,0,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,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,0,1, - 1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,1, - 1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1, - 1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1, - 1,0,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,1, - 1,0,0,0,0,0,0,0,0,0,1,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 - ] - - loadMap(width, height, m_data) // cursed temp thing - data.items = genItems(getMap(0)) + let map = getMap(mapId) + if (!map) { + let {width, height, data} = decompressMap(maps[mapId]) + map = genMap(width, height, data, mapId) + } + + gameData.items = genItems(map) } diff --git a/client/src/main.ts b/client/src/main.ts index 7ac13a3..b5ea424 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -1,7 +1,7 @@ import { Game } from "./net/game.js"; import { InitialState, onLogic } from "./logic/logic.js"; import { startGraphicsUpdater } from "./renderer.js"; -import { GameKeyMap, Frame, Key } from "./types.js"; +import { GameKeyMap, Frame, Key, Player } from "./types.js"; const join = document.getElementById("join") const lobby = document.getElementById("lobby") @@ -42,7 +42,7 @@ const onLoad = (startData: Frame) => { return false } - let players = Object.values(startData.data.players).filter(p => { return p !== null && p.name !== undefined }) + let players = Object.values(startData.data.players).filter((p: Player): boolean => p !== null && p.name !== undefined) if (players.length >= 4) { alert('Room is full') return false @@ -59,7 +59,6 @@ const onFrame = (data: Frame, frame: number) => { } - const startGame = (code: string, name: string) => { const game = new Game(3000) diff --git a/client/src/map.ts b/client/src/map.ts index d26c467..1ad6d63 100644 --- a/client/src/map.ts +++ b/client/src/map.ts @@ -1,4 +1,5 @@ -import { Wall, ItemType, Map, Maps, Items } from "./types.js" +import { Wall, ItemType, Map, Maps, Items, Tile } from "./types.js" +import { LZString } from "./lib/lz-string.js" export const getItemKey = ( x: number, @@ -90,6 +91,8 @@ const genWalls = ( return walls } +const canItem = (tile: Tile): boolean => tile != Tile.WALL && tile != Tile.GHOST_WALL && tile != Tile.GHOST_SPAWN + export const genItems = (map: Map): Items => { let width = map.width @@ -101,21 +104,35 @@ export const genItems = (map: Map): Items => { for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { let tile = getPoint(width, height, data, x, y) - if (tile != 0) continue + if (!canItem(tile)) continue let item_key = getItemKey(x, y, width) - items[item_key] = {type: ItemType.DOT, pos: {x, y}} - let tile_south = getPoint(width, height, data, x, y + 1) - if (tile_south == 0) { - item_key = getItemKey(x, y + .5, width) - items[item_key] = {type: ItemType.DOT, pos: {x, y: y + .5}} - } + let type: ItemType + + if (tile == Tile.FOOD) + type = ItemType.FOOD + else if (tile == Tile.THICC_DOT) + type = ItemType.THICC_DOT + else + type = ItemType.DOT + + items[item_key] = {type, pos: {x, y}} - let tile_east = getPoint(width, height, data, x + 1, y) - if (tile_east == 0) { - item_key = getItemKey(x + .5, y, width) - items[item_key] = {type: ItemType.DOT, pos: {x: x + .5, y}} + if (type == ItemType.DOT || type == ItemType.THICC_DOT) { + type = ItemType.DOT + + let tile_south = getPoint(width, height, data, x, y + 1) + if (canItem(tile_south) && tile_south != Tile.FOOD) { + item_key = getItemKey(x, y + .5, width) + items[item_key] = {type, pos: {x, y: y + .5}} + } + + let tile_east = getPoint(width, height, data, x + 1, y) + if (canItem(tile_east) && tile_east != Tile.FOOD) { + item_key = getItemKey(x + .5, y, width) + items[item_key] = {type, pos: {x: x + .5, y}} + } } } } @@ -124,7 +141,6 @@ export const genItems = (map: Map): Items => { } let mapData: Maps = {} -let id: number = 0 export const genMap = ( width: number, @@ -144,26 +160,22 @@ export const genMap = ( return mapData[mapId] } -export const loadMap = ( - width: number, - height: number, - data: number[] -): number => { - - let mapId = id++ - - mapData[mapId] = { - data: structuredClone(data), - walls: genWalls(width, height, data), - width, - height, - id: mapId - } - - return mapId -} - export const getMap = (mapId: number): Map | undefined => { if (mapId == undefined) return undefined return mapData[mapId] } + +export const compressMap = (map: Map): string => { + let encoded = map.width + '|' + map.height + '|' + map.data.map(n => n + ',').join('').slice(0, -1) + return LZString.compressToBase64(encoded) +} + +export const decompressMap = (encoded: string): {width: number, height: number, data: number[]} => { + let decoded = LZString.decompressFromBase64(encoded) + let values = decoded.split('|') + let width = parseInt(values[0]) + let height = parseInt(values[1]) + let data = values[2].split(',').map(c => parseInt(c)) + + return {width, height, data} +} diff --git a/client/src/renderer.ts b/client/src/renderer.ts index 8482ca6..bc6cf83 100644 --- a/client/src/renderer.ts +++ b/client/src/renderer.ts @@ -137,9 +137,17 @@ const draw_items = ( let width: number, atlas_index: [number, number] switch (item.type) { case ItemType.DOT: - width = .2, + width = .2 atlas_index = [2, 3] break + case ItemType.THICC_DOT: + width = .4 + atlas_index = [2, 3] + break + case ItemType.FOOD: + width = 1 + atlas_index = [3, 3] + break default: continue } @@ -267,6 +275,7 @@ const draw_debug_sprites = ( let tile_type = map.data[y * map.width + x] + let size = 1 let atlas_index: [number, number]; switch (tile_type) { case Tile.EMPTY: @@ -275,9 +284,12 @@ const draw_debug_sprites = ( case Tile.GHOST_WALL: atlas_index = [4, 0] break - case Tile.FOOD: + case Tile.GHOST_SPAWN: atlas_index = [3, 0] break + case Tile.FOOD: + atlas_index = [3, 3] + break case Tile.PLAYER_SPAWN_1: atlas_index = [3, 1] break @@ -291,10 +303,12 @@ const draw_debug_sprites = ( atlas_index = [4, 2] break case Tile.THICC_DOT: - atlas_index = [4, 3] + atlas_index = [2, 3] + size = .4 break case Tile.INITIAL_DOT: - atlas_index = [3, 3] + atlas_index = [2, 3] + size = .2 break } @@ -302,7 +316,7 @@ const draw_debug_sprites = ( ctx, x, y, - 1, + size, atlas, atlas_index, ATLAS_TILE_WIDTH, diff --git a/client/src/types.ts b/client/src/types.ts index 02d5adb..c130980 100644 --- a/client/src/types.ts +++ b/client/src/types.ts @@ -2,17 +2,17 @@ export const ATLAS_TILE_WIDTH = 32 export enum Tile { - EMPTY, - WALL, - GHOST_WALL, - FOOD, - PLAYER_SPAWN_1, - PLAYER_SPAWN_2, - PLAYER_SPAWN_3, - PLAYER_SPAWN_4, - GHOST_SPAWN, - THICC_DOT, - INITIAL_DOT + EMPTY = 0, + WALL = 1, + GHOST_WALL = 2, + FOOD = 3, + PLAYER_SPAWN_1 = 4, + PLAYER_SPAWN_2 = 5, + PLAYER_SPAWN_3 = 6, + PLAYER_SPAWN_4 = 7, + GHOST_SPAWN = 8, + THICC_DOT = 9, + INITIAL_DOT = 10 } export enum Wall { @@ -36,7 +36,9 @@ export enum Wall { } export enum ItemType { - DOT + DOT, + THICC_DOT, + FOOD } export enum Key { |