diff options
author | Tyler Murphy <tylerm@tylerm.dev> | 2023-06-16 20:38:55 -0400 |
---|---|---|
committer | Tyler Murphy <tylerm@tylerm.dev> | 2023-06-16 20:38:55 -0400 |
commit | 44334fc3852eb832280a335f72e6416c93a9f19f (patch) | |
tree | 4a97b6064a97c4ad58c07d89050ad8a11e7a4f70 /client/src/logic | |
parent | better map bg renderer (diff) | |
download | tuxman-44334fc3852eb832280a335f72e6416c93a9f19f.tar.gz tuxman-44334fc3852eb832280a335f72e6416c93a9f19f.tar.bz2 tuxman-44334fc3852eb832280a335f72e6416c93a9f19f.zip |
ts
Diffstat (limited to 'client/src/logic')
-rw-r--r-- | client/src/logic/items.ts | 41 | ||||
-rw-r--r-- | client/src/logic/logic.ts | 80 | ||||
-rw-r--r-- | client/src/logic/movement.ts | 142 | ||||
-rw-r--r-- | client/src/logic/players.ts | 79 | ||||
-rw-r--r-- | client/src/logic/ui.ts | 32 |
5 files changed, 374 insertions, 0 deletions
diff --git a/client/src/logic/items.ts b/client/src/logic/items.ts new file mode 100644 index 0000000..5f8a38e --- /dev/null +++ b/client/src/logic/items.ts @@ -0,0 +1,41 @@ +import { getMap, getItemKey } from "../map.js" +import { GameState, Map, Player } from "../types.js" + +const ceilHalf = (n: number): number => { + return Math.ceil(n*2)/2 +} + +const floorHalf = (n: number): number => { + return Math.floor(n*2)/2 +} + +const eatItems = (data: GameState, map: Map, player: Player) => { + + let pos = player.pos + + for (let x = ceilHalf(pos.x-.5); x <= floorHalf(pos.x+.5); x += .5) { + for (let y = ceilHalf(pos.y-.5); y <= floorHalf(pos.y+.5); y += .5) { + let item_key = getItemKey(x, y, map.width) + delete data.items[item_key] + } + } +} + +export const updateItems = (data: GameState) => { + + let map = getMap(data.mapId) + if (!map) return + + for(const id in data.input) { + + const player = data.players[id] + + if(!player) { + continue; + } + + eatItems(data, map, player) + + } + +} diff --git a/client/src/logic/logic.ts b/client/src/logic/logic.ts new file mode 100644 index 0000000..1cca2b7 --- /dev/null +++ b/client/src/logic/logic.ts @@ -0,0 +1,80 @@ +import { genItems, loadMap, getMap } 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"; + + +export const InitialState: GameState = { + started: false, + input: {}, + players: [], + items: {}, + mapId: undefined +} + +export const onLogic = ( + pastData: GameState = InitialState, + input: Input = { players: {} }, + _frame: number +) => { + + let data = structuredClone(pastData) + + let startPressed = updatePlayers(data, input); + + if (data.started) { + updateMovement(data) + updateItems(data) + } else { + updateUI(data) + } + + if (startPressed && !data.started) { + initMap(data) + data.started = true; + } + + return data + +} + +const initMap = (data: GameState) => { + + document.getElementById("lobby").style.display = "none" + + data.mapId = 0 + + if (getMap(0)) return + + 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)) +} + diff --git a/client/src/logic/movement.ts b/client/src/logic/movement.ts new file mode 100644 index 0000000..40cfc3e --- /dev/null +++ b/client/src/logic/movement.ts @@ -0,0 +1,142 @@ +import { getMap } from "../map.js" +import { Vec2, Map, Rotation, Key, Player, GameState } from "../types.js" + +const MOVE_SPEED = .1 + +const roundPos = (pos: Vec2): Vec2 => { + return {x: Math.round(pos.x), y: Math.round(pos.y)} +} + +const isStablePos = (pos: Vec2): boolean => { + let rpos = roundPos(pos) + return Math.abs(rpos.x - pos.x) < .05 && Math.abs(rpos.y - pos.y) < .05 +} + +const getTile = ( + map: Map, + pos: Vec2, + ox: number, + oy: number +): number => { + let x = Math.round(pos.x + ox) + let y = Math.round(pos.y + oy) + if (x < 0 || x >= map.width || y < 0 || y >= map.height) return 1 + return map.data[y * map.width + x] +} + +const getTileFrontWithRot = ( + map: Map, + pos: Vec2, + rot: Rotation +): number => { + let collider = 1 + switch(rot) { + case Rotation.NORTH: + collider = getTile(map, pos, 0, -.51) + break + case Rotation.SOUTH: + collider = getTile(map, pos, 0, .51) + break + case Rotation.WEST: + collider = getTile(map, pos, -.51, 0) + break + case Rotation.EAST: + collider = getTile(map, pos, .51, 0) + break + } + return collider +} + +const getRot = (key: Key): Rotation => { + switch (key) { + case Key.UP: return Rotation.NORTH + case Key.DOWN: return Rotation.SOUTH + case Key.LEFT: return Rotation.WEST + case Key.RIGHT: return Rotation.EAST + case Key.NOTHING: return Rotation.NOTHING + } +} + +const incrementPos = ( + pos: Vec2, + rot: Rotation, + speed: number +): void => { + switch (rot) { + case Rotation.NORTH: + pos.y -= speed + break + case Rotation.SOUTH: + pos.y += speed + break + case Rotation.WEST: + pos.x -= speed + break + case Rotation.EAST: + pos.y += speed + break + } +} + +let i = 0 + +const updateMovementForPlayer = ( + map: Map, + player: Player, + inputKey: Key +) => { + + let inputRot = getRot(inputKey) + let moveRot = player.moveRotation + let currentPosition = player.pos + + let turningFrontTile = getTileFrontWithRot(map, currentPosition, inputRot) + if (turningFrontTile == 1 || turningFrontTile == 2) { + inputRot = Rotation.NOTHING + } + + let turning = inputRot != Rotation.NOTHING && inputRot != moveRot + + player.inputRotation = inputRot + + if (turning && isStablePos(currentPosition)) { + currentPosition = roundPos(currentPosition) + player.moveRotation = inputRot + moveRot = inputRot + } + + let movePos = structuredClone(currentPosition) + incrementPos(movePos, moveRot, MOVE_SPEED) + + let frontTile = getTileFrontWithRot(map, currentPosition, moveRot) + if (frontTile != 1 && frontTile != 2) { + player.pos = movePos + player.moving = true + } else { + player.pos = roundPos(currentPosition) + player.moving = false + } + + +} + +export const updateMovement = (data: GameState) => { + + let map = getMap(data.mapId) + if (!map) return + + for (const id in data.players) { + + const player = data.players[id] + + if(!player) { + continue + } + + let inputKey = data.input[id] + + updateMovementForPlayer(map, player, inputKey) + + } + +} diff --git a/client/src/logic/players.ts b/client/src/logic/players.ts new file mode 100644 index 0000000..ebe469f --- /dev/null +++ b/client/src/logic/players.ts @@ -0,0 +1,79 @@ +import { GameState, Input, Key, Rotation } from "../types.js" + +const canPlayerJoin = (data: GameState) => { + + // lobby has already started + if (data.started) { + return false + } + + // lobby full + if (Object.keys(data.players).length >= 4) { + return false + } + + return true + +} + +export const updatePlayers = (data: GameState, input: Input) => { + + let startPressed = false; + + for(const added of input.added || []) { + + if (!canPlayerJoin(data)) { + continue + } + + console.log("added", added); + + data.input[added] = Key.NOTHING + + data.players[added] ||= { + pos: {x: 1, y: 1}, + inputRotation: Rotation.EAST, + moveRotation: Rotation.EAST, + moving: false, + }; + + } + + for(const id in input.players) { + + if(!input.players[id]) { + continue; + } + + if(id in data.players && input.players[id].name !== undefined) { + + let name = input.players[id].name; + name = name.substring(0, 16); + + data.players[id] = { + ...data.players[id], + name, + }; + + } + + startPressed ||= input.players[id].start; + if (input.players[id].key) + data.input[id] = input.players[id].key + + } + + for(const removed of input.removed || []) { + console.log("removed", removed); + delete data.input[removed]; + delete data.players[removed]; + + let element_id = 'span' + removed + let element = document.getElementById(element_id) + if (element !== null && element !== undefined) element.remove() + } + + return startPressed + +} + diff --git a/client/src/logic/ui.ts b/client/src/logic/ui.ts new file mode 100644 index 0000000..5706843 --- /dev/null +++ b/client/src/logic/ui.ts @@ -0,0 +1,32 @@ +import { GameState } from "../types.js" + +export const updateUI = (data: GameState) => { + + const player_display = document.getElementById("players") + + for (const id in data.players) { + + const player = data.players[id] + + if (!player) { + continue + } + + let name = player.name + + if (!name) { + continue + } + + let element_id = 'span' + id + let element = player_display.children[element_id] + + if (!element) { + let span = document.createElement("span") + span.textContent = `[${id}] ${name}` + span.id = element_id + player_display.appendChild(span) + } + } + +} |