some improvements :D

This commit is contained in:
Zutatensuppe 2020-11-07 16:33:28 +01:00
parent 426c8578e5
commit 61837a155f
3 changed files with 180 additions and 176 deletions

View file

@ -56,7 +56,6 @@ export default class WsClient extends WsWrapper {
return
}
console.log(`ws dispatch ${type} ${tag}`)
for (const callback of callbacks) {
callback(...args)
}

View file

@ -252,25 +252,19 @@ function getSurroundingTilesByIdx(puzzle, idx) {
]
}
function determinePuzzleTileShapes (tiles, info) {
var tabs = [-1, 1]
for (let IDX in tiles) {
var _X = info.coords[IDX].x
var _Y = info.coords[IDX].y
function determinePuzzleTileShapes (info) {
const tabs = [-1, 1]
var topTab = _Y === 0 ? 0 : tiles[IDX - info.tiles_x].tabs.bottom * -1;
var rightTab = _X === info.tiles_x -1 ? 0 : choice(tabs)
var leftTab = _X === 0 ? 0 : tiles[IDX - 1].tabs.right * -1
var bottomTab = _Y === info.tiles_y -1 ? 0 : choice(tabs)
tiles[IDX].tabs = {
top: topTab,
right: rightTab,
left: leftTab,
bottom: bottomTab,
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.tiles_x].bottom * -1,
right: info.coords[i].x === info.tiles_x -1 ? 0 : choice(tabs),
left: info.coords[i].x === 0 ? 0 : shapes[i - 1].right * -1,
bottom: info.coords[i].y === info.tiles_y -1 ? 0 : choice(tabs),
}
}
return tiles
return shapes
}
async function createPuzzleTileBitmaps (bitmap, tiles, info) {
@ -296,10 +290,10 @@ async function createPuzzleTileBitmaps (bitmap, tiles, info) {
let ctx = c.getContext('2d')
ctx.clearRect(0, 0,tileDrawSize, tileDrawSize)
var topTab = tile.tabs.top
var rightTab = tile.tabs.right
var leftTab = tile.tabs.left
var bottomTab = tile.tabs.bottom
var topTab = info.shapes[tile.idx].top
var rightTab = info.shapes[tile.idx].right
var leftTab = info.shapes[tile.idx].left
var bottomTab = info.shapes[tile.idx].bottom
var topLeftEdge = new Point(tileMarginWidth, tileMarginWidth);
ctx.save();
@ -436,7 +430,7 @@ const unfinishedTileByPos = (puzzle, pos) => {
let tileIdx = -1
for (let idx = 0; idx < puzzle.tiles.length; idx++) {
let tile = puzzle.tiles[idx]
if (tile.finished) {
if (tile.owner === -1) {
continue
}
@ -470,7 +464,7 @@ async function loadPuzzleBitmaps(puzzle) {
return bitmaps
}
async function loadPuzzle(targetTiles, imageUrl) {
async function createPuzzle(targetTiles, imageUrl) {
// load bitmap, to determine the original size of the image
let bitmpTmp = await loadImageToBitmap(imageUrl)
@ -483,7 +477,7 @@ async function loadPuzzle(targetTiles, imageUrl) {
idx: i,
}
}
tiles = await determinePuzzleTileShapes(tiles, info)
const shapes = determinePuzzleTileShapes(info)
// Complete puzzle object
const p = {
@ -493,8 +487,10 @@ async function loadPuzzle(targetTiles, imageUrl) {
idx: tile.idx, // index of tile in the array
group: 0, // if grouped with other tiles
z: 0, // z index of the tile
finished: false, // if the tile is in its final position
tabs: tile.tabs, // tabs :)
owner: 0, // who owns the tile
// 0 = free for taking
// -1 = finished
// other values: id of player who has the tile
// physical current position of the tile (x/y in pixels)
// this position is the initial position only and is the
// value that changes when moving a tile
@ -505,7 +501,14 @@ async function loadPuzzle(targetTiles, imageUrl) {
},
}
}),
// extra puzzle information
// game data for puzzle, data changes during the game
data: {
// TODO: maybe calculate this each time?
maxZ: 0, // max z of all pieces
maxGroup: 0, // max group of all pieces
},
// static puzzle information. stays same for complete duration of
// the game
info: {
// information that was used to create the puzzle
targetTiles: targetTiles,
@ -530,6 +533,7 @@ async function loadPuzzle(targetTiles, imageUrl) {
// the tile_coordinate
// this can be used to determine where the
// final destination of a tile is
shapes: shapes, // tile shapes
},
}
return p
@ -561,13 +565,13 @@ async function main () {
// todo: maybe put in protocols, same as `me()`
let gameId = 'asdfbla' // uniqId()
let me = initme()
const player = {x: 0, y: 0, down: false}
let conn = setupNetwork(me + '|' + gameId)
conn.send(JSON.stringify({type: 'init'}))
conn.send(JSON.stringify({type: 'init', player}))
conn.onSocket('message', async ({data}) => {
const d = JSON.parse(data)
let puzzle
console.log(d)
if (d.type === 'init') {
if (d.puzzle) {
puzzle = d.puzzle
@ -576,26 +580,25 @@ async function main () {
// The game doesnt exist yet on the server, so load puzzle
// and then give the server some info about the puzzle
// Load puzzle and determine information about it
console.log(puzzle)
puzzle = await loadPuzzle(TARGET_TILES, IMAGE_URL)
// TODO: move puzzle creation to server
puzzle = await createPuzzle(TARGET_TILES, IMAGE_URL)
conn.send(JSON.stringify({
type: 'init_puzzle',
puzzle: puzzle,
}))
console.log('loaded from local config')
}
console.log(puzzle)
console.log('the puzzle ', puzzle)
let bitmaps = await loadPuzzleBitmaps(puzzle)
startGame(puzzle, bitmaps, conn)
} else {
console.log(d)
// console.log(d)
}
})
const _STATE = {
m_x: 0,
m_y: 0,
m_d: false,
changes: [],
}
let _STATE_CHANGED = false
@ -623,20 +626,46 @@ async function main () {
conn.onSocket('message', ({data}) => {
const d = JSON.parse(data)
if (d.type === 'tile_changed' && d.origin !== me) {
updateDrawMinMax(puzzle.tiles[d.idx].pos, puzzle.info.tileDrawSize)
if (d.type === 'state_changed' && d.origin !== me) {
for (let change of d.changes) {
switch (change.type) {
case 'change_tile': {
updateDrawMinMax(puzzle.tiles[change.tile.idx].pos, puzzle.info.tileDrawSize)
puzzle.tiles[d.idx].pos = {x: d.pos.x, y: d.pos.y}
puzzle.tiles[d.idx].z = d.z
puzzle.tiles[d.idx].group = d.group
puzzle.tiles[d.idx].finished = d.finished
puzzle.tiles[change.tile.idx] = change.tile
updateDrawMinMax(puzzle.tiles[d.idx].pos, puzzle.info.tileDrawSize)
updateDrawMinMax(puzzle.tiles[change.tile.idx].pos, puzzle.info.tileDrawSize)
} break;
case 'change_data': {
puzzle.data = change.data
} break;
}
}
}
})
console.log(puzzle)
const changePlayer = (change) => {
for (let k of Object.keys(change)) {
player[k] = change[k]
}
_STATE.changes.push({type: 'change_player', player: player})
_STATE_CHANGED = true
}
const changeData = (change) => {
for (let k of Object.keys(change)) {
puzzle.data[k] = change[k]
}
_STATE.changes.push({type: 'change_data', data: puzzle.data})
_STATE_CHANGED = true
}
const changeTile = (t, change) => {
for (let k of Object.keys(change)) {
t[k] = change[k]
}
_STATE.changes.push({type: 'change_tile', tile: t})
_STATE_CHANGED = true
}
// Create a dom and attach adapters to it so we can work with it
const canvas = addCanvasToDom(createCanvas())
@ -656,9 +685,6 @@ async function main () {
// Information about what tile is the player currently grabbing
let grabbingTileIdx = -1
let maxZ = 0
let maxGroup = 0
// The actual place for the puzzle. The tiles may
// not be moved around infinitely, just on the (invisible)
// puzzle table. however, the camera may move away from the table
@ -716,16 +742,17 @@ async function main () {
} else if (other.group) {
targetGroup = other.group
} else {
maxGroup++
targetGroup = maxGroup
changeData({ maxGroup: puzzle.data.maxGroup + 1 })
targetGroup = puzzle.data.maxGroup
}
tile.group = targetGroup
other.group = targetGroup
changeTile(tile, { group: targetGroup })
changeTile(other, { group: targetGroup })
if (searchGroups.length > 0) {
for (let tmp of puzzle.tiles) {
if (searchGroups.includes(tmp.group)) {
tmp.group = targetGroup
changeTile(tmp, { group: targetGroup })
}
}
}
@ -764,30 +791,23 @@ async function main () {
const setGroupedZIndex = (tile, zIndex) => {
for (let t of getGroupedTiles(tile)) {
t.z = zIndex
changeTile(t, { z: zIndex })
}
}
conn.send(JSON.stringify({
type: 'change_tile',
idx: t.idx,
pos: t.pos,
z: t.z,
group: t.group,
finished: t.finished,
}))
const setGroupedOwner = (tile, owner) => {
for (let t of getGroupedTiles(tile)) {
// may only change own tiles or untaken tiles
if (t.owner === me || t.owner === 0) {
changeTile(t, { owner: owner })
}
}
}
const moveGroupedTilesDiff = (tile, diffX, diffY) => {
for (let t of getGroupedTiles(tile)) {
t.pos = pointAdd(t.pos, {x: diffX, y: diffY})
changeTile(t, { pos: pointAdd(t.pos, { x: diffX, y: diffY }) })
conn.send(JSON.stringify({
type: 'change_tile',
idx: t.idx,
pos: t.pos,
z: t.z,
finished: t.finished,
}))
// TODO: instead there could be a function to
// get min/max x/y of a group
updateDrawMinMax(tileCenterPos(t), puzzle.info.tileDrawSize)
@ -799,15 +819,7 @@ async function main () {
}
const finishGroupedTiles = (tile) => {
for (let t of getGroupedTiles(tile)) {
t.finished = true
t.z = 1
conn.send(JSON.stringify({
type: 'change_tile',
idx: t.idx,
pos: t.pos,
z: t.z,
finished: t.finished,
}))
changeTile(t, {owner: -1, z: 1})
}
}
// ---------------------------------------------------------------
@ -831,16 +843,12 @@ async function main () {
for (let mouse of evts.consumeAll()) {
if (mouse.type === 'move') {
const tp = cam.translateMouse(mouse)
_STATE.m_x = tp.x
_STATE.m_y = tp.y
_STATE_CHANGED = true
changePlayer({x: tp.x, y: tp.y})
}
if (mouse.type === 'down') {
_STATE.m_d = true
_STATE_CHANGED = true
changePlayer({down: true})
} else if (mouse.type === 'up') {
_STATE.m_d = false
_STATE_CHANGED = true
changePlayer({down: false})
}
if (mouse.type === 'wheel') {
if (mouse.y < 0) {
@ -864,8 +872,9 @@ async function main () {
grabbingTileIdx = unfinishedTileByPos(puzzle, tp)
console.log(grabbingTileIdx)
if (grabbingTileIdx >= 0) {
maxZ++
setGroupedZIndex(puzzle.tiles[grabbingTileIdx], maxZ)
changeData({maxZ: puzzle.data.maxZ + 1})
setGroupedZIndex(puzzle.tiles[grabbingTileIdx], puzzle.data.maxZ)
setGroupedOwner(puzzle.tiles[grabbingTileIdx], me)
}
console.log('down', tp)
@ -880,6 +889,7 @@ async function main () {
// location
let tile = puzzle.tiles[grabbingTileIdx]
setGroupedOwner(tile, 0)
let pt = pointSub(tile.pos, boardPos)
let dst = tileRectByPos(pt)
let srcRect = srcRectByIdx(puzzle.info, grabbingTileIdx)
@ -907,7 +917,7 @@ async function main () {
]
const check = (t, off, other) => {
if (snapped || !other || other.finished || areGrouped(t, other)) {
if (snapped || !other || (other.owner === -1) || areGrouped(t, other)) {
return
}
let trec_ = tileRectByTile(t)
@ -1003,6 +1013,7 @@ async function main () {
type: 'state',
state: _STATE,
}))
_STATE.changes = []
_STATE_CHANGED = false
}
}

View file

@ -26,8 +26,6 @@ app.use('/', (req, res, next) => {
})
app.listen(port, hostname, () => console.log(`server running on http://${hostname}:${port}`))
const players = {}
const games = {}
const wss = new WebSocketServer(config.ws);
@ -47,42 +45,38 @@ wss.on('message', ({socket, data}) => {
switch (parsed.type) {
case 'init': {
// a new player (or previous player) joined
players[uid] = players[uid] || {}
players[uid].id = uid
players[uid].tiles = players[uid].tiles || 0
players[uid].m_x = players[uid].x || null
players[uid].m_y = players[uid].y || null
players[uid].m_d = false
console.log('init', players)
const puzzle = games[gid] ? games[gid].puzzle : null
console.log('init', games[gid])
wss.notifyOne({type: 'init', puzzle: puzzle}, socket)
games[gid] = games[gid] || {puzzle: null, players: {}}
games[gid].players[uid] = parsed.player
wss.notifyOne({
type: 'init',
puzzle: games[gid].puzzle,
players: games[gid].players,
}, socket)
} break;
// new puzzle was created and sent to us
case 'init_puzzle': {
games[gid] = {
puzzle: parsed.puzzle,
}
games[gid].puzzle = parsed.puzzle
} break;
// somebody has changed the state
case 'state': {
players[uid].m_x = parsed.state.m_x
players[uid].m_y = parsed.state.m_y
players[uid].m_d = parsed.state.m_d
for (let change of parsed.state.changes) {
switch (change.type) {
case 'change_player': {
games[gid].players[uid] = change.player
} break;
case 'change_tile': {
let idx = parsed.idx
let z = parsed.z
let finished = parsed.finished
let pos = { x: parsed.pos.x, y: parsed.pos.y }
let group = parsed.group
// games[gid].puzzle.tiles[idx] = games[gid].puzzle.tiles[idx] || {}
games[gid].puzzle.tiles[idx].pos = pos
games[gid].puzzle.tiles[idx].z = z
games[gid].puzzle.tiles[idx].finished = finished
games[gid].puzzle.tiles[idx].group = group
notify({type:'tile_changed', origin: uid, idx, pos, z, finished, group})
games[gid].puzzle.tiles[change.tile.idx] = change.tile
} break;
case 'change_data': {
games[gid].puzzle.data = change.data
} break;
}
}
notify({type:'state_changed', origin: uid, changes: parsed.state.changes})
} break;
}
} catch (e) {