reduce size of game json files
This commit is contained in:
parent
c6899a615b
commit
b6a3cfd8ba
9 changed files with 380 additions and 149 deletions
|
|
@ -7,28 +7,70 @@ function exists(gameId) {
|
||||||
return (!!GAMES[gameId]) || false
|
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) {
|
function setGame(gameId, game) {
|
||||||
GAMES[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) {
|
function playerExists(gameId, playerId) {
|
||||||
return !!GAMES[gameId].players[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) {
|
function addPlayer(gameId, playerId) {
|
||||||
const ts = Util.timestamp()
|
const ts = Util.timestamp()
|
||||||
if (!GAMES[gameId].players[playerId]) {
|
if (!GAMES[gameId].players[playerId]) {
|
||||||
GAMES[gameId].players[playerId] = {
|
setPlayer(gameId, playerId, createPlayer(playerId, ts))
|
||||||
id: playerId,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
d: 0, // mouse down
|
|
||||||
name: 'anon',
|
|
||||||
color: '#ffffff',
|
|
||||||
bgcolor: '#222222',
|
|
||||||
points: 0,
|
|
||||||
ts,
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
changePlayer(gameId, playerId, { ts })
|
changePlayer(gameId, playerId, { ts })
|
||||||
}
|
}
|
||||||
|
|
@ -56,21 +98,52 @@ function removeSocket(gameId, socket) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllGames() {
|
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) {
|
function get(gameId) {
|
||||||
return GAMES[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) {
|
function getSockets(gameId) {
|
||||||
return GAMES[gameId].sockets
|
return GAMES[gameId].sockets
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePlayer(gameId, playerId, change) {
|
function changePlayer(gameId, playerId, change) {
|
||||||
|
const player = getPlayer(gameId, playerId)
|
||||||
for (let k of Object.keys(change)) {
|
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) {
|
function changeData(gameId, change) {
|
||||||
|
|
@ -81,12 +154,14 @@ function changeData(gameId, change) {
|
||||||
|
|
||||||
function changeTile(gameId, tileIdx, change) {
|
function changeTile(gameId, tileIdx, change) {
|
||||||
for (let k of Object.keys(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) => {
|
const getTile = (gameId, tileIdx) => {
|
||||||
return GAMES[gameId].puzzle.tiles[tileIdx]
|
return Util.decodeTile(GAMES[gameId].puzzle.tiles[tileIdx])
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTileGroup = (gameId, tileIdx) => {
|
const getTileGroup = (gameId, tileIdx) => {
|
||||||
|
|
@ -116,13 +191,27 @@ const getTileZIndex = (gameId, tileIdx) => {
|
||||||
|
|
||||||
const getFirstOwnedTileIdx = (gameId, userId) => {
|
const getFirstOwnedTileIdx = (gameId, userId) => {
|
||||||
for (let t of GAMES[gameId].puzzle.tiles) {
|
for (let t of GAMES[gameId].puzzle.tiles) {
|
||||||
if (t.owner === userId) {
|
const tile = Util.decodeTile(t)
|
||||||
return t.idx
|
if (tile.owner === userId) {
|
||||||
|
return tile.idx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1
|
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) => {
|
const getMaxGroup = (gameId) => {
|
||||||
return GAMES[gameId].puzzle.data.maxGroup
|
return GAMES[gameId].puzzle.data.maxGroup
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +234,7 @@ const getMaxZIndexByTileIdxs = (gameId, tileIdxs) => {
|
||||||
function srcPosByTileIdx(gameId, tileIdx) {
|
function srcPosByTileIdx(gameId, tileIdx) {
|
||||||
const info = GAMES[gameId].puzzle.info
|
const info = GAMES[gameId].puzzle.info
|
||||||
|
|
||||||
const c = info.coords[tileIdx]
|
const c = Util.coordByTileIdx(info, tileIdx)
|
||||||
const cx = c.x * info.tileSize
|
const cx = c.x * info.tileSize
|
||||||
const cy = c.y * info.tileSize
|
const cy = c.y * info.tileSize
|
||||||
|
|
||||||
|
|
@ -155,18 +244,17 @@ function srcPosByTileIdx(gameId, tileIdx) {
|
||||||
function getSurroundingTilesByIdx(gameId, tileIdx) {
|
function getSurroundingTilesByIdx(gameId, tileIdx) {
|
||||||
const info = GAMES[gameId].puzzle.info
|
const info = GAMES[gameId].puzzle.info
|
||||||
|
|
||||||
const _X = info.coords[tileIdx].x
|
const c = Util.coordByTileIdx(info, tileIdx)
|
||||||
const _Y = info.coords[tileIdx].y
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
// top
|
// top
|
||||||
(_Y > 0) ? (tileIdx - info.tilesX) : -1,
|
(c.y > 0) ? (tileIdx - info.tilesX) : -1,
|
||||||
// right
|
// right
|
||||||
(_X < info.tilesX - 1) ? (tileIdx + 1) : -1,
|
(c.x < info.tilesX - 1) ? (tileIdx + 1) : -1,
|
||||||
// bottom
|
// bottom
|
||||||
(_Y < info.tilesY - 1) ? (tileIdx + info.tilesX) : -1,
|
(c.y < info.tilesY - 1) ? (tileIdx + info.tilesX) : -1,
|
||||||
// left
|
// 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
|
// get all grouped tiles for a tile
|
||||||
function getGroupedTileIdxs(gameId, tileIdx) {
|
function getGroupedTileIdxs(gameId, tileIdx) {
|
||||||
const tiles = GAMES[gameId].puzzle.tiles
|
const tiles = GAMES[gameId].puzzle.tiles
|
||||||
const tile = tiles[tileIdx]
|
const tile = Util.decodeTile(tiles[tileIdx])
|
||||||
|
|
||||||
const grouped = []
|
const grouped = []
|
||||||
if (tile.group) {
|
if (tile.group) {
|
||||||
for (let other of tiles) {
|
for (let other of tiles) {
|
||||||
if (other.group === tile.group) {
|
const otherTile = Util.decodeTile(other)
|
||||||
grouped.push(other.idx)
|
if (otherTile.group === tile.group) {
|
||||||
|
grouped.push(otherTile.idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -227,7 +316,7 @@ const freeTileIdxByPos = (gameId, pos) => {
|
||||||
let maxZ = -1
|
let maxZ = -1
|
||||||
let tileIdx = -1
|
let tileIdx = -1
|
||||||
for (let idx = 0; idx < tiles.length; idx++) {
|
for (let idx = 0; idx < tiles.length; idx++) {
|
||||||
const tile = tiles[idx]
|
const tile = Util.decodeTile(tiles[idx])
|
||||||
if (tile.owner !== 0) {
|
if (tile.owner !== 0) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -248,6 +337,22 @@ const freeTileIdxByPos = (gameId, pos) => {
|
||||||
return tileIdx
|
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
|
// determine if two tiles are grouped together
|
||||||
const areGrouped = (gameId, tileIdx1, tileIdx2) => {
|
const areGrouped = (gameId, tileIdx1, tileIdx2) => {
|
||||||
const g1 = getTileGroup(gameId, tileIdx1)
|
const g1 = getTileGroup(gameId, tileIdx1)
|
||||||
|
|
@ -255,9 +360,24 @@ const areGrouped = (gameId, tileIdx1, tileIdx2) => {
|
||||||
return g1 && g1 === g2
|
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) {
|
function handleInput(gameId, playerId, input) {
|
||||||
let puzzle = GAMES[gameId].puzzle
|
const puzzle = GAMES[gameId].puzzle
|
||||||
let players = GAMES[gameId].players
|
|
||||||
let evtInfo = GAMES[gameId].evtInfos[playerId]
|
let evtInfo = GAMES[gameId].evtInfos[playerId]
|
||||||
|
|
||||||
let changes = []
|
let changes = []
|
||||||
|
|
@ -277,7 +397,7 @@ function handleInput(gameId, playerId, input) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const _playerChange = () => {
|
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
|
// put both tiles (and their grouped tiles) in the same group
|
||||||
|
|
@ -312,7 +432,8 @@ function handleInput(gameId, playerId, input) {
|
||||||
|
|
||||||
// TODO: strange
|
// TODO: strange
|
||||||
if (searchGroups.length > 0) {
|
if (searchGroups.length > 0) {
|
||||||
for (let tile of tiles) {
|
for (let t of tiles) {
|
||||||
|
const tile = Util.decodeTile(t)
|
||||||
if (searchGroups.includes(tile.group)) {
|
if (searchGroups.includes(tile.group)) {
|
||||||
changeTile(gameId, tile.idx, { group })
|
changeTile(gameId, tile.idx, { group })
|
||||||
_tileChange(tile.idx)
|
_tileChange(tile.idx)
|
||||||
|
|
@ -404,7 +525,7 @@ function handleInput(gameId, playerId, input) {
|
||||||
// Snap the tile to the final destination
|
// Snap the tile to the final destination
|
||||||
moveTilesDiff(gameId, tileIdxs, diff)
|
moveTilesDiff(gameId, tileIdxs, diff)
|
||||||
finishTiles(gameId, tileIdxs)
|
finishTiles(gameId, tileIdxs)
|
||||||
changePlayer(gameId, playerId, { points: players[playerId].points + tileIdxs.length })
|
changePlayer(gameId, playerId, { points: getPlayerPoints(gameId, playerId) + tileIdxs.length })
|
||||||
_tileChanges(tileIdxs)
|
_tileChanges(tileIdxs)
|
||||||
} else {
|
} else {
|
||||||
// Snap to other tiles
|
// Snap to other tiles
|
||||||
|
|
@ -457,17 +578,35 @@ function handleInput(gameId, playerId, input) {
|
||||||
return changes
|
return changes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setGame,
|
newGame,
|
||||||
exists,
|
exists,
|
||||||
playerExists,
|
playerExists,
|
||||||
|
getActivePlayers,
|
||||||
addPlayer,
|
addPlayer,
|
||||||
socketExists,
|
socketExists,
|
||||||
addSocket,
|
addSocket,
|
||||||
removeSocket,
|
removeSocket,
|
||||||
|
getFinishedTileCount,
|
||||||
|
getTileCount,
|
||||||
|
getImageUrl,
|
||||||
get,
|
get,
|
||||||
getAllGames,
|
getAllGames,
|
||||||
getSockets,
|
getSockets,
|
||||||
|
getPlayerBgColor,
|
||||||
|
getPlayerColor,
|
||||||
|
getPlayerName,
|
||||||
|
changePlayer,
|
||||||
|
setPlayer,
|
||||||
|
setTile,
|
||||||
|
setPuzzleData,
|
||||||
|
getTableWidth,
|
||||||
|
getTableHeight,
|
||||||
|
getPuzzleWidth,
|
||||||
|
getPuzzleHeight,
|
||||||
|
getTilesSortedByZIndex,
|
||||||
|
getFirstOwnedTile,
|
||||||
|
getTileDrawOffset,
|
||||||
|
getTileDrawSize,
|
||||||
handleInput,
|
handleInput,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
105
common/Util.js
105
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 {
|
export default {
|
||||||
uniqId,
|
uniqId,
|
||||||
randomInt,
|
randomInt,
|
||||||
|
|
@ -53,4 +147,15 @@ export default {
|
||||||
throttle,
|
throttle,
|
||||||
shuffle,
|
shuffle,
|
||||||
timestamp,
|
timestamp,
|
||||||
|
|
||||||
|
encodeShape,
|
||||||
|
decodeShape,
|
||||||
|
|
||||||
|
encodeTile,
|
||||||
|
decodeTile,
|
||||||
|
|
||||||
|
encodePlayer,
|
||||||
|
decodePlayer,
|
||||||
|
|
||||||
|
coordByTileIdx,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
game/Game.js
19
game/Game.js
|
|
@ -1,6 +1,23 @@
|
||||||
import GameCommon from './../common/GameCommon.js'
|
import GameCommon from './../common/GameCommon.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createGame: GameCommon.setGame,
|
newGame: GameCommon.newGame,
|
||||||
|
getActivePlayers: GameCommon.getActivePlayers,
|
||||||
handleInput: GameCommon.handleInput,
|
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,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import Geometry from '../common/Geometry.js'
|
import Geometry from '../common/Geometry.js'
|
||||||
import Graphics from './Graphics.js'
|
import Graphics from './Graphics.js'
|
||||||
|
import Util from './../common/Util.js'
|
||||||
|
|
||||||
async function createPuzzleTileBitmaps(img, tiles, info) {
|
async function createPuzzleTileBitmaps(img, tiles, info) {
|
||||||
var tileSize = info.tileSize
|
var tileSize = info.tileSize
|
||||||
|
|
@ -76,9 +77,10 @@ async function createPuzzleTileBitmaps(img, tiles, info) {
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let tile of tiles) {
|
for (let t of tiles) {
|
||||||
|
const tile = Util.decodeTile(t)
|
||||||
const srcRect = srcRectByIdx(info, tile.idx)
|
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 c = Graphics.createCanvas(tileDrawSize, tileDrawSize)
|
||||||
const ctx = c.getContext('2d')
|
const ctx = c.getContext('2d')
|
||||||
|
|
@ -192,7 +194,7 @@ async function createPuzzleTileBitmaps(img, tiles, info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function srcRectByIdx(puzzleInfo, idx) {
|
function srcRectByIdx(puzzleInfo, idx) {
|
||||||
const c = puzzleInfo.coords[idx]
|
const c = Util.coordByTileIdx(puzzleInfo, idx)
|
||||||
return {
|
return {
|
||||||
x: c.x * puzzleInfo.tileSize,
|
x: c.x * puzzleInfo.tileSize,
|
||||||
y: c.y * puzzleInfo.tileSize,
|
y: c.y * puzzleInfo.tileSize,
|
||||||
|
|
|
||||||
107
game/game.js
107
game/game.js
|
|
@ -27,18 +27,6 @@ function addCanvasToDom(canvas) {
|
||||||
return 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 addMenuToDom(previewImageUrl) {
|
||||||
function row (...elements) {
|
function row (...elements) {
|
||||||
const row = document.createElement('tr')
|
const row = document.createElement('tr')
|
||||||
|
|
@ -141,8 +129,8 @@ function addMenuToDom(previewImageUrl) {
|
||||||
scoresTitleEl.appendChild(document.createTextNode('Scores'))
|
scoresTitleEl.appendChild(document.createTextNode('Scores'))
|
||||||
|
|
||||||
const scoresListEl = document.createElement('table')
|
const scoresListEl = document.createElement('table')
|
||||||
const updateScores = (players) => {
|
const updateScores = (gameId) => {
|
||||||
const activePlayers = getActivePlayers(players)
|
const activePlayers = Game.getActivePlayers(gameId)
|
||||||
const scores = activePlayers.map(p => ({
|
const scores = activePlayers.map(p => ({
|
||||||
name: p.name,
|
name: p.name,
|
||||||
points: p.points,
|
points: p.points,
|
||||||
|
|
@ -188,15 +176,6 @@ function initme() {
|
||||||
return ID
|
return ID
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFirstOwnedTile = (puzzle, userId) => {
|
|
||||||
for (let t of puzzle.tiles) {
|
|
||||||
if (t.owner === userId) {
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class EventAdapter {
|
export default class EventAdapter {
|
||||||
constructor(canvas, viewport) {
|
constructor(canvas, viewport) {
|
||||||
this.events = []
|
this.events = []
|
||||||
|
|
@ -279,20 +258,12 @@ async function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const game = await Communication.connect(gameId, CLIENT_ID)
|
const game = await Communication.connect(gameId, CLIENT_ID)
|
||||||
Game.createGame(GAME_ID, game);
|
Game.newGame(game)
|
||||||
|
|
||||||
const bitmaps = await PuzzleGraphics.loadPuzzleBitmaps(game.puzzle)
|
const bitmaps = await PuzzleGraphics.loadPuzzleBitmaps(game.puzzle)
|
||||||
const puzzle = game.puzzle
|
|
||||||
const players = game.players
|
|
||||||
|
|
||||||
const changePlayer = (change) => {
|
const {bgColorPickerEl, playerColorPickerEl, nameChangeEl, updateScores} = addMenuToDom(Game.getImageUrl(gameId))
|
||||||
for (let k of Object.keys(change)) {
|
updateScores(gameId)
|
||||||
players[CLIENT_ID][k] = change[k]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const {bgColorPickerEl, playerColorPickerEl, nameChangeEl, updateScores} = addMenuToDom(game.puzzle.info.imageUrl)
|
|
||||||
updateScores(players)
|
|
||||||
|
|
||||||
// Create a dom and attach adapters to it so we can work with it
|
// Create a dom and attach adapters to it so we can work with it
|
||||||
const canvas = addCanvasToDom(Graphics.createCanvas())
|
const canvas = addCanvasToDom(Graphics.createCanvas())
|
||||||
|
|
@ -303,21 +274,21 @@ async function main() {
|
||||||
const viewport = new Camera(canvas)
|
const viewport = new Camera(canvas)
|
||||||
// center viewport
|
// center viewport
|
||||||
viewport.move(
|
viewport.move(
|
||||||
-(puzzle.info.table.width - viewport.width) /2,
|
-(Game.getTableWidth(gameId) - viewport.width) /2,
|
||||||
-(puzzle.info.table.height - viewport.height) /2
|
-(Game.getTableHeight(gameId) - viewport.height) /2
|
||||||
)
|
)
|
||||||
|
|
||||||
const evts = new EventAdapter(canvas, viewport)
|
const evts = new EventAdapter(canvas, viewport)
|
||||||
|
|
||||||
bgColorPickerEl.value = players[CLIENT_ID].bgcolor
|
bgColorPickerEl.value = Game.getPlayerBgColor(gameId, CLIENT_ID)
|
||||||
bgColorPickerEl.addEventListener('change', () => {
|
bgColorPickerEl.addEventListener('change', () => {
|
||||||
evts.addEvent(['bg_color', bgColorPickerEl.value])
|
evts.addEvent(['bg_color', bgColorPickerEl.value])
|
||||||
})
|
})
|
||||||
playerColorPickerEl.value = players[CLIENT_ID].color
|
playerColorPickerEl.value = Game.getPlayerBgColor(gameId, CLIENT_ID)
|
||||||
playerColorPickerEl.addEventListener('change', () => {
|
playerColorPickerEl.addEventListener('change', () => {
|
||||||
evts.addEvent(['player_color', playerColorPickerEl.value])
|
evts.addEvent(['player_color', playerColorPickerEl.value])
|
||||||
})
|
})
|
||||||
nameChangeEl.value = players[CLIENT_ID].name
|
nameChangeEl.value = Game.getPlayerName(gameId, CLIENT_ID)
|
||||||
nameChangeEl.addEventListener('change', () => {
|
nameChangeEl.addEventListener('change', () => {
|
||||||
evts.addEvent(['player_name', nameChangeEl.value])
|
evts.addEvent(['player_name', nameChangeEl.value])
|
||||||
})
|
})
|
||||||
|
|
@ -330,28 +301,25 @@ async function main() {
|
||||||
for(let [changeType, changeData] of evChanges) {
|
for(let [changeType, changeData] of evChanges) {
|
||||||
switch (changeType) {
|
switch (changeType) {
|
||||||
case 'player': {
|
case 'player': {
|
||||||
if (changeData.id !== CLIENT_ID) {
|
const p = Util.decodePlayer(changeData)
|
||||||
players[changeData.id] = changeData
|
if (p.id !== CLIENT_ID) {
|
||||||
|
Game.setPlayer(gameId, p.id, p)
|
||||||
RERENDER = true
|
RERENDER = true
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case 'tile': {
|
case 'tile': {
|
||||||
puzzle.tiles[changeData.idx] = changeData
|
const t = Util.decodeTile(changeData)
|
||||||
|
Game.setTile(gameId, t.idx, t)
|
||||||
RERENDER = true
|
RERENDER = true
|
||||||
} break;
|
} break;
|
||||||
case 'data': {
|
case 'data': {
|
||||||
puzzle.data = changeData
|
Game.setPuzzleData(gameId, changeData)
|
||||||
RERENDER = true
|
RERENDER = true
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const tilesSortedByZIndex = () => {
|
|
||||||
const sorted = puzzle.tiles.slice()
|
|
||||||
return sorted.sort((t1, t2) => t1.z - t2.z)
|
|
||||||
}
|
|
||||||
|
|
||||||
let _last_mouse_down = null
|
let _last_mouse_down = null
|
||||||
const onUpdate = () => {
|
const onUpdate = () => {
|
||||||
for (let evt of evts.consumeAll()) {
|
for (let evt of evts.consumeAll()) {
|
||||||
|
|
@ -360,12 +328,9 @@ async function main() {
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
const type = evt[0]
|
const type = evt[0]
|
||||||
if (type === 'move') {
|
if (type === 'move') {
|
||||||
const pos = { x: evt[1], y: evt[2] }
|
if (_last_mouse_down && !Game.getFirstOwnedTile(gameId, CLIENT_ID)) {
|
||||||
RERENDER = true
|
|
||||||
changePlayer(pos)
|
|
||||||
|
|
||||||
if (_last_mouse_down && !getFirstOwnedTile(puzzle, CLIENT_ID)) {
|
|
||||||
// move the cam
|
// move the cam
|
||||||
|
const pos = { x: evt[1], y: evt[2] }
|
||||||
const mouse = viewport.worldToViewport(pos)
|
const mouse = viewport.worldToViewport(pos)
|
||||||
const diffX = Math.round(mouse.x - _last_mouse_down.x)
|
const diffX = Math.round(mouse.x - _last_mouse_down.x)
|
||||||
const diffY = Math.round(mouse.y - _last_mouse_down.y)
|
const diffY = Math.round(mouse.y - _last_mouse_down.y)
|
||||||
|
|
@ -382,13 +347,13 @@ async function main() {
|
||||||
if (viewport.zoomIn()) {
|
if (viewport.zoomIn()) {
|
||||||
const pos = { x: evt[1], y: evt[2] }
|
const pos = { x: evt[1], y: evt[2] }
|
||||||
RERENDER = true
|
RERENDER = true
|
||||||
changePlayer(pos)
|
Game.changePlayer(gameId, CLIENT_ID, pos)
|
||||||
}
|
}
|
||||||
} else if (type === 'zoomout') {
|
} else if (type === 'zoomout') {
|
||||||
if (viewport.zoomOut()) {
|
if (viewport.zoomOut()) {
|
||||||
const pos = { x: evt[1], y: evt[2] }
|
const pos = { x: evt[1], y: evt[2] }
|
||||||
RERENDER = true
|
RERENDER = true
|
||||||
changePlayer(pos)
|
Game.changePlayer(gameId, CLIENT_ID, pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -414,7 +379,7 @@ async function main() {
|
||||||
|
|
||||||
// CLEAR CTX
|
// 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)
|
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
||||||
if (DEBUG) Debug.checkpoint('clear done')
|
if (DEBUG) Debug.checkpoint('clear done')
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
@ -423,12 +388,12 @@ async function main() {
|
||||||
// DRAW BOARD
|
// DRAW BOARD
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
pos = viewport.worldToViewport({
|
pos = viewport.worldToViewport({
|
||||||
x: (puzzle.info.table.width - puzzle.info.width) / 2,
|
x: (Game.getTableWidth(gameId) - Game.getPuzzleWidth(gameId)) / 2,
|
||||||
y: (puzzle.info.table.height - puzzle.info.height) / 2
|
y: (Game.getTableHeight(gameId) - Game.getPuzzleHeight(gameId)) / 2
|
||||||
})
|
})
|
||||||
dim = viewport.worldDimToViewport({
|
dim = viewport.worldDimToViewport({
|
||||||
w: puzzle.info.width,
|
w: Game.getPuzzleWidth(gameId),
|
||||||
h: puzzle.info.height,
|
h: Game.getPuzzleHeight(gameId),
|
||||||
})
|
})
|
||||||
ctx.fillStyle = 'rgba(255, 255, 255, .5)'
|
ctx.fillStyle = 'rgba(255, 255, 255, .5)'
|
||||||
ctx.fillRect(pos.x, pos.y, dim.w, dim.h)
|
ctx.fillRect(pos.x, pos.y, dim.w, dim.h)
|
||||||
|
|
@ -438,15 +403,15 @@ async function main() {
|
||||||
|
|
||||||
// DRAW TILES
|
// DRAW TILES
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
for (let tile of tilesSortedByZIndex()) {
|
for (let tile of Game.getTilesSortedByZIndex(gameId)) {
|
||||||
const bmp = bitmaps[tile.idx]
|
const bmp = bitmaps[tile.idx]
|
||||||
pos = viewport.worldToViewport({
|
pos = viewport.worldToViewport({
|
||||||
x: puzzle.info.tileDrawOffset + tile.pos.x,
|
x: Game.getTileDrawOffset(gameId) + tile.pos.x,
|
||||||
y: puzzle.info.tileDrawOffset + tile.pos.y,
|
y: Game.getTileDrawOffset(gameId) + tile.pos.y,
|
||||||
})
|
})
|
||||||
dim = viewport.worldDimToViewport({
|
dim = viewport.worldDimToViewport({
|
||||||
w: puzzle.info.tileDrawSize,
|
w: Game.getTileDrawSize(gameId),
|
||||||
h: puzzle.info.tileDrawSize,
|
h: Game.getTileDrawSize(gameId),
|
||||||
})
|
})
|
||||||
ctx.drawImage(bmp,
|
ctx.drawImage(bmp,
|
||||||
0, 0, bmp.width, bmp.height,
|
0, 0, bmp.width, bmp.height,
|
||||||
|
|
@ -459,18 +424,18 @@ async function main() {
|
||||||
|
|
||||||
// DRAW PLAYERS
|
// DRAW PLAYERS
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
for (let p of getActivePlayers(players)) {
|
for (let player of Game.getActivePlayers(gameId)) {
|
||||||
const cursor = await getPlayerCursor(p)
|
const cursor = await getPlayerCursor(player)
|
||||||
const pos = viewport.worldToViewport(p)
|
const pos = viewport.worldToViewport(player)
|
||||||
ctx.drawImage(cursor,
|
ctx.drawImage(cursor,
|
||||||
Math.round(pos.x - cursor.width/2),
|
Math.round(pos.x - cursor.width/2),
|
||||||
Math.round(pos.y - cursor.height/2)
|
Math.round(pos.y - cursor.height/2)
|
||||||
)
|
)
|
||||||
if (p.id !== CLIENT_ID) {
|
if (player.id !== CLIENT_ID) {
|
||||||
ctx.fillStyle = 'white'
|
ctx.fillStyle = 'white'
|
||||||
ctx.font = '10px sans-serif'
|
ctx.font = '10px sans-serif'
|
||||||
ctx.textAlign = 'center'
|
ctx.textAlign = 'center'
|
||||||
ctx.fillText(p.name + ' (' + p.points + ')',
|
ctx.fillText(player.name + ' (' + player.points + ')',
|
||||||
Math.round(pos.x),
|
Math.round(pos.x),
|
||||||
Math.round(pos.y) + cursor.height
|
Math.round(pos.y) + cursor.height
|
||||||
)
|
)
|
||||||
|
|
@ -480,7 +445,7 @@ async function main() {
|
||||||
|
|
||||||
// DRAW PLAYERS
|
// DRAW PLAYERS
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
updateScores(players)
|
updateScores(gameId)
|
||||||
if (DEBUG) Debug.checkpoint('scores done')
|
if (DEBUG) Debug.checkpoint('scores done')
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,16 @@ export default {
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<h1>Running games</h1>
|
<h1>Running games</h1>
|
||||||
<div v-for="g in games">
|
<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>
|
</div>
|
||||||
|
|
||||||
<h1>New game</h1>
|
<h1>New game</h1>
|
||||||
<div>
|
<div>
|
||||||
<label>Tiles: </label>
|
<label>Pieces: </label>
|
||||||
<input type="text" v-model="tiles" />
|
<input type="text" v-model="tiles" />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@ import { createPuzzle } from './Puzzle.js'
|
||||||
import GameCommon from './../common/GameCommon.js'
|
import GameCommon from './../common/GameCommon.js'
|
||||||
|
|
||||||
async function createGame(gameId, targetTiles, image) {
|
async function createGame(gameId, targetTiles, image) {
|
||||||
const game = {
|
GameCommon.newGame({
|
||||||
|
id: gameId,
|
||||||
puzzle: await createPuzzle(targetTiles, image),
|
puzzle: await createPuzzle(targetTiles, image),
|
||||||
players: {},
|
players: {},
|
||||||
sockets: [],
|
sockets: [],
|
||||||
evtInfos: {},
|
evtInfos: {},
|
||||||
}
|
})
|
||||||
GameCommon.setGame(gameId, game)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadAllGames() {
|
function loadAllGames() {
|
||||||
|
|
@ -21,20 +21,20 @@ function loadAllGames() {
|
||||||
const gameId = f.replace(/\.json$/, '')
|
const gameId = f.replace(/\.json$/, '')
|
||||||
const contents = fs.readFileSync(`./../data/${f}`, 'utf-8')
|
const contents = fs.readFileSync(`./../data/${f}`, 'utf-8')
|
||||||
const game = JSON.parse(contents)
|
const game = JSON.parse(contents)
|
||||||
GameCommon.setGame(gameId, {
|
GameCommon.newGame({
|
||||||
|
id: gameId,
|
||||||
puzzle: game.puzzle,
|
puzzle: game.puzzle,
|
||||||
players: game.players,
|
players: game.players,
|
||||||
sockets: [],
|
sockets: [],
|
||||||
evtInfos: {},
|
evtInfos: {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function persistAll() {
|
function persistAll() {
|
||||||
const games = GameCommon.getAllGames()
|
for (const game of GameCommon.getAllGames()) {
|
||||||
for (const gameId of Object.keys(games)) {
|
fs.writeFileSync('./../data/' + game.id + '.json', JSON.stringify({
|
||||||
const game = games[gameId]
|
id: game.id,
|
||||||
fs.writeFileSync('./../data/' + gameId + '.json', JSON.stringify({
|
|
||||||
puzzle: game.puzzle,
|
puzzle: game.puzzle,
|
||||||
players: game.players,
|
players: game.players,
|
||||||
}))
|
}))
|
||||||
|
|
@ -43,9 +43,13 @@ function persistAll() {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
loadAllGames,
|
loadAllGames,
|
||||||
getAllGames: GameCommon.getAllGames,
|
|
||||||
persistAll,
|
persistAll,
|
||||||
createGame,
|
createGame,
|
||||||
|
getAllGames: GameCommon.getAllGames,
|
||||||
|
getActivePlayers: GameCommon.getActivePlayers,
|
||||||
|
getFinishedTileCount: GameCommon.getFinishedTileCount,
|
||||||
|
getImageUrl: GameCommon.getImageUrl,
|
||||||
|
getTileCount: GameCommon.getTileCount,
|
||||||
exists: GameCommon.exists,
|
exists: GameCommon.exists,
|
||||||
addPlayer: GameCommon.addPlayer,
|
addPlayer: GameCommon.addPlayer,
|
||||||
playerExists: GameCommon.playerExists,
|
playerExists: GameCommon.playerExists,
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,12 @@ async function createPuzzle(targetTiles, image) {
|
||||||
|
|
||||||
let positions = new Array(info.tiles)
|
let positions = new Array(info.tiles)
|
||||||
for (let tile of tiles) {
|
for (let tile of tiles) {
|
||||||
|
let coord = Util.coordByTileIdx(info, tile.idx)
|
||||||
positions[tile.idx] ={
|
positions[tile.idx] ={
|
||||||
// instead of info.tileSize, we use info.tileDrawSize
|
// instead of info.tileSize, we use info.tileDrawSize
|
||||||
// to spread the tiles a bit
|
// to spread the tiles a bit
|
||||||
x: (info.coords[tile.idx].x) * (info.tileSize * 1.5),
|
x: coord.x * info.tileSize * 1.5,
|
||||||
y: (info.coords[tile.idx].y) * (info.tileSize * 1.5),
|
y: coord.y * info.tileSize * 1.5,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +74,7 @@ async function createPuzzle(targetTiles, image) {
|
||||||
positions = Util.shuffle(positions)
|
positions = Util.shuffle(positions)
|
||||||
|
|
||||||
tiles = tiles.map(tile => {
|
tiles = tiles.map(tile => {
|
||||||
return {
|
return Util.encodeTile({
|
||||||
idx: tile.idx, // index of tile in the array
|
idx: tile.idx, // index of tile in the array
|
||||||
group: 0, // if grouped with other tiles
|
group: 0, // if grouped with other tiles
|
||||||
z: 0, // z index of the tile
|
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
|
// this position is the initial position only and is the
|
||||||
// value that changes when moving a tile
|
// value that changes when moving a tile
|
||||||
pos: positions[tile.idx],
|
pos: positions[tile.idx],
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Complete puzzle object
|
// Complete puzzle object
|
||||||
|
|
@ -125,7 +126,6 @@ async function createPuzzle(targetTiles, image) {
|
||||||
tiles: info.tiles, // the final number of tiles in the puzzle
|
tiles: info.tiles, // the final number of tiles in the puzzle
|
||||||
tilesX: info.tilesX, // number of tiles each row
|
tilesX: info.tilesX, // number of tiles each row
|
||||||
tilesY: info.tilesY, // number of tiles each col
|
tilesY: info.tilesY, // number of tiles each col
|
||||||
coords: info.coords, // map of tile index to its coordinates
|
|
||||||
// ( index => {x, y} )
|
// ( index => {x, y} )
|
||||||
// this is not the physical coordinate, but
|
// this is not the physical coordinate, but
|
||||||
// the tile_coordinate
|
// the tile_coordinate
|
||||||
|
|
@ -141,12 +141,13 @@ function determinePuzzleTileShapes(info) {
|
||||||
|
|
||||||
const shapes = new Array(info.tiles)
|
const shapes = new Array(info.tiles)
|
||||||
for (let i = 0; i < info.tiles; i++) {
|
for (let i = 0; i < info.tiles; i++) {
|
||||||
shapes[i] = {
|
let coord = Util.coordByTileIdx(info, i)
|
||||||
top: info.coords[i].y === 0 ? 0 : shapes[i - info.tilesX].bottom * -1,
|
shapes[i] = Util.encodeShape({
|
||||||
right: info.coords[i].x === info.tilesX - 1 ? 0 : Util.choice(tabs),
|
top: coord.y === 0 ? 0 : shapes[i - info.tilesX].bottom * -1,
|
||||||
left: info.coords[i].x === 0 ? 0 : shapes[i - 1].right * -1,
|
right: coord.x === info.tilesX - 1 ? 0 : Util.choice(tabs),
|
||||||
bottom: info.coords[i].y === info.tilesY - 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
|
return shapes
|
||||||
}
|
}
|
||||||
|
|
@ -173,7 +174,6 @@ const determinePuzzleInfo = (w, h, targetTiles) => {
|
||||||
const tileSize = TILE_SIZE
|
const tileSize = TILE_SIZE
|
||||||
const width = tilesX * tileSize
|
const width = tilesX * tileSize
|
||||||
const height = tilesY * tileSize
|
const height = tilesY * tileSize
|
||||||
const coords = buildCoords({ width, height, tileSize, tiles })
|
|
||||||
|
|
||||||
const tileMarginWidth = tileSize * .5;
|
const tileMarginWidth = tileSize * .5;
|
||||||
const tileDrawSize = Math.round(tileSize + tileMarginWidth * 2)
|
const tileDrawSize = Math.round(tileSize + tileMarginWidth * 2)
|
||||||
|
|
@ -187,21 +187,9 @@ const determinePuzzleInfo = (w, h, targetTiles) => {
|
||||||
tiles,
|
tiles,
|
||||||
tilesX,
|
tilesX,
|
||||||
tilesY,
|
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 {
|
export {
|
||||||
createPuzzle,
|
createPuzzle,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,12 @@ app.use('/uploads/', express.static('./../data/uploads/'))
|
||||||
app.use('/', async (req, res, next) => {
|
app.use('/', async (req, res, next) => {
|
||||||
if (req.path === '/') {
|
if (req.path === '/') {
|
||||||
const games = [
|
const games = [
|
||||||
...Object.keys(Game.getAllGames()).map(id => ({
|
...Game.getAllGames().map(game => ({
|
||||||
id: id,
|
id: game.id,
|
||||||
title: 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)
|
const game = Game.get(gameId)
|
||||||
notify(
|
notify(
|
||||||
[Protocol.EV_SERVER_INIT, {
|
[Protocol.EV_SERVER_INIT, {
|
||||||
|
id: game.id,
|
||||||
puzzle: game.puzzle,
|
puzzle: game.puzzle,
|
||||||
players: game.players,
|
players: game.players,
|
||||||
|
sockets: [],
|
||||||
evtInfos: game.evtInfos,
|
evtInfos: game.evtInfos,
|
||||||
}],
|
}],
|
||||||
[socket]
|
[socket]
|
||||||
|
|
@ -143,8 +148,10 @@ wss.on('message', async ({socket, data}) => {
|
||||||
const game = Game.get(gameId)
|
const game = Game.get(gameId)
|
||||||
notify(
|
notify(
|
||||||
[Protocol.EV_SERVER_INIT, {
|
[Protocol.EV_SERVER_INIT, {
|
||||||
|
id: game.id,
|
||||||
puzzle: game.puzzle,
|
puzzle: game.puzzle,
|
||||||
players: game.players,
|
players: game.players,
|
||||||
|
sockets: [],
|
||||||
evtInfos: game.evtInfos,
|
evtInfos: game.evtInfos,
|
||||||
}],
|
}],
|
||||||
[socket]
|
[socket]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue