move clientId init to index.html, make zoom events only exist when they actually do something

This commit is contained in:
Zutatensuppe 2021-05-13 23:38:36 +02:00
parent a0118b0bdf
commit e9129cf049
7 changed files with 106 additions and 111 deletions

View file

@ -6,6 +6,8 @@ import Util from './Util.js'
const SCORE_MODE_FINAL = 0 const SCORE_MODE_FINAL = 0
const SCORE_MODE_ANY = 1 const SCORE_MODE_ANY = 1
const IDLE_TIMEOUT_SEC = 30
// Map<gameId, GameObject> // Map<gameId, GameObject>
const GAMES = {} const GAMES = {}
@ -76,18 +78,14 @@ function playerExists(gameId, playerId) {
return idx !== -1 return idx !== -1
} }
function getRelevantPlayers(gameId, ts) { function getActivePlayers(gameId, ts) {
const minTs = ts - 30 * Time.SEC const minTs = ts - IDLE_TIMEOUT_SEC * Time.SEC
return getAllPlayers(gameId).filter(player => { return getAllPlayers(gameId).filter(p => p.ts >= minTs)
return player.ts >= minTs || player.points > 0
})
} }
function getActivePlayers(gameId, ts) { function getIdlePlayers(gameId, ts) {
const minTs = ts - 30 * Time.SEC const minTs = ts - IDLE_TIMEOUT_SEC * Time.SEC
return getAllPlayers(gameId).filter(player => { return getAllPlayers(gameId).filter(p => p.ts < minTs && p.points > 0)
return player.ts >= minTs
})
} }
function addPlayer(gameId, playerId, ts) { function addPlayer(gameId, playerId, ts) {
@ -722,6 +720,16 @@ function handleInput(gameId, playerId, input, ts) {
} }
} }
evtInfo._last_mouse = pos evtInfo._last_mouse = pos
} else if (type === Protocol.INPUT_EV_ZOOM_IN) {
const pos = { x: input[1], y: input[2] }
changePlayer(gameId, playerId, pos)
_playerChange()
evtInfo._last_mouse = pos
} else if (type === Protocol.INPUT_EV_ZOOM_OUT) {
const pos = { x: input[1], y: input[2] }
changePlayer(gameId, playerId, pos)
_playerChange()
evtInfo._last_mouse = pos
} else { } else {
changePlayer(gameId, playerId, { ts }) changePlayer(gameId, playerId, { ts })
_playerChange() _playerChange()
@ -736,8 +744,8 @@ export default {
setGame, setGame,
exists, exists,
playerExists, playerExists,
getRelevantPlayers,
getActivePlayers, getActivePlayers,
getIdlePlayers,
addPlayer, addPlayer,
getFinishedTileCount, getFinishedTileCount,
getTileCount, getTileCount,

View file

@ -5,44 +5,48 @@ export default class Camera {
this.x = 0 this.x = 0
this.y = 0 this.y = 0
this.zoom = 1 this.curZoom = 1
this.minZoom = .1 this.minZoom = .1
this.maxZoom = 6 this.maxZoom = 6
this.zoomStep = .05 this.zoomStep = .05
} }
move(x, y) { move(x, y) {
this.x += x / this.zoom this.x += x / this.curZoom
this.y += y / this.zoom this.y += y / this.curZoom
}
canZoom(inout) {
return this.curZoom != this.calculateNewZoom(inout)
}
calculateNewZoom(inout) {
const factor = inout === 'in' ? 1 : -1
const newzoom = this.curZoom + this.zoomStep * this.curZoom * factor
const capped = Math.min(Math.max(newzoom, this.minZoom), this.maxZoom)
return capped
} }
setZoom(newzoom, viewportCoordCenter) { setZoom(newzoom, viewportCoordCenter) {
const zoom = Math.min(Math.max(newzoom, this.minZoom), this.maxZoom) if (this.curZoom == newzoom) {
if (zoom == this.zoom) {
return false return false
} }
const zoomFactor = 1 - (this.zoom / zoom) const zoomFactor = 1 - (this.curZoom / newzoom)
this.move( this.move(
-viewportCoordCenter.x * zoomFactor, -viewportCoordCenter.x * zoomFactor,
-viewportCoordCenter.y * zoomFactor, -viewportCoordCenter.y * zoomFactor,
) )
this.zoom = zoom this.curZoom = newzoom
return true return true
} }
zoomOut(viewportCoordCenter) { /**
return this.setZoom( * Zooms towards/away from the provided coordinate, if possible.
this.zoom - this.zoomStep * this.zoom, * If at max or min zoom respectively, no zooming is performed.
viewportCoordCenter */
) zoom(inout, viewportCoordCenter) {
} return this.setZoom(this.calculateNewZoom(inout), viewportCoordCenter)
zoomIn(viewportCoordCenter) {
return this.setZoom(
this.zoom + this.zoomStep * this.zoom,
viewportCoordCenter
)
} }
/** /**
@ -65,8 +69,8 @@ export default class Camera {
*/ */
viewportToWorldRaw(viewportCoord) { viewportToWorldRaw(viewportCoord) {
return { return {
x: (viewportCoord.x / this.zoom) - this.x, x: (viewportCoord.x / this.curZoom) - this.x,
y: (viewportCoord.y / this.zoom) - this.y, y: (viewportCoord.y / this.curZoom) - this.y,
} }
} }
@ -90,8 +94,8 @@ export default class Camera {
*/ */
worldToViewportRaw(worldCoord) { worldToViewportRaw(worldCoord) {
return { return {
x: (worldCoord.x + this.x) * this.zoom, x: (worldCoord.x + this.x) * this.curZoom,
y: (worldCoord.y + this.y) * this.zoom, y: (worldCoord.y + this.y) * this.curZoom,
} }
} }
@ -116,8 +120,8 @@ export default class Camera {
*/ */
worldDimToViewportRaw(worldDim) { worldDimToViewportRaw(worldDim) {
return { return {
w: worldDim.w * this.zoom, w: worldDim.w * this.curZoom,
h: worldDim.h * this.zoom, h: worldDim.h * this.curZoom,
} }
} }
} }

View file

@ -39,15 +39,6 @@ function addCanvasToDom(TARGET_EL, canvas) {
return canvas return canvas
} }
function initme() {
let ID = localStorage.getItem('ID')
if (!ID) {
ID = Util.uniqId()
localStorage.setItem('ID', ID)
}
return ID
}
function EventAdapter (canvas, window, viewport) { function EventAdapter (canvas, window, viewport) {
let events = [] let events = []
@ -107,10 +98,12 @@ function EventAdapter (canvas, window, viewport) {
}) })
canvas.addEventListener('wheel', (ev) => { canvas.addEventListener('wheel', (ev) => {
const evt = ev.deltaY < 0 if (viewport.canZoom(ev.deltaY < 0 ? 'in' : 'out')) {
? Protocol.INPUT_EV_ZOOM_IN const evt = ev.deltaY < 0
: Protocol.INPUT_EV_ZOOM_OUT ? Protocol.INPUT_EV_ZOOM_IN
addEvent([evt, ...mousePos(ev)]) : Protocol.INPUT_EV_ZOOM_OUT
addEvent([evt, ...mousePos(ev)])
}
}) })
window.addEventListener('keydown', (ev) => key(true, ev)) window.addEventListener('keydown', (ev) => key(true, ev))
@ -157,9 +150,13 @@ function EventAdapter (canvas, window, viewport) {
if (ZOOM_IN && ZOOM_OUT) { if (ZOOM_IN && ZOOM_OUT) {
// cancel each other out // cancel each other out
} else if (ZOOM_IN) { } else if (ZOOM_IN) {
addEvent([Protocol.INPUT_EV_ZOOM_IN, ...canvasCenter()]) if (viewport.canZoom('in')) {
addEvent([Protocol.INPUT_EV_ZOOM_IN, ...canvasCenter()])
}
} else if (ZOOM_OUT) { } else if (ZOOM_OUT) {
addEvent([Protocol.INPUT_EV_ZOOM_OUT, ...canvasCenter()]) if (viewport.canZoom('out')) {
addEvent([Protocol.INPUT_EV_ZOOM_OUT, ...canvasCenter()])
}
} }
} }
@ -175,16 +172,11 @@ function EventAdapter (canvas, window, viewport) {
} }
} }
export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) { export async function main(gameId, clientId, wsAddress, MODE, TARGET_EL, HUD) {
if (typeof gameId === 'undefined') throw '[ gameId not set ]'
if (typeof wsAddress === 'undefined') throw '[ wsAddress not set ]'
if (typeof MODE === 'undefined') throw '[ MODE not set ]'
if (typeof DEBUG === 'undefined') window.DEBUG = false if (typeof DEBUG === 'undefined') window.DEBUG = false
const CLIENT_ID = initme()
const shouldDrawPlayerText = (player) => { const shouldDrawPlayerText = (player) => {
return MODE === MODE_REPLAY || player.id !== CLIENT_ID return MODE === MODE_REPLAY || player.id !== clientId
} }
const cursorGrab = await Graphics.loadImageToBitmap('/grab.png') const cursorGrab = await Graphics.loadImageToBitmap('/grab.png')
@ -227,12 +219,12 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
let TIME let TIME
if (MODE === MODE_PLAY) { if (MODE === MODE_PLAY) {
const game = await Communication.connect(wsAddress, gameId, CLIENT_ID) const game = await Communication.connect(wsAddress, gameId, clientId)
const gameObject = Util.decodeGame(game) const gameObject = Util.decodeGame(game)
Game.setGame(gameObject.id, gameObject) Game.setGame(gameObject.id, gameObject)
TIME = () => Time.timestamp() TIME = () => Time.timestamp()
} else if (MODE === MODE_REPLAY) { } else if (MODE === MODE_REPLAY) {
const {game, log} = await Communication.connectReplay(wsAddress, gameId, CLIENT_ID) const {game, log} = await Communication.connectReplay(wsAddress, gameId, clientId)
const gameObject = Util.decodeGame(game) const gameObject = Util.decodeGame(game)
Game.setGame(gameObject.id, gameObject) Game.setGame(gameObject.id, gameObject)
REPLAY.log = log REPLAY.log = log
@ -285,16 +277,6 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
const previewImageUrl = Game.getImageUrl(gameId) const previewImageUrl = Game.getImageUrl(gameId)
const activePlayers = (gameId, ts) => {
const minTs = ts - 30 * Time.SEC
const players = Game.getRelevantPlayers(gameId, ts)
return players.filter(player => player.ts >= minTs)
}
const idlePlayers = (gameId, ts) => {
const minTs = ts - 30 * Time.SEC
const players = Game.getRelevantPlayers(gameId, ts)
return players.filter(player => player.ts < minTs)
}
const updateTimerElements = () => { const updateTimerElements = () => {
const startTs = Game.getStartTs(gameId) const startTs = Game.getStartTs(gameId)
const finishTs = Game.getFinishTs(gameId) const finishTs = Game.getFinishTs(gameId)
@ -308,42 +290,29 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
HUD.setPiecesDone(Game.getFinishedTileCount(gameId)) HUD.setPiecesDone(Game.getFinishedTileCount(gameId))
HUD.setPiecesTotal(Game.getTileCount(gameId)) HUD.setPiecesTotal(Game.getTileCount(gameId))
const ts = TIME() const ts = TIME()
HUD.setActivePlayers(activePlayers(gameId, ts)) HUD.setActivePlayers(Game.getActivePlayers(gameId, ts))
HUD.setIdlePlayers(idlePlayers(gameId, ts)) HUD.setIdlePlayers(Game.getIdlePlayers(gameId, ts))
const longFinished = !! Game.getFinishTs(gameId) const longFinished = !! Game.getFinishTs(gameId)
let finished = longFinished let finished = longFinished
const justFinished = () => finished && !longFinished const justFinished = () => finished && !longFinished
const playerBgColor = () => { const playerBgColor = () => {
return (Game.getPlayerBgColor(gameId, CLIENT_ID) return (Game.getPlayerBgColor(gameId, clientId)
|| localStorage.getItem('bg_color') || localStorage.getItem('bg_color')
|| '#222222') || '#222222')
} }
const playerColor = () => { const playerColor = () => {
return (Game.getPlayerColor(gameId, CLIENT_ID) return (Game.getPlayerColor(gameId, clientId)
|| localStorage.getItem('player_color') || localStorage.getItem('player_color')
|| '#ffffff') || '#ffffff')
} }
const playerName = () => { const playerName = () => {
return (Game.getPlayerName(gameId, CLIENT_ID) return (Game.getPlayerName(gameId, clientId)
|| localStorage.getItem('player_name') || localStorage.getItem('player_name')
|| 'anon') || 'anon')
} }
const onBgChange = (value) => {
localStorage.setItem('bg_color', value)
evts.addEvent([Protocol.INPUT_EV_BG_COLOR, value])
}
const onColorChange = (value) => {
localStorage.setItem('player_color', value)
evts.addEvent([Protocol.INPUT_EV_PLAYER_COLOR, value])
}
const onNameChange = (value) => {
localStorage.setItem('player_name', value)
evts.addEvent([Protocol.INPUT_EV_PLAYER_NAME, value])
}
const doSetSpeedStatus = () => { const doSetSpeedStatus = () => {
HUD.setReplaySpeed(REPLAY.speeds[REPLAY.speedIdx]) HUD.setReplaySpeed(REPLAY.speeds[REPLAY.speedIdx])
HUD.setReplayPaused(REPLAY.paused) HUD.setReplayPaused(REPLAY.paused)
@ -382,7 +351,7 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
switch (changeType) { switch (changeType) {
case Protocol.CHANGE_PLAYER: { case Protocol.CHANGE_PLAYER: {
const p = Util.decodePlayer(changeData) const p = Util.decodePlayer(changeData)
if (p.id !== CLIENT_ID) { if (p.id !== clientId) {
Game.setPlayer(gameId, p.id, p) Game.setPlayer(gameId, p.id, p)
RERENDER = true RERENDER = true
} }
@ -468,7 +437,7 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
RERENDER = true RERENDER = true
viewport.move(diffX, diffY) viewport.move(diffX, diffY)
} else if (type === Protocol.INPUT_EV_MOUSE_MOVE) { } else if (type === Protocol.INPUT_EV_MOUSE_MOVE) {
if (_last_mouse_down && !Game.getFirstOwnedTile(gameId, CLIENT_ID)) { if (_last_mouse_down && !Game.getFirstOwnedTile(gameId, clientId)) {
// move the cam // move the cam
const pos = { x: evt[1], y: evt[2] } const pos = { x: evt[1], y: evt[2] }
const mouse = viewport.worldToViewport(pos) const mouse = viewport.worldToViewport(pos)
@ -486,16 +455,12 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
_last_mouse_down = null _last_mouse_down = null
} else if (type === Protocol.INPUT_EV_ZOOM_IN) { } else if (type === Protocol.INPUT_EV_ZOOM_IN) {
const pos = { x: evt[1], y: evt[2] } const pos = { x: evt[1], y: evt[2] }
if (viewport.zoomIn(viewport.worldToViewport(pos))) { RERENDER = true
RERENDER = true viewport.zoom('in', viewport.worldToViewport(pos))
Game.changePlayer(gameId, CLIENT_ID, pos)
}
} else if (type === Protocol.INPUT_EV_ZOOM_OUT) { } else if (type === Protocol.INPUT_EV_ZOOM_OUT) {
const pos = { x: evt[1], y: evt[2] } const pos = { x: evt[1], y: evt[2] }
if (viewport.zoomOut(viewport.worldToViewport(pos))) { RERENDER = true
RERENDER = true viewport.zoom('out', viewport.worldToViewport(pos))
Game.changePlayer(gameId, CLIENT_ID, pos)
}
} else if (type === Protocol.INPUT_EV_TOGGLE_PREVIEW) { } else if (type === Protocol.INPUT_EV_TOGGLE_PREVIEW) {
HUD.togglePreview() HUD.togglePreview()
} }
@ -503,7 +468,7 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
// LOCAL + SERVER CHANGES // LOCAL + SERVER CHANGES
// ------------------------------------------------------------- // -------------------------------------------------------------
const ts = TIME() const ts = TIME()
const changes = Game.handleInput(gameId, CLIENT_ID, evt, ts) const changes = Game.handleInput(gameId, clientId, evt, ts)
if (changes.length > 0) { if (changes.length > 0) {
RERENDER = true RERENDER = true
} }
@ -536,14 +501,12 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
_last_mouse_down = null _last_mouse_down = null
} else if (type === Protocol.INPUT_EV_ZOOM_IN) { } else if (type === Protocol.INPUT_EV_ZOOM_IN) {
const pos = { x: evt[1], y: evt[2] } const pos = { x: evt[1], y: evt[2] }
if (viewport.zoomIn(viewport.worldToViewport(pos))) { RERENDER = true
RERENDER = true viewport.zoom('in', viewport.worldToViewport(pos))
}
} else if (type === Protocol.INPUT_EV_ZOOM_OUT) { } else if (type === Protocol.INPUT_EV_ZOOM_OUT) {
const pos = { x: evt[1], y: evt[2] } const pos = { x: evt[1], y: evt[2] }
if (viewport.zoomOut(viewport.worldToViewport(pos))) { RERENDER = true
RERENDER = true viewport.zoom('out', viewport.worldToViewport(pos))
}
} else if (type === Protocol.INPUT_EV_TOGGLE_PREVIEW) { } else if (type === Protocol.INPUT_EV_TOGGLE_PREVIEW) {
HUD.togglePreview() HUD.togglePreview()
} }
@ -639,8 +602,8 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
// propagate HUD changes // propagate HUD changes
// --------------------------------------------------------------- // ---------------------------------------------------------------
HUD.setActivePlayers(activePlayers(gameId, ts)) HUD.setActivePlayers(Game.getActivePlayers(gameId, ts))
HUD.setIdlePlayers(idlePlayers(gameId, ts)) HUD.setIdlePlayers(Game.getIdlePlayers(gameId, ts))
HUD.setPiecesDone(Game.getFinishedTileCount(gameId)) HUD.setPiecesDone(Game.getFinishedTileCount(gameId))
if (DEBUG) Debug.checkpoint('HUD done') if (DEBUG) Debug.checkpoint('HUD done')
// --------------------------------------------------------------- // ---------------------------------------------------------------
@ -661,9 +624,18 @@ export async function main(gameId, wsAddress, MODE, TARGET_EL, HUD) {
setHotkeys: (state) => { setHotkeys: (state) => {
evts.setHotkeys(state) evts.setHotkeys(state)
}, },
onBgChange, onBgChange: (value) => {
onColorChange, localStorage.setItem('bg_color', value)
onNameChange, evts.addEvent([Protocol.INPUT_EV_BG_COLOR, value])
},
onColorChange: (value) => {
localStorage.setItem('player_color', value)
evts.addEvent([Protocol.INPUT_EV_PLAYER_COLOR, value])
},
onNameChange: (value) => {
localStorage.setItem('player_name', value)
evts.addEvent([Protocol.INPUT_EV_PLAYER_NAME, value])
},
replayOnSpeedUp, replayOnSpeedUp,
replayOnSpeedDown, replayOnSpeedDown,
replayOnPauseToggle, replayOnPauseToggle,

View file

@ -18,6 +18,15 @@
const res = await fetch(`/api/conf`) const res = await fetch(`/api/conf`)
const conf = await res.json() const conf = await res.json()
function initme() {
let ID = localStorage.getItem('ID')
if (!ID) {
ID = Util.uniqId()
localStorage.setItem('ID', ID)
}
return ID
}
const router = VueRouter.createRouter({ const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(), history: VueRouter.createWebHashHistory(),
routes: [ routes: [
@ -37,6 +46,7 @@
const app = Vue.createApp(App) const app = Vue.createApp(App)
app.config.globalProperties.$config = conf app.config.globalProperties.$config = conf
app.config.globalProperties.$clientId = initme()
app.use(router) app.use(router)
app.mount('#app') app.mount('#app')
})() })()

View file

@ -82,6 +82,7 @@ export default {
}) })
this.g = await main( this.g = await main(
this.$route.params.id, this.$route.params.id,
this.$clientId,
this.$config.WS_ADDRESS, this.$config.WS_ADDRESS,
MODE_PLAY, MODE_PLAY,
this.$el, this.$el,

View file

@ -97,6 +97,7 @@ export default {
}) })
this.g = await main( this.g = await main(
this.$route.params.id, this.$route.params.id,
this.$clientId,
this.$config.WS_ADDRESS, this.$config.WS_ADDRESS,
MODE_REPLAY, MODE_REPLAY,
this.$el, this.$el,

View file

@ -58,7 +58,6 @@ export default {
addPlayer, addPlayer,
handleInput, handleInput,
getAllGames: GameCommon.getAllGames, getAllGames: GameCommon.getAllGames,
getRelevantPlayers: GameCommon.getRelevantPlayers,
getActivePlayers: GameCommon.getActivePlayers, getActivePlayers: GameCommon.getActivePlayers,
getFinishedTileCount: GameCommon.getFinishedTileCount, getFinishedTileCount: GameCommon.getFinishedTileCount,
getImageUrl: GameCommon.getImageUrl, getImageUrl: GameCommon.getImageUrl,