some more moving code around

This commit is contained in:
Zutatensuppe 2020-11-09 01:54:05 +01:00
parent d4ddf91259
commit 73872ebb6f
3 changed files with 564 additions and 535 deletions

49
game/Communication.js Normal file
View file

@ -0,0 +1,49 @@
import WsClient from './WsClient.js'
let conn
let changesCallback = () => {}
function onChanges(callback) {
changesCallback = callback
}
function connect(gameId, playerId) {
conn = new WsClient(WS_ADDRESS, playerId + '|' + gameId)
return new Promise(r => {
conn.connect()
conn.send(JSON.stringify({ type: 'init' }))
conn.onSocket('message', async ({ data }) => {
const d = JSON.parse(data)
if (d.type === 'init') {
r(d.game)
} else if (d.type === 'state_changed' && d.origin !== playerId) {
changesCallback(d.changes)
}
})
})
}
const _STATE = {
changed: false,
changes: [],
}
function addChange(change) {
_STATE.changes.push(change)
_STATE.changed = true
}
function sendChanges() {
if (_STATE.changed) {
conn.send(JSON.stringify({ type: 'state', state: _STATE }))
_STATE.changes = []
_STATE.changed = false
}
}
export default {
connect,
onChanges,
addChange,
sendChanges,
}

21
game/Debug.js Normal file
View file

@ -0,0 +1,21 @@
let _pt = 0
let _mindiff = 0
const checkpoint_start = (mindiff) => {
_pt = performance.now()
_mindiff = mindiff
}
const checkpoint = (label) => {
const now = performance.now();
const diff = now - _pt
if (diff > _mindiff) {
console.log(label + ': ' + (diff));
}
_pt = now;
}
export default {
checkpoint_start,
checkpoint,
}

View file

@ -7,9 +7,13 @@ import Camera from './Camera.js'
import EventAdapter from './EventAdapter.js' import EventAdapter from './EventAdapter.js'
import WsClient from './WsClient.js' import WsClient from './WsClient.js'
import Graphics from './Graphics.js' import Graphics from './Graphics.js'
import Debug from './Debug.js'
import Communication from './Communication.js'
if (!GAME_ID) throw '[ GAME_ID not set ]' if (typeof GAME_ID === 'undefined') throw '[ GAME_ID not set ]'
if (!WS_ADDRESS) throw '[ WS_ADDRESS not set ]' if (typeof WS_ADDRESS === 'undefined') throw '[ WS_ADDRESS not set ]'
if (typeof DEBUG === 'undefined') window.DEBUG = false
function addCanvasToDom(canvas) { function addCanvasToDom(canvas) {
document.body.append(canvas) document.body.append(canvas)
@ -178,6 +182,33 @@ const unfinishedTileByPos = (puzzle, pos) => {
return tileIdx return tileIdx
} }
class DirtyRect {
constructor() {
this.reset()
}
get () {
return this.x0 === null ? null : [
{x0: this.x0, x1: this.x1, y0: this.y0, y1: this.y1}
]
}
add (pos, offset) {
const x0 = pos.x - offset
const x1 = pos.x + offset
const y0 = pos.y - offset
const y1 = pos.y + offset
this.x0 = this.x0 === null ? x0 : Math.min(this.x0, x0)
this.x1 = this.x1 === null ? x1 : Math.max(this.x1, x1)
this.y0 = this.y0 === null ? y0 : Math.min(this.y0, y0)
this.y1 = this.y1 === null ? y1 : Math.max(this.y1, y1)
}
reset () {
this.x0 = null
this.x1 = null
this.y0 = null
this.y1 = null
}
}
async function loadPuzzleBitmaps(puzzle) { async function loadPuzzleBitmaps(puzzle) {
// load bitmap, to determine the original size of the image // load bitmap, to determine the original size of the image
const bmp = await Graphics.loadImageToBitmap(puzzle.info.imageUrl) const bmp = await Graphics.loadImageToBitmap(puzzle.info.imageUrl)
@ -203,12 +234,6 @@ function initme() {
return ID return ID
} }
function setupNetwork(me) {
const wsc = new WsClient(WS_ADDRESS, me)
wsc.connect()
return wsc
}
async function main () { async function main () {
let gameId = GAME_ID let gameId = GAME_ID
let me = initme() let me = initme()
@ -216,58 +241,16 @@ async function main () {
let cursorGrab = await Graphics.loadImageToBitmap('/grab.png') let cursorGrab = await Graphics.loadImageToBitmap('/grab.png')
let cursorHand = await Graphics.loadImageToBitmap('/hand.png') let cursorHand = await Graphics.loadImageToBitmap('/hand.png')
let conn = setupNetwork(me + '|' + gameId) const game = await Communication.connect(gameId, me)
conn.send(JSON.stringify({ type: 'init' }))
conn.onSocket('message', async ({data}) => {
const d = JSON.parse(data)
if (d.type === 'init') {
console.log('the game ', d.game)
let bitmaps = await loadPuzzleBitmaps(d.game.puzzle)
startGame(d.game, bitmaps, conn)
} else {
// console.log(d)
}
})
const _STATE = { const bitmaps = await loadPuzzleBitmaps(game.puzzle)
changes: [], const puzzle = game.puzzle
} const players = game.players
let _STATE_CHANGED = false
class renderRect {
constructor() {
this.reset()
}
get () {
return this.x0 === null ? null : [
{x0: this.x0, x1: this.x1, y0: this.y0, y1: this.y1}
]
}
add (pos, offset) {
const x0 = pos.x - offset
const x1 = pos.x + offset
const y0 = pos.y - offset
const y1 = pos.y + offset
this.x0 = this.x0 === null ? x0 : Math.min(this.x0, x0)
this.x1 = this.x1 === null ? x1 : Math.max(this.x1, x1)
this.y0 = this.y0 === null ? y0 : Math.min(this.y0, y0)
this.y1 = this.y1 === null ? y1 : Math.max(this.y1, y1)
}
reset () {
this.x0 = null
this.x1 = null
this.y0 = null
this.y1 = null
}
}
const startGame = (game, bitmaps, conn) => {
let puzzle = game.puzzle
let players = game.players
// information for next render cycle // information for next render cycle
let rectPlayer = new renderRect() let rectPlayer = new DirtyRect()
let rerenderPlayer = true let rerenderPlayer = true
let rectTable = new renderRect() let rectTable = new DirtyRect()
let rerenderTable = true let rerenderTable = true
let rerender = true let rerender = true
@ -275,23 +258,19 @@ async function main () {
for (let k of Object.keys(change)) { for (let k of Object.keys(change)) {
players[me][k] = change[k] players[me][k] = change[k]
} }
_STATE.changes.push({type: 'change_player', player: players[me]}) Communication.addChange({type: 'change_player', player: players[me]})
_STATE_CHANGED = true
} }
const changeData = (change) => { const changeData = (change) => {
for (let k of Object.keys(change)) { for (let k of Object.keys(change)) {
puzzle.data[k] = change[k] puzzle.data[k] = change[k]
} }
_STATE.changes.push({type: 'change_data', data: puzzle.data}) Communication.addChange({type: 'change_data', data: puzzle.data})
_STATE_CHANGED = true
} }
const changeTile = (t, change) => { const changeTile = (t, change) => {
for (let k of Object.keys(change)) { for (let k of Object.keys(change)) {
t[k] = change[k] t[k] = change[k]
} }
_STATE.changes.push({type: 'change_tile', tile: t}) Communication.addChange({type: 'change_tile', tile: t})
_STATE_CHANGED = true
} }
// 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
@ -303,10 +282,8 @@ async function main () {
// this global data will change according to input events // this global data will change according to input events
const viewport = new Camera(canvas) const viewport = new Camera(canvas)
conn.onSocket('message', ({data}) => { Communication.onChanges((changes) => {
const d = JSON.parse(data) for (let change of changes) {
if (d.type === 'state_changed' && d.origin !== me) {
for (let change of d.changes) {
switch (change.type) { switch (change.type) {
case 'change_player': { case 'change_player': {
if (players[change.player.id]) { if (players[change.player.id]) {
@ -330,7 +307,6 @@ async function main () {
} break; } break;
} }
} }
}
}) })
// Information about what tile is the player currently grabbing // Information about what tile is the player currently grabbing
@ -509,11 +485,11 @@ async function main () {
} }
if (grabbingTileIdx >= 0) { if (grabbingTileIdx >= 0) {
let tp_last = viewport.viewportToWorld({ x: last_x, y: last_y }) const tp_last = viewport.viewportToWorld({ x: last_x, y: last_y })
const diffX = tp.x - tp_last.x const diffX = tp.x - tp_last.x
const diffY = tp.y - tp_last.y const diffY = tp.y - tp_last.y
let t = puzzle.tiles[grabbingTileIdx] const t = puzzle.tiles[grabbingTileIdx]
moveGroupedTilesDiff(t, diffX, diffY) moveGroupedTilesDiff(t, diffX, diffY)
// todo: dont +- tileDrawSize, we can work with less? // todo: dont +- tileDrawSize, we can work with less?
@ -544,7 +520,6 @@ async function main () {
setGroupedZIndex(puzzle.tiles[grabbingTileIdx], puzzle.data.maxZ) setGroupedZIndex(puzzle.tiles[grabbingTileIdx], puzzle.data.maxZ)
setGroupedOwner(puzzle.tiles[grabbingTileIdx], me) setGroupedOwner(puzzle.tiles[grabbingTileIdx], me)
} }
console.log('down', tp)
} else if (mouse.type === 'up') { } else if (mouse.type === 'up') {
changePlayer({ down: false }) changePlayer({ down: false })
@ -568,7 +543,6 @@ async function main () {
let srcRect = srcRectByIdx(puzzle.info, grabbingTileIdx) let srcRect = srcRectByIdx(puzzle.info, grabbingTileIdx)
if (srcRect.centerDistance(dst) < puzzle.info.snapDistance) { if (srcRect.centerDistance(dst) < puzzle.info.snapDistance) {
// Snap the tile to the final destination // Snap the tile to the final destination
console.log('ok! !!!')
moveGroupedTiles(tile, { moveGroupedTiles(tile, {
x: srcRect.x0 + boardPos.x, x: srcRect.x0 + boardPos.x,
y: srcRect.y0 + boardPos.y, y: srcRect.y0 + boardPos.y,
@ -610,7 +584,6 @@ async function main () {
} }
} }
grabbingTileIdx = -1 grabbingTileIdx = -1
console.log('up', tp)
} else if (mouse.type === 'wheel') { } else if (mouse.type === 'wheel') {
if ( if (
mouse.deltaY < 0 && viewport.zoomIn() mouse.deltaY < 0 && viewport.zoomIn()
@ -634,31 +607,7 @@ async function main () {
rerenderPlayer = true rerenderPlayer = true
} }
if (_STATE_CHANGED) { Communication.sendChanges()
conn.send(JSON.stringify({
type: 'state',
state: _STATE,
}))
_STATE.changes = []
_STATE_CHANGED = false
}
}
// helper for measuring performance
let _pt = 0
let _mindiff = 0
const checkpoint_start = (mindiff) => {
_pt = performance.now()
_mindiff = mindiff
}
const checkpoint = (n) => {
const now = performance.now();
const diff = now - _pt
if (diff > _mindiff) {
console.log(n + ': ' + (diff));
}
_pt = now;
} }
// TODO: // TODO:
@ -676,13 +625,14 @@ async function main () {
return return
} }
checkpoint_start(20) if (DEBUG) Debug.checkpoint_start(20)
// draw the puzzle table // draw the puzzle table
if (rerenderTable) { if (rerenderTable) {
Graphics.fillBitmapCapped(puzzleTable, puzzleTableColor, rectTable.get()) Graphics.fillBitmapCapped(puzzleTable, puzzleTableColor, rectTable.get())
checkpoint('after fill')
if (DEBUG) Debug.checkpoint('after fill')
// draw the puzzle board on the table // draw the puzzle board on the table
Graphics.mapBitmapToBitmapCapped(board, board.getBoundingRect(), puzzleTable, new BoundingRectangle( Graphics.mapBitmapToBitmapCapped(board, board.getBoundingRect(), puzzleTable, new BoundingRectangle(
@ -691,7 +641,8 @@ async function main () {
boardPos.y, boardPos.y,
boardPos.y + board.height - 1, boardPos.y + board.height - 1,
), rectTable.get()) ), rectTable.get())
checkpoint('imgtoimg')
if (DEBUG) Debug.checkpoint('imgtoimg')
// draw all the tiles on the table // draw all the tiles on the table
@ -711,7 +662,8 @@ async function main () {
rectTable.get() rectTable.get()
) )
} }
checkpoint('tiles')
if (DEBUG) Debug.checkpoint('tiles')
} }
if (rerenderTable || rerender) { if (rerenderTable || rerender) {
@ -720,7 +672,8 @@ async function main () {
// camera // camera
adapter.clear() adapter.clear()
adapter.apply() adapter.apply()
checkpoint('afterclear_1')
if (DEBUG) Debug.checkpoint('afterclear_1')
// TODO: improve the rendering // TODO: improve the rendering
// atm it is pretty slow (~40-50ms) // atm it is pretty slow (~40-50ms)
@ -730,10 +683,14 @@ async function main () {
adapter, adapter,
adapter.getBoundingRect() adapter.getBoundingRect()
) )
checkpoint('to_adapter_1')
if (DEBUG) Debug.checkpoint('to_adapter_1')
} else if (rerenderPlayer) { } else if (rerenderPlayer) {
adapter.clearRect(rectPlayer.get()) adapter.clearRect(rectPlayer.get())
checkpoint('afterclear_2')
if (DEBUG) Debug.checkpoint('afterclear_2')
Graphics.mapBitmapToAdapterCapped( Graphics.mapBitmapToAdapterCapped(
puzzleTable, puzzleTable,
viewport.rect(), viewport.rect(),
@ -741,7 +698,8 @@ async function main () {
adapter.getBoundingRect(), adapter.getBoundingRect(),
rectPlayer.get() rectPlayer.get()
) )
checkpoint('to_adapter_2')
if (DEBUG) Debug.checkpoint('to_adapter_2')
} }
if (rerenderPlayer) { if (rerenderPlayer) {
@ -761,11 +719,13 @@ async function main () {
) )
) )
} }
checkpoint('after_players')
if (DEBUG) Debug.checkpoint('after_players')
} }
adapter.apply() adapter.apply()
checkpoint('finals')
if (DEBUG) Debug.checkpoint('finals')
rerenderTable = false rerenderTable = false
rerenderPlayer = false rerenderPlayer = false
@ -778,7 +738,6 @@ async function main () {
update: onUpdate, update: onUpdate,
render: onRender, render: onRender,
}) })
}
} }
main() main()