custom map overrides
This commit is contained in:
parent
c66865d431
commit
484409b64d
10 changed files with 115 additions and 45 deletions
|
@ -24,29 +24,3 @@ canvas {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#popup {
|
|
||||||
background-color: #191919;
|
|
||||||
position: absolute;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: .5rem;
|
|
||||||
border: 1px solid #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#popup textarea {
|
|
||||||
margin: .5rem 0;
|
|
||||||
height: 5rem;
|
|
||||||
background-color: transparent;
|
|
||||||
color: white;
|
|
||||||
border: 1px solid #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#popup input {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#close {
|
|
||||||
width: .3rem;
|
|
||||||
height: .3rem;
|
|
||||||
font-size: .6rem;
|
|
||||||
line-height: 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -23,16 +23,16 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
#center-inner {
|
#center-inner {
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
margin-left: calc(50% - 20rem / 2);
|
||||||
|
max-width: 20rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mapeditor {
|
#custommaps, #mapeditor {
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,3 +87,31 @@ input {
|
||||||
p {
|
p {
|
||||||
padding: .25rem;
|
padding: .25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#popup {
|
||||||
|
background-color: #191919;
|
||||||
|
position: absolute;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: .5rem;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
width: 19rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup textarea {
|
||||||
|
margin: .5rem 0;
|
||||||
|
height: 5rem;
|
||||||
|
background-color: transparent;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#popup input {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close {
|
||||||
|
width: .3rem;
|
||||||
|
height: .3rem;
|
||||||
|
font-size: .6rem;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
|
|
@ -14,12 +14,24 @@
|
||||||
<input type="text" id="player_name" name="name" placeholder="Player Name">
|
<input type="text" id="player_name" name="name" placeholder="Player Name">
|
||||||
<input type="submit" value="Join!"/>
|
<input type="submit" value="Join!"/>
|
||||||
</form>
|
</form>
|
||||||
|
<input id="custommaps" type="button" value="Custom Map Overrides">
|
||||||
<input id="mapeditor" type="button" value="Map Editor">
|
<input id="mapeditor" type="button" value="Map Editor">
|
||||||
<div id="lobby" style="display: none;">
|
<div id="lobby" style="display: none;">
|
||||||
<span>Players:</span>
|
<span>Players:</span>
|
||||||
<div id="players"></div>
|
<div id="players"></div>
|
||||||
<input type="button" id="start" value="Start Game"/>
|
<input type="button" id="start" value="Start Game"/>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="popup" style="display: none">
|
||||||
|
<input type="button" id="close" value="x" style='margin-bottom: .5rem' onclick="document.getElementById('popup').style.display = 'none'">
|
||||||
|
Map 1
|
||||||
|
<textarea id="map1"></textarea>
|
||||||
|
Map 2
|
||||||
|
<textarea id="map2"></textarea>
|
||||||
|
Map 3
|
||||||
|
<textarea id="map3"> </textarea>
|
||||||
|
Map 4
|
||||||
|
<textarea id="map4"></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="js/main.js" type="module"></script>
|
<script src="js/main.js" type="module"></script>
|
||||||
|
|
|
@ -33,10 +33,17 @@ export const onLogic = (
|
||||||
data.frame = frame
|
data.frame = frame
|
||||||
random(data)
|
random(data)
|
||||||
|
|
||||||
let startPressed = updatePlayers(data, input);
|
let startPressed = updatePlayers(data, input)
|
||||||
|
|
||||||
let playersLeft = 0
|
let playersLeft = 0
|
||||||
for (let id in data.players) {
|
for (let id in data.players) {
|
||||||
|
|
||||||
let player = data.players[id]
|
let player = data.players[id]
|
||||||
|
|
||||||
|
if (!player) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (player.dead) {
|
if (player.dead) {
|
||||||
player.framesDead++
|
player.framesDead++
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { GameState, Input, Key, Rotation } from "../types.js"
|
import { checkMap, decompressMap, genMap } from "../map.js"
|
||||||
|
import { GAME_MAP_COUNT, GameState, Input, Key, Rotation, Vec2 } from "../types.js"
|
||||||
|
|
||||||
const canPlayerJoin = (data: GameState) => {
|
const canPlayerJoin = (data: GameState) => {
|
||||||
|
|
||||||
|
@ -16,6 +17,27 @@ const canPlayerJoin = (data: GameState) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadMaps = (maps: {[key: number]: string}): boolean => {
|
||||||
|
|
||||||
|
for (let mapId = 0; mapId < GAME_MAP_COUNT; mapId++) {
|
||||||
|
|
||||||
|
let {width, height, data} = decompressMap(maps[mapId])
|
||||||
|
let map = genMap(width, height, data, mapId)
|
||||||
|
let [success, result] = checkMap(map)
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
alert(result)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
map.spawns = result as Vec2[]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const updatePlayers = (data: GameState, input: Input) => {
|
export const updatePlayers = (data: GameState, input: Input) => {
|
||||||
|
|
||||||
let startPressed = false;
|
let startPressed = false;
|
||||||
|
@ -62,7 +84,13 @@ export const updatePlayers = (data: GameState, input: Input) => {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
startPressed ||= input.players[id].start;
|
if (input.players[id].start) {
|
||||||
|
let maps = input.players[id].maps
|
||||||
|
if (loadMaps(maps)) {
|
||||||
|
startPressed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (input.players[id].key)
|
if (input.players[id].key)
|
||||||
data.input[id] = input.players[id].key
|
data.input[id] = input.players[id].key
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,18 @@ import { checkMap, decompressMap, genMap } from "./map.js";
|
||||||
const join = document.getElementById("join")
|
const join = document.getElementById("join")
|
||||||
const lobby = document.getElementById("lobby")
|
const lobby = document.getElementById("lobby")
|
||||||
const mapeditor = document.getElementById("mapeditor")
|
const mapeditor = document.getElementById("mapeditor")
|
||||||
|
const custommaps = document.getElementById("custommaps")
|
||||||
|
const popup = document.getElementById("popup")
|
||||||
|
|
||||||
const maps = {
|
const defaultMaps = {
|
||||||
[0]: 'MwRgPgTOIDS/dEOU1L1sxgDDX+9CDijSTyzLcFrVabN7EnYXCUnaBOK31xCMyEUSPfg3FZ20trTlTJnPpX4iV6tRLpCOC7bslbVvNQBY41SxesBWE/bYHpTnFPkZjFResG/hpb003RGBEMR0YQQAOSIjYcNDDRntAgNi/Txl/L2CkozgXfWdgtTUANmsQKyrrAHYHFLiI2T1870KgkkzS7N6CLUdmpvbipyV4hv7pQVSe8PGittHllo7J9Z7N5Y9W3Z39uCA'
|
[0]: 'MwRgPgTOIDS/dEOU1L1sxgDDX+9CDijSTyzLcFrVabN7EnYXCUnaBOK31xCMyEUSPfg3FZ20trTlTJnPpX4iV6tRLpCOC7bslbVvNQBY41SxesBWE/bYHpTnFPkZjFResG/hpb003RGBEMR0YQQAOSIjYcNDDRntAgNi/Txl/L2CkozgXfWdgtTUANmsQKyrrAHYHFLiI2T1870KgkkzS7N6CLUdmpvbipyV4hv7pQVSe8PGittHllo7J9Z7N5Y9W3Z39uCA',
|
||||||
|
[1]: 'MwdgPgTMkDQXD5IQRhgBhm5PF97mptvqQalpWkVbdXQ/Uxo5eeTZly97zy5359h/Euzw1mUgbWIzpCynPHS5I9UpgBOGRpGSGyQZh0HVmxWtYGdfMRYZXuBvbs3P5sthSei3Z6y8Xdz9lIM96KwAWLGI42ISUeKTE+IBWf0cHYyFcu2zAuRzXfMUA4I9CXPKI1nF4NGBvYIN4AA4fBzDG7xVAmt8wo2raosK8idLalHNIyfmxq1mWADZU9ZTN5O2YEEzmJea3fMOxsq6Lk96CuZyK+fvDg+uc02mLyxvw2z9h5+KHiwfgCNDV7FUzqxIU8vst6hIFojBkiRvC/llzpioYE0WROuC8biGjIiUA===',
|
||||||
|
[2]: 'MzA+CYEZUgaOHyYly2o+rnEAZb6EFJGknFlFyXHUX15b52pk73NqeeO+zjkAnLQ7kaVUXWGcBLcq3kie2Jou6rGNOhPGi2kvSIWZlfEytOLEA2UsMSALPGYvnbgKxj7im/z9zLdTlzAI0RX2M7HR8/WyCDeM16aTUkYAY/AA5/enTQqUNI9Wi5XzjUkqMkCLtg1JQisPiynOLvOAA2N0hXHrcAdi9dUpyzLgsVOrHpoYz9XQXZ7QMp2rX2RvzxvnKU5bbhhNg91u2zwIzzCT4LpPnC72itdsnXjbePnCA===',
|
||||||
|
[3]: 'MwRgPgTMYgNHD5MS5aAMbXa7zm4BOWfJU8k2YMm0oyiuCgypmtnD17llxX3Gzo9KxIQxHiBzStX552kjIvlc+KiTOmbF2gfRmrB3I1olrjXKbRHDOunXuP6lAFngFPH7yC8BWDQsLM2srS0dbSNQXdXE4CFgEhLilWNxiYRCkOUTYAA5cuBzrTNFwoKjcpJtoh1qnEpNkHAaI0oqjADYfL18e7wB2OqV6yMYm+3Gp80DlYLbZtKNGsTHhrLM7CdSFMIqXZaoF1qdhDJ2t012dvbmbiJWbF2pNm1XL8s+lz84gA=='
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export var maps = {}
|
||||||
|
|
||||||
join.onsubmit = async function(event) {
|
join.onsubmit = async function(event) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
|
@ -27,19 +34,18 @@ join.onsubmit = async function(event) {
|
||||||
alert('Please enter a player name')
|
alert('Please enter a player name')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let mapId = 0; mapId < GAME_MAP_COUNT; mapId++) {
|
for (let mapId = 0; mapId < GAME_MAP_COUNT; mapId++) {
|
||||||
let {width, height, data} = decompressMap(maps[0]) // for now
|
|
||||||
let map = genMap(width, height, data, mapId)
|
|
||||||
let [success, result] = checkMap(map)
|
|
||||||
|
|
||||||
if (!success) {
|
let id = 'map' + (mapId+1)
|
||||||
alert(result)
|
let content = (document.getElementById(id) as HTMLTextAreaElement).value.trim()
|
||||||
return
|
console.log(id, content)
|
||||||
|
if (content.length > 0) {
|
||||||
|
maps[mapId] = content
|
||||||
|
} else {
|
||||||
|
maps[mapId] = defaultMaps[mapId]
|
||||||
}
|
}
|
||||||
|
|
||||||
map.spawns = result as Vec2[]
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
startGame(room_code, player_name)
|
startGame(room_code, player_name)
|
||||||
|
@ -49,6 +55,10 @@ mapeditor.onclick = function() {
|
||||||
window.location.href = 'mapeditor.html'
|
window.location.href = 'mapeditor.html'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custommaps.onclick = function() {
|
||||||
|
popup.style.display = 'flex'
|
||||||
|
}
|
||||||
|
|
||||||
const onLoad = (startData: Frame) => {
|
const onLoad = (startData: Frame) => {
|
||||||
|
|
||||||
if (startData.data.started) {
|
if (startData.data.started) {
|
||||||
|
@ -64,6 +74,8 @@ const onLoad = (startData: Frame) => {
|
||||||
|
|
||||||
join.style.display = "none"
|
join.style.display = "none"
|
||||||
mapeditor.style.display = "none"
|
mapeditor.style.display = "none"
|
||||||
|
custommaps.style.display = "none"
|
||||||
|
popup.style.display = "none"
|
||||||
lobby.style.display = ""
|
lobby.style.display = ""
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -88,6 +100,7 @@ const startGame = (code: string, name: string) => {
|
||||||
{
|
{
|
||||||
start: false,
|
start: false,
|
||||||
key: Key.NOTHING,
|
key: Key.NOTHING,
|
||||||
|
maps: {},
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -114,7 +114,7 @@ export class Game {
|
||||||
onLoad: (startFrame: Frame) => boolean,
|
onLoad: (startFrame: Frame) => boolean,
|
||||||
onFrame: (data: Frame, frame: number) => void,
|
onFrame: (data: Frame, frame: number) => void,
|
||||||
onLogic: (pastData: GameState, input: Input, frame: number) => GameState,
|
onLogic: (pastData: GameState, input: Input, frame: number) => GameState,
|
||||||
data: PlayerInput = { start: false, key: Key.NOTHING }
|
data: PlayerInput = { start: false, key: Key.NOTHING, maps: {}}
|
||||||
): void {
|
): void {
|
||||||
|
|
||||||
const fps = 60;
|
const fps = 60;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Key, KeyMap, PlayerInput } from "../types.js"
|
import { Key, KeyMap, PlayerInput } from "../types.js"
|
||||||
|
import { maps as definedMaps } from '../main.js'
|
||||||
|
|
||||||
let pressed = {}
|
let pressed = {}
|
||||||
|
|
||||||
|
@ -62,9 +63,15 @@ export const startInputListener = (keymap: KeyMap): () => PlayerInput => {
|
||||||
let s = start;
|
let s = start;
|
||||||
start = false;
|
start = false;
|
||||||
|
|
||||||
|
let maps = {}
|
||||||
|
if (s) {
|
||||||
|
maps = definedMaps
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
start: s,
|
start: s,
|
||||||
|
maps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,6 +194,7 @@ export type Player = {
|
||||||
export type PlayerInput = {
|
export type PlayerInput = {
|
||||||
start: boolean,
|
start: boolean,
|
||||||
key: Key,
|
key: Key,
|
||||||
|
maps: {[key: number]: string}
|
||||||
name?: string
|
name?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ RUN apk add musl-dev
|
||||||
RUN cargo build --release
|
RUN cargo build --release
|
||||||
|
|
||||||
FROM node:alpine AS builder-ts
|
FROM node:alpine AS builder-ts
|
||||||
|
RUN npm install typescript
|
||||||
COPY client /app/
|
COPY client /app/
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN npm install typescript
|
|
||||||
RUN npx tsc
|
RUN npx tsc
|
||||||
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
|
|
Loading…
Reference in a new issue