From b6a3cfd8babcf876b315c2ba30c4f3925aafe74c Mon Sep 17 00:00:00 2001 From: Zutatensuppe Date: Sat, 5 Dec 2020 19:45:34 +0100 Subject: [PATCH] reduce size of game json files --- common/GameCommon.js | 209 ++++++++++++++++++++++++++++++++++------- common/Util.js | 105 +++++++++++++++++++++ game/Game.js | 19 +++- game/PuzzleGraphics.js | 8 +- game/game.js | 107 +++++++-------------- game/index.js | 8 +- server/Game.js | 24 +++-- server/Puzzle.js | 36 +++---- server/index.js | 13 ++- 9 files changed, 380 insertions(+), 149 deletions(-) diff --git a/common/GameCommon.js b/common/GameCommon.js index 37448b7..7b055a3 100644 --- a/common/GameCommon.js +++ b/common/GameCommon.js @@ -7,28 +7,70 @@ function exists(gameId) { return (!!GAMES[gameId]) || false } +function createGame(id, puzzle, players, sockets, evtInfos) { + return { + id: id, + puzzle: puzzle, + players: players, + sockets: sockets, + evtInfos: evtInfos, + } +} + +function createPlayer(id, ts) { + return { + id: id, + x: 0, + y: 0, + d: 0, // mouse down + name: 'anon', + color: '#ffffff', + bgcolor: '#222222', + points: 0, + ts: ts, + } +} + +function newGame({id, puzzle, players, sockets, evtInfos}) { + const game = createGame(id, puzzle, players, sockets, evtInfos) + setGame(id, game) + return game +} + function setGame(gameId, game) { GAMES[gameId] = game } +function getPlayer(gameId, playerId) { + return Util.decodePlayer(GAMES[gameId].players[playerId]) +} + +function setPlayer(gameId, playerId, player) { + GAMES[gameId].players[playerId] = Util.encodePlayer(player) +} + +function setTile(gameId, tileIdx, tile) { + GAMES[gameId].puzzle.tiles[tileIdx] = Util.encodeTile(tile) +} + +function setPuzzleData(gameId, data) { + GAMES[gameId].puzzle.data = data +} + function playerExists(gameId, playerId) { return !!GAMES[gameId].players[playerId] } +function getActivePlayers(gameId) { + const ts = Util.timestamp() + const minTs = ts - 30000 + return getAllPlayers(gameId).filter(player => player.ts >= minTs) +} + function addPlayer(gameId, playerId) { const ts = Util.timestamp() if (!GAMES[gameId].players[playerId]) { - GAMES[gameId].players[playerId] = { - id: playerId, - x: 0, - y: 0, - d: 0, // mouse down - name: 'anon', - color: '#ffffff', - bgcolor: '#222222', - points: 0, - ts, - } + setPlayer(gameId, playerId, createPlayer(playerId, ts)) } else { changePlayer(gameId, playerId, { ts }) } @@ -56,21 +98,52 @@ function removeSocket(gameId, socket) { } function getAllGames() { - return GAMES + return Object.values(GAMES) +} + +function getAllPlayers(gameId) { + return GAMES[gameId] + ? Object.values(GAMES[gameId].players).map(Util.decodePlayer) + : [] } function get(gameId) { return GAMES[gameId] } +function getTileCount(gameId) { + return GAMES[gameId].puzzle.tiles.length +} + +function getImageUrl(gameId) { + return GAMES[gameId].puzzle.info.imageUrl +} + +function getFinishedTileCount(gameId) { + let count = 0 + for (let t of GAMES[gameId].puzzle.tiles) { + if (Util.decodeTile(t).owner === -1) { + count++ + } + } + return count +} + +function getTilesSortedByZIndex(gameId) { + const tiles = GAMES[gameId].puzzle.tiles.map(Util.decodeTile) + return tiles.sort((t1, t2) => t1.z - t2.z) +} + function getSockets(gameId) { return GAMES[gameId].sockets } function changePlayer(gameId, playerId, change) { + const player = getPlayer(gameId, playerId) for (let k of Object.keys(change)) { - GAMES[gameId].players[playerId][k] = change[k] + player[k] = change[k] } + setPlayer(gameId, playerId, player) } function changeData(gameId, change) { @@ -81,12 +154,14 @@ function changeData(gameId, change) { function changeTile(gameId, tileIdx, change) { for (let k of Object.keys(change)) { - GAMES[gameId].puzzle.tiles[tileIdx][k] = change[k] + const tile = Util.decodeTile(GAMES[gameId].puzzle.tiles[tileIdx]) + tile[k] = change[k] + GAMES[gameId].puzzle.tiles[tileIdx] = Util.encodeTile(tile) } } const getTile = (gameId, tileIdx) => { - return GAMES[gameId].puzzle.tiles[tileIdx] + return Util.decodeTile(GAMES[gameId].puzzle.tiles[tileIdx]) } const getTileGroup = (gameId, tileIdx) => { @@ -116,13 +191,27 @@ const getTileZIndex = (gameId, tileIdx) => { const getFirstOwnedTileIdx = (gameId, userId) => { for (let t of GAMES[gameId].puzzle.tiles) { - if (t.owner === userId) { - return t.idx + const tile = Util.decodeTile(t) + if (tile.owner === userId) { + return tile.idx } } return -1 } +const getFirstOwnedTile = (gameId, userId) => { + const idx = getFirstOwnedTileIdx(gameId, userId) + return idx < 0 ? null : GAMES[gameId].puzzle.tiles[idx] +} + +const getTileDrawOffset = (gameId) => { + return GAMES[gameId].puzzle.info.tileDrawOffset +} + +const getTileDrawSize = (gameId) => { + return GAMES[gameId].puzzle.info.tileDrawSize +} + const getMaxGroup = (gameId) => { return GAMES[gameId].puzzle.data.maxGroup } @@ -145,7 +234,7 @@ const getMaxZIndexByTileIdxs = (gameId, tileIdxs) => { function srcPosByTileIdx(gameId, tileIdx) { const info = GAMES[gameId].puzzle.info - const c = info.coords[tileIdx] + const c = Util.coordByTileIdx(info, tileIdx) const cx = c.x * info.tileSize const cy = c.y * info.tileSize @@ -155,18 +244,17 @@ function srcPosByTileIdx(gameId, tileIdx) { function getSurroundingTilesByIdx(gameId, tileIdx) { const info = GAMES[gameId].puzzle.info - const _X = info.coords[tileIdx].x - const _Y = info.coords[tileIdx].y + const c = Util.coordByTileIdx(info, tileIdx) return [ // top - (_Y > 0) ? (tileIdx - info.tilesX) : -1, + (c.y > 0) ? (tileIdx - info.tilesX) : -1, // right - (_X < info.tilesX - 1) ? (tileIdx + 1) : -1, + (c.x < info.tilesX - 1) ? (tileIdx + 1) : -1, // bottom - (_Y < info.tilesY - 1) ? (tileIdx + info.tilesX) : -1, + (c.y < info.tilesY - 1) ? (tileIdx + info.tilesX) : -1, // left - (_X > 0) ? (tileIdx - 1) : -1, + (c.x > 0) ? (tileIdx - 1) : -1, ] } @@ -203,13 +291,14 @@ const setTilesOwner = (gameId, tileIdxs, owner) => { // get all grouped tiles for a tile function getGroupedTileIdxs(gameId, tileIdx) { const tiles = GAMES[gameId].puzzle.tiles - const tile = tiles[tileIdx] + const tile = Util.decodeTile(tiles[tileIdx]) const grouped = [] if (tile.group) { for (let other of tiles) { - if (other.group === tile.group) { - grouped.push(other.idx) + const otherTile = Util.decodeTile(other) + if (otherTile.group === tile.group) { + grouped.push(otherTile.idx) } } } else { @@ -227,7 +316,7 @@ const freeTileIdxByPos = (gameId, pos) => { let maxZ = -1 let tileIdx = -1 for (let idx = 0; idx < tiles.length; idx++) { - const tile = tiles[idx] + const tile = Util.decodeTile(tiles[idx]) if (tile.owner !== 0) { continue } @@ -248,6 +337,22 @@ const freeTileIdxByPos = (gameId, pos) => { return tileIdx } +const getPlayerBgColor = (gameId, playerId) => { + return getPlayer(gameId, playerId).bgcolor +} + +const getPlayerColor = (gameId, playerId) => { + return getPlayer(gameId, playerId).color +} + +const getPlayerName = (gameId, playerId) => { + return getPlayer(gameId, playerId).name +} + +const getPlayerPoints = (gameId, playerId) => { + return getPlayer(gameId, playerId).points +} + // determine if two tiles are grouped together const areGrouped = (gameId, tileIdx1, tileIdx2) => { const g1 = getTileGroup(gameId, tileIdx1) @@ -255,9 +360,24 @@ const areGrouped = (gameId, tileIdx1, tileIdx2) => { return g1 && g1 === g2 } +const getTableWidth = (gameId) => { + return GAMES[gameId].puzzle.info.table.width +} + +const getTableHeight = (gameId) => { + return GAMES[gameId].puzzle.info.table.height +} + +const getPuzzleWidth = (gameId) => { + return GAMES[gameId].puzzle.info.width +} + +const getPuzzleHeight = (gameId) => { + return GAMES[gameId].puzzle.info.height +} + function handleInput(gameId, playerId, input) { - let puzzle = GAMES[gameId].puzzle - let players = GAMES[gameId].players + const puzzle = GAMES[gameId].puzzle let evtInfo = GAMES[gameId].evtInfos[playerId] let changes = [] @@ -277,7 +397,7 @@ function handleInput(gameId, playerId, input) { } const _playerChange = () => { - changes.push(['player', players[playerId]]) + changes.push(['player', GAMES[gameId].players[playerId]]) } // put both tiles (and their grouped tiles) in the same group @@ -312,7 +432,8 @@ function handleInput(gameId, playerId, input) { // TODO: strange if (searchGroups.length > 0) { - for (let tile of tiles) { + for (let t of tiles) { + const tile = Util.decodeTile(t) if (searchGroups.includes(tile.group)) { changeTile(gameId, tile.idx, { group }) _tileChange(tile.idx) @@ -404,7 +525,7 @@ function handleInput(gameId, playerId, input) { // Snap the tile to the final destination moveTilesDiff(gameId, tileIdxs, diff) finishTiles(gameId, tileIdxs) - changePlayer(gameId, playerId, { points: players[playerId].points + tileIdxs.length }) + changePlayer(gameId, playerId, { points: getPlayerPoints(gameId, playerId) + tileIdxs.length }) _tileChanges(tileIdxs) } else { // Snap to other tiles @@ -457,17 +578,35 @@ function handleInput(gameId, playerId, input) { return changes } - export default { - setGame, + newGame, exists, playerExists, + getActivePlayers, addPlayer, socketExists, addSocket, removeSocket, + getFinishedTileCount, + getTileCount, + getImageUrl, get, getAllGames, getSockets, + getPlayerBgColor, + getPlayerColor, + getPlayerName, + changePlayer, + setPlayer, + setTile, + setPuzzleData, + getTableWidth, + getTableHeight, + getPuzzleWidth, + getPuzzleHeight, + getTilesSortedByZIndex, + getFirstOwnedTile, + getTileDrawOffset, + getTileDrawSize, handleInput, } diff --git a/common/Util.js b/common/Util.js index 5980f4c..f6f3313 100644 --- a/common/Util.js +++ b/common/Util.js @@ -46,6 +46,100 @@ export const timestamp = () => { ) } +function encodeShape(data) { + if (typeof data === 'number') { + return data + } + /* encoded in 1 byte: + 00000000 + ^^ top + ^^ right + ^^ bottom + ^^ left + */ + return ((data.top + 1) << 0) + | ((data.right + 1) << 2) + | ((data.bottom + 1) << 4) + | ((data.left + 1) << 6) +} + +function decodeShape(data) { + if (typeof data !== 'number') { + return data + } + return { + top: (data >> 0 & 0b11) - 1, + right: (data >> 2 & 0b11) - 1, + bottom: (data >> 4 & 0b11) - 1, + left: (data >> 6 & 0b11) - 1, + } +} + +function encodeTile(data) { + if (Array.isArray(data)) { + return data + } + return [data.idx, data.pos.x, data.pos.y, data.z, data.owner, data.group] +} + +function decodeTile(data) { + if (!Array.isArray(data)) { + return data + } + return { + idx: data[0], + pos: { + x: data[1], + y: data[2], + }, + z: data[3], + owner: data[4], + group: data[5], + } +} + +function encodePlayer(data) { + if (Array.isArray(data)) { + return data + } + return [ + data.id, + data.x, + data.y, + data.d, + data.name, + data.color, + data.bgcolor, + data.points, + data.ts, + ] +} + +function decodePlayer(data) { + if (!Array.isArray(data)) { + return data + } + return { + id: data[0], + x: data[1], + y: data[2], + d: data[3], // mouse down + name: data[4], + color: data[5], + bgcolor: data[6], + points: data[7], + ts: data[8], + } +} + +function coordByTileIdx(info, tileIdx) { + const wTiles = info.width / info.tileSize + return { + x: tileIdx % wTiles, + y: Math.floor(tileIdx / wTiles), + } +} + export default { uniqId, randomInt, @@ -53,4 +147,15 @@ export default { throttle, shuffle, timestamp, + + encodeShape, + decodeShape, + + encodeTile, + decodeTile, + + encodePlayer, + decodePlayer, + + coordByTileIdx, } diff --git a/game/Game.js b/game/Game.js index 93800b7..1bc2a05 100644 --- a/game/Game.js +++ b/game/Game.js @@ -1,6 +1,23 @@ import GameCommon from './../common/GameCommon.js' export default { - createGame: GameCommon.setGame, + newGame: GameCommon.newGame, + getActivePlayers: GameCommon.getActivePlayers, handleInput: GameCommon.handleInput, + getPlayerBgColor: GameCommon.getPlayerBgColor, + getPlayerColor: GameCommon.getPlayerColor, + getPlayerName: GameCommon.getPlayerName, + changePlayer: GameCommon.changePlayer, + setPlayer: GameCommon.setPlayer, + setTile: GameCommon.setTile, + getImageUrl: GameCommon.getImageUrl, + setPuzzleData: GameCommon.setPuzzleData, + getTableWidth: GameCommon.getTableWidth, + getTableHeight: GameCommon.getTableHeight, + getPuzzleWidth: GameCommon.getPuzzleWidth, + getPuzzleHeight: GameCommon.getPuzzleHeight, + getTilesSortedByZIndex: GameCommon.getTilesSortedByZIndex, + getFirstOwnedTile: GameCommon.getFirstOwnedTile, + getTileDrawOffset: GameCommon.getTileDrawOffset, + getTileDrawSize: GameCommon.getTileDrawSize, } diff --git a/game/PuzzleGraphics.js b/game/PuzzleGraphics.js index e8eb610..270d493 100644 --- a/game/PuzzleGraphics.js +++ b/game/PuzzleGraphics.js @@ -1,5 +1,6 @@ import Geometry from '../common/Geometry.js' import Graphics from './Graphics.js' +import Util from './../common/Util.js' async function createPuzzleTileBitmaps(img, tiles, info) { var tileSize = info.tileSize @@ -76,9 +77,10 @@ async function createPuzzleTileBitmaps(img, tiles, info) { return path } - for (let tile of tiles) { + for (let t of tiles) { + const tile = Util.decodeTile(t) const srcRect = srcRectByIdx(info, tile.idx) - const path = pathForShape(info.shapes[tile.idx]) + const path = pathForShape(Util.decodeShape(info.shapes[tile.idx])) const c = Graphics.createCanvas(tileDrawSize, tileDrawSize) const ctx = c.getContext('2d') @@ -192,7 +194,7 @@ async function createPuzzleTileBitmaps(img, tiles, info) { } function srcRectByIdx(puzzleInfo, idx) { - const c = puzzleInfo.coords[idx] + const c = Util.coordByTileIdx(puzzleInfo, idx) return { x: c.x * puzzleInfo.tileSize, y: c.y * puzzleInfo.tileSize, diff --git a/game/game.js b/game/game.js index 12c8823..9a05d2c 100644 --- a/game/game.js +++ b/game/game.js @@ -27,18 +27,6 @@ function addCanvasToDom(canvas) { return canvas } -function getActivePlayers(players) { - const ts = Util.timestamp() - const activePlayers = [] - for (let id of Object.keys(players)) { - const player = players[id] - if (player.ts >= ts - 30000) { - activePlayers.push(player) - } - } - return activePlayers -} - function addMenuToDom(previewImageUrl) { function row (...elements) { const row = document.createElement('tr') @@ -141,8 +129,8 @@ function addMenuToDom(previewImageUrl) { scoresTitleEl.appendChild(document.createTextNode('Scores')) const scoresListEl = document.createElement('table') - const updateScores = (players) => { - const activePlayers = getActivePlayers(players) + const updateScores = (gameId) => { + const activePlayers = Game.getActivePlayers(gameId) const scores = activePlayers.map(p => ({ name: p.name, points: p.points, @@ -188,15 +176,6 @@ function initme() { return ID } -const getFirstOwnedTile = (puzzle, userId) => { - for (let t of puzzle.tiles) { - if (t.owner === userId) { - return t - } - } - return null -} - export default class EventAdapter { constructor(canvas, viewport) { this.events = [] @@ -279,20 +258,12 @@ async function main() { } const game = await Communication.connect(gameId, CLIENT_ID) - Game.createGame(GAME_ID, game); + Game.newGame(game) const bitmaps = await PuzzleGraphics.loadPuzzleBitmaps(game.puzzle) - const puzzle = game.puzzle - const players = game.players - const changePlayer = (change) => { - for (let k of Object.keys(change)) { - players[CLIENT_ID][k] = change[k] - } - } - - const {bgColorPickerEl, playerColorPickerEl, nameChangeEl, updateScores} = addMenuToDom(game.puzzle.info.imageUrl) - updateScores(players) + const {bgColorPickerEl, playerColorPickerEl, nameChangeEl, updateScores} = addMenuToDom(Game.getImageUrl(gameId)) + updateScores(gameId) // Create a dom and attach adapters to it so we can work with it const canvas = addCanvasToDom(Graphics.createCanvas()) @@ -303,21 +274,21 @@ async function main() { const viewport = new Camera(canvas) // center viewport viewport.move( - -(puzzle.info.table.width - viewport.width) /2, - -(puzzle.info.table.height - viewport.height) /2 + -(Game.getTableWidth(gameId) - viewport.width) /2, + -(Game.getTableHeight(gameId) - viewport.height) /2 ) const evts = new EventAdapter(canvas, viewport) - bgColorPickerEl.value = players[CLIENT_ID].bgcolor + bgColorPickerEl.value = Game.getPlayerBgColor(gameId, CLIENT_ID) bgColorPickerEl.addEventListener('change', () => { evts.addEvent(['bg_color', bgColorPickerEl.value]) }) - playerColorPickerEl.value = players[CLIENT_ID].color + playerColorPickerEl.value = Game.getPlayerBgColor(gameId, CLIENT_ID) playerColorPickerEl.addEventListener('change', () => { evts.addEvent(['player_color', playerColorPickerEl.value]) }) - nameChangeEl.value = players[CLIENT_ID].name + nameChangeEl.value = Game.getPlayerName(gameId, CLIENT_ID) nameChangeEl.addEventListener('change', () => { evts.addEvent(['player_name', nameChangeEl.value]) }) @@ -330,28 +301,25 @@ async function main() { for(let [changeType, changeData] of evChanges) { switch (changeType) { case 'player': { - if (changeData.id !== CLIENT_ID) { - players[changeData.id] = changeData + const p = Util.decodePlayer(changeData) + if (p.id !== CLIENT_ID) { + Game.setPlayer(gameId, p.id, p) RERENDER = true } } break; case 'tile': { - puzzle.tiles[changeData.idx] = changeData + const t = Util.decodeTile(changeData) + Game.setTile(gameId, t.idx, t) RERENDER = true } break; case 'data': { - puzzle.data = changeData + Game.setPuzzleData(gameId, changeData) RERENDER = true } break; } } }) - const tilesSortedByZIndex = () => { - const sorted = puzzle.tiles.slice() - return sorted.sort((t1, t2) => t1.z - t2.z) - } - let _last_mouse_down = null const onUpdate = () => { for (let evt of evts.consumeAll()) { @@ -360,12 +328,9 @@ async function main() { // ------------------------------------------------------------- const type = evt[0] if (type === 'move') { - const pos = { x: evt[1], y: evt[2] } - RERENDER = true - changePlayer(pos) - - if (_last_mouse_down && !getFirstOwnedTile(puzzle, CLIENT_ID)) { + if (_last_mouse_down && !Game.getFirstOwnedTile(gameId, CLIENT_ID)) { // move the cam + const pos = { x: evt[1], y: evt[2] } const mouse = viewport.worldToViewport(pos) const diffX = Math.round(mouse.x - _last_mouse_down.x) const diffY = Math.round(mouse.y - _last_mouse_down.y) @@ -382,13 +347,13 @@ async function main() { if (viewport.zoomIn()) { const pos = { x: evt[1], y: evt[2] } RERENDER = true - changePlayer(pos) + Game.changePlayer(gameId, CLIENT_ID, pos) } } else if (type === 'zoomout') { if (viewport.zoomOut()) { const pos = { x: evt[1], y: evt[2] } RERENDER = true - changePlayer(pos) + Game.changePlayer(gameId, CLIENT_ID, pos) } } @@ -414,7 +379,7 @@ async function main() { // CLEAR CTX // --------------------------------------------------------------- - ctx.fillStyle = players[CLIENT_ID].bgcolor || '#222222' + ctx.fillStyle = Game.getPlayerBgColor(gameId, CLIENT_ID) || '#222222' ctx.fillRect(0, 0, canvas.width, canvas.height) if (DEBUG) Debug.checkpoint('clear done') // --------------------------------------------------------------- @@ -423,12 +388,12 @@ async function main() { // DRAW BOARD // --------------------------------------------------------------- pos = viewport.worldToViewport({ - x: (puzzle.info.table.width - puzzle.info.width) / 2, - y: (puzzle.info.table.height - puzzle.info.height) / 2 + x: (Game.getTableWidth(gameId) - Game.getPuzzleWidth(gameId)) / 2, + y: (Game.getTableHeight(gameId) - Game.getPuzzleHeight(gameId)) / 2 }) dim = viewport.worldDimToViewport({ - w: puzzle.info.width, - h: puzzle.info.height, + w: Game.getPuzzleWidth(gameId), + h: Game.getPuzzleHeight(gameId), }) ctx.fillStyle = 'rgba(255, 255, 255, .5)' ctx.fillRect(pos.x, pos.y, dim.w, dim.h) @@ -438,15 +403,15 @@ async function main() { // DRAW TILES // --------------------------------------------------------------- - for (let tile of tilesSortedByZIndex()) { + for (let tile of Game.getTilesSortedByZIndex(gameId)) { const bmp = bitmaps[tile.idx] pos = viewport.worldToViewport({ - x: puzzle.info.tileDrawOffset + tile.pos.x, - y: puzzle.info.tileDrawOffset + tile.pos.y, + x: Game.getTileDrawOffset(gameId) + tile.pos.x, + y: Game.getTileDrawOffset(gameId) + tile.pos.y, }) dim = viewport.worldDimToViewport({ - w: puzzle.info.tileDrawSize, - h: puzzle.info.tileDrawSize, + w: Game.getTileDrawSize(gameId), + h: Game.getTileDrawSize(gameId), }) ctx.drawImage(bmp, 0, 0, bmp.width, bmp.height, @@ -459,18 +424,18 @@ async function main() { // DRAW PLAYERS // --------------------------------------------------------------- - for (let p of getActivePlayers(players)) { - const cursor = await getPlayerCursor(p) - const pos = viewport.worldToViewport(p) + for (let player of Game.getActivePlayers(gameId)) { + const cursor = await getPlayerCursor(player) + const pos = viewport.worldToViewport(player) ctx.drawImage(cursor, Math.round(pos.x - cursor.width/2), Math.round(pos.y - cursor.height/2) ) - if (p.id !== CLIENT_ID) { + if (player.id !== CLIENT_ID) { ctx.fillStyle = 'white' ctx.font = '10px sans-serif' ctx.textAlign = 'center' - ctx.fillText(p.name + ' (' + p.points + ')', + ctx.fillText(player.name + ' (' + player.points + ')', Math.round(pos.x), Math.round(pos.y) + cursor.height ) @@ -480,7 +445,7 @@ async function main() { // DRAW PLAYERS // --------------------------------------------------------------- - updateScores(players) + updateScores(gameId) if (DEBUG) Debug.checkpoint('scores done') // --------------------------------------------------------------- diff --git a/game/index.js b/game/index.js index 191027d..ec42324 100644 --- a/game/index.js +++ b/game/index.js @@ -38,12 +38,16 @@ export default {

Running games

- {{g.title}} + + +
+ {{g.tilesFinished}}/{{g.tilesTotal}} pieces, {{g.players}} players +

New game

- +
diff --git a/server/Game.js b/server/Game.js index 8d14e87..1368036 100644 --- a/server/Game.js +++ b/server/Game.js @@ -3,13 +3,13 @@ import { createPuzzle } from './Puzzle.js' import GameCommon from './../common/GameCommon.js' async function createGame(gameId, targetTiles, image) { - const game = { + GameCommon.newGame({ + id: gameId, puzzle: await createPuzzle(targetTiles, image), players: {}, sockets: [], evtInfos: {}, - } - GameCommon.setGame(gameId, game) + }) } function loadAllGames() { @@ -21,20 +21,20 @@ function loadAllGames() { const gameId = f.replace(/\.json$/, '') const contents = fs.readFileSync(`./../data/${f}`, 'utf-8') const game = JSON.parse(contents) - GameCommon.setGame(gameId, { + GameCommon.newGame({ + id: gameId, puzzle: game.puzzle, players: game.players, sockets: [], - evtInfos: {}, + evtInfos: {} }) } } function persistAll() { - const games = GameCommon.getAllGames() - for (const gameId of Object.keys(games)) { - const game = games[gameId] - fs.writeFileSync('./../data/' + gameId + '.json', JSON.stringify({ + for (const game of GameCommon.getAllGames()) { + fs.writeFileSync('./../data/' + game.id + '.json', JSON.stringify({ + id: game.id, puzzle: game.puzzle, players: game.players, })) @@ -43,9 +43,13 @@ function persistAll() { export default { loadAllGames, - getAllGames: GameCommon.getAllGames, persistAll, createGame, + getAllGames: GameCommon.getAllGames, + getActivePlayers: GameCommon.getActivePlayers, + getFinishedTileCount: GameCommon.getFinishedTileCount, + getImageUrl: GameCommon.getImageUrl, + getTileCount: GameCommon.getTileCount, exists: GameCommon.exists, addPlayer: GameCommon.addPlayer, playerExists: GameCommon.playerExists, diff --git a/server/Puzzle.js b/server/Puzzle.js index c5ece8e..667a871 100644 --- a/server/Puzzle.js +++ b/server/Puzzle.js @@ -23,11 +23,12 @@ async function createPuzzle(targetTiles, image) { let positions = new Array(info.tiles) for (let tile of tiles) { + let coord = Util.coordByTileIdx(info, tile.idx) positions[tile.idx] ={ // instead of info.tileSize, we use info.tileDrawSize // to spread the tiles a bit - x: (info.coords[tile.idx].x) * (info.tileSize * 1.5), - y: (info.coords[tile.idx].y) * (info.tileSize * 1.5), + x: coord.x * info.tileSize * 1.5, + y: coord.y * info.tileSize * 1.5, } } @@ -73,7 +74,7 @@ async function createPuzzle(targetTiles, image) { positions = Util.shuffle(positions) tiles = tiles.map(tile => { - return { + return Util.encodeTile({ idx: tile.idx, // index of tile in the array group: 0, // if grouped with other tiles z: 0, // z index of the tile @@ -88,7 +89,7 @@ async function createPuzzle(targetTiles, image) { // this position is the initial position only and is the // value that changes when moving a tile pos: positions[tile.idx], - } + }) }) // Complete puzzle object @@ -125,7 +126,6 @@ async function createPuzzle(targetTiles, image) { tiles: info.tiles, // the final number of tiles in the puzzle tilesX: info.tilesX, // number of tiles each row tilesY: info.tilesY, // number of tiles each col - coords: info.coords, // map of tile index to its coordinates // ( index => {x, y} ) // this is not the physical coordinate, but // the tile_coordinate @@ -141,12 +141,13 @@ function determinePuzzleTileShapes(info) { const shapes = new Array(info.tiles) for (let i = 0; i < info.tiles; i++) { - shapes[i] = { - top: info.coords[i].y === 0 ? 0 : shapes[i - info.tilesX].bottom * -1, - right: info.coords[i].x === info.tilesX - 1 ? 0 : Util.choice(tabs), - left: info.coords[i].x === 0 ? 0 : shapes[i - 1].right * -1, - bottom: info.coords[i].y === info.tilesY - 1 ? 0 : Util.choice(tabs), - } + let coord = Util.coordByTileIdx(info, i) + shapes[i] = Util.encodeShape({ + top: coord.y === 0 ? 0 : shapes[i - info.tilesX].bottom * -1, + right: coord.x === info.tilesX - 1 ? 0 : Util.choice(tabs), + left: coord.x === 0 ? 0 : shapes[i - 1].right * -1, + bottom: coord.y === info.tilesY - 1 ? 0 : Util.choice(tabs), + }) } return shapes } @@ -173,7 +174,6 @@ const determinePuzzleInfo = (w, h, targetTiles) => { const tileSize = TILE_SIZE const width = tilesX * tileSize const height = tilesY * tileSize - const coords = buildCoords({ width, height, tileSize, tiles }) const tileMarginWidth = tileSize * .5; const tileDrawSize = Math.round(tileSize + tileMarginWidth * 2) @@ -187,21 +187,9 @@ const determinePuzzleInfo = (w, h, targetTiles) => { tiles, tilesX, tilesY, - coords, } } -const buildCoords = (puzzleInfo) => { - const wTiles = puzzleInfo.width / puzzleInfo.tileSize - const coords = new Array(puzzleInfo.tiles) - for (let i = 0; i < puzzleInfo.tiles; i++) { - const y = Math.floor(i / wTiles) - const x = i % wTiles - coords[i] = { x, y } - } - return coords -} - export { createPuzzle, } diff --git a/server/index.js b/server/index.js index 74a5215..73ba731 100644 --- a/server/index.js +++ b/server/index.js @@ -76,9 +76,12 @@ app.use('/uploads/', express.static('./../data/uploads/')) app.use('/', async (req, res, next) => { if (req.path === '/') { const games = [ - ...Object.keys(Game.getAllGames()).map(id => ({ - id: id, - title: id, + ...Game.getAllGames().map(game => ({ + id: game.id, + tilesFinished: Game.getFinishedTileCount(game.id), + tilesTotal: Game.getTileCount(game.id), + players: Game.getActivePlayers(game.id).length, + imageUrl: Game.getImageUrl(game.id), })), ] @@ -126,8 +129,10 @@ wss.on('message', async ({socket, data}) => { const game = Game.get(gameId) notify( [Protocol.EV_SERVER_INIT, { + id: game.id, puzzle: game.puzzle, players: game.players, + sockets: [], evtInfos: game.evtInfos, }], [socket] @@ -143,8 +148,10 @@ wss.on('message', async ({socket, data}) => { const game = Game.get(gameId) notify( [Protocol.EV_SERVER_INIT, { + id: game.id, puzzle: game.puzzle, players: game.players, + sockets: [], evtInfos: game.evtInfos, }], [socket]