reduce size of game json files

This commit is contained in:
Zutatensuppe 2020-12-05 19:45:34 +01:00
parent c6899a615b
commit b6a3cfd8ba
9 changed files with 380 additions and 149 deletions

View file

@ -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,
}

View file

@ -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,
}

View file

@ -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,
}

View file

@ -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,

View file

@ -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')
// ---------------------------------------------------------------

View file

@ -38,12 +38,16 @@ export default {
<div id="app">
<h1>Running games</h1>
<div v-for="g in games">
<a :href="'/g/' + g.id">{{g.title}}</a>
<a :href="'/g/' + g.id">
<img :src="g.imageUrl" style="width: 150px; display: inline-block; margin: 5px;" />
<br />
{{g.tilesFinished}}/{{g.tilesTotal}} pieces, {{g.players}} players
</a>
</div>
<h1>New game</h1>
<div>
<label>Tiles: </label>
<label>Pieces: </label>
<input type="text" v-model="tiles" />
</div>
<div>

View file

@ -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,

View file

@ -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,
}

View file

@ -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]