some more type hinting etc
This commit is contained in:
parent
432e1b6668
commit
ee7804a594
18 changed files with 161 additions and 150 deletions
|
|
@ -1,16 +1,12 @@
|
|||
import Geometry from './Geometry'
|
||||
import Geometry, { Point, Rect } from './Geometry'
|
||||
import Protocol from './Protocol'
|
||||
import { Rng } from './Rng'
|
||||
import Time from './Time'
|
||||
import Util from './Util'
|
||||
|
||||
interface EncodedPlayer extends Array<any> {}
|
||||
interface EncodedPiece extends Array<any> {}
|
||||
|
||||
interface Point {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
export type EncodedPlayer = Array<any>
|
||||
export type EncodedPiece = Array<any>
|
||||
export type EncodedPieceShape = number
|
||||
|
||||
interface GameRng {
|
||||
obj: Rng
|
||||
|
|
@ -22,7 +18,7 @@ interface Game {
|
|||
players: Array<EncodedPlayer>
|
||||
puzzle: Puzzle
|
||||
evtInfos: Record<string, EvtInfo>
|
||||
scoreMode?: number
|
||||
scoreMode?: ScoreMode
|
||||
rng: GameRng
|
||||
}
|
||||
|
||||
|
|
@ -44,15 +40,24 @@ interface PuzzleTable {
|
|||
height: number
|
||||
}
|
||||
|
||||
enum PieceEdge {
|
||||
Flat = 0,
|
||||
Out = 1,
|
||||
In = -1,
|
||||
}
|
||||
export interface PieceShape {
|
||||
top: 0|1|-1
|
||||
bottom: 0|1|-1
|
||||
left: 0|1|-1
|
||||
right: 0|1|-1
|
||||
top: PieceEdge
|
||||
bottom: PieceEdge
|
||||
left: PieceEdge
|
||||
right: PieceEdge
|
||||
}
|
||||
|
||||
export interface Piece {
|
||||
owner: string|number
|
||||
idx: number
|
||||
pos: Point
|
||||
z: number
|
||||
group: number
|
||||
}
|
||||
|
||||
export interface PuzzleInfo {
|
||||
|
|
@ -72,8 +77,7 @@ export interface PuzzleInfo {
|
|||
tilesX: number
|
||||
tilesY: number
|
||||
|
||||
// TODO: ts type Array<PieceShape>
|
||||
shapes: Array<any>
|
||||
shapes: Array<EncodedPieceShape>
|
||||
}
|
||||
|
||||
export interface Player {
|
||||
|
|
@ -93,8 +97,10 @@ interface EvtInfo {
|
|||
_last_mouse_down: Point|null
|
||||
}
|
||||
|
||||
const SCORE_MODE_FINAL = 0
|
||||
const SCORE_MODE_ANY = 1
|
||||
export enum ScoreMode {
|
||||
FINAL = 0,
|
||||
ANY = 1,
|
||||
}
|
||||
|
||||
const IDLE_TIMEOUT_SEC = 30
|
||||
|
||||
|
|
@ -134,20 +140,20 @@ function getPlayerIndexById(gameId: string, playerId: string): number {
|
|||
return -1
|
||||
}
|
||||
|
||||
function getPlayerIdByIndex(gameId: string, playerIndex: number) {
|
||||
function getPlayerIdByIndex(gameId: string, playerIndex: number): string|null {
|
||||
if (GAMES[gameId].players.length > playerIndex) {
|
||||
return Util.decodePlayer(GAMES[gameId].players[playerIndex]).id
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function getPlayer(gameId: string, playerId: string) {
|
||||
let idx = getPlayerIndexById(gameId, playerId)
|
||||
function getPlayer(gameId: string, playerId: string): Player {
|
||||
const idx = getPlayerIndexById(gameId, playerId)
|
||||
return Util.decodePlayer(GAMES[gameId].players[idx])
|
||||
}
|
||||
|
||||
function setPlayer(gameId: string, playerId: string, player: Player) {
|
||||
let idx = getPlayerIndexById(gameId, playerId)
|
||||
const idx = getPlayerIndexById(gameId, playerId)
|
||||
if (idx === -1) {
|
||||
GAMES[gameId].players.push(Util.encodePlayer(player))
|
||||
} else {
|
||||
|
|
@ -168,17 +174,17 @@ function playerExists(gameId: string, playerId: string) {
|
|||
return idx !== -1
|
||||
}
|
||||
|
||||
function getActivePlayers(gameId: string, ts: number) {
|
||||
function getActivePlayers(gameId: string, ts: number): Array<Player> {
|
||||
const minTs = ts - IDLE_TIMEOUT_SEC * Time.SEC
|
||||
return getAllPlayers(gameId).filter((p: Player) => p.ts >= minTs)
|
||||
}
|
||||
|
||||
function getIdlePlayers(gameId: string, ts: number) {
|
||||
function getIdlePlayers(gameId: string, ts: number): Array<Player> {
|
||||
const minTs = ts - IDLE_TIMEOUT_SEC * Time.SEC
|
||||
return getAllPlayers(gameId).filter((p: Player) => p.ts < minTs && p.points > 0)
|
||||
}
|
||||
|
||||
function addPlayer(gameId: string, playerId: string, ts: number) {
|
||||
function addPlayer(gameId: string, playerId: string, ts: number): void {
|
||||
if (!playerExists(gameId, playerId)) {
|
||||
setPlayer(gameId, playerId, __createPlayerObject(playerId, ts))
|
||||
} else {
|
||||
|
|
@ -186,7 +192,7 @@ function addPlayer(gameId: string, playerId: string, ts: number) {
|
|||
}
|
||||
}
|
||||
|
||||
function getEvtInfo(gameId: string, playerId: string) {
|
||||
function getEvtInfo(gameId: string, playerId: string): EvtInfo {
|
||||
if (playerId in GAMES[gameId].evtInfos) {
|
||||
return GAMES[gameId].evtInfos[playerId]
|
||||
}
|
||||
|
|
@ -211,7 +217,7 @@ function getAllGames(): Array<Game> {
|
|||
})
|
||||
}
|
||||
|
||||
function getAllPlayers(gameId: string) {
|
||||
function getAllPlayers(gameId: string): Array<Player> {
|
||||
return GAMES[gameId]
|
||||
? GAMES[gameId].players.map(Util.decodePlayer)
|
||||
: []
|
||||
|
|
@ -221,11 +227,11 @@ function get(gameId: string) {
|
|||
return GAMES[gameId]
|
||||
}
|
||||
|
||||
function getTileCount(gameId: string) {
|
||||
function getTileCount(gameId: string): number {
|
||||
return GAMES[gameId].puzzle.tiles.length
|
||||
}
|
||||
|
||||
function getImageUrl(gameId: string) {
|
||||
function getImageUrl(gameId: string): string {
|
||||
return GAMES[gameId].puzzle.info.imageUrl
|
||||
}
|
||||
|
||||
|
|
@ -233,8 +239,8 @@ function setImageUrl(gameId: string, imageUrl: string) {
|
|||
GAMES[gameId].puzzle.info.imageUrl = imageUrl
|
||||
}
|
||||
|
||||
function getScoreMode(gameId: string) {
|
||||
return GAMES[gameId].scoreMode || SCORE_MODE_FINAL
|
||||
function getScoreMode(gameId: string): ScoreMode {
|
||||
return GAMES[gameId].scoreMode || ScoreMode.FINAL
|
||||
}
|
||||
|
||||
function isFinished(gameId: string) {
|
||||
|
|
@ -259,6 +265,7 @@ function getTilesSortedByZIndex(gameId: string) {
|
|||
function changePlayer(gameId: string, playerId: string, change: any) {
|
||||
const player = getPlayer(gameId, playerId)
|
||||
for (let k of Object.keys(change)) {
|
||||
// @ts-ignore
|
||||
player[k] = change[k]
|
||||
}
|
||||
setPlayer(gameId, playerId, player)
|
||||
|
|
@ -274,12 +281,13 @@ function changeData(gameId: string, change: any) {
|
|||
function changeTile(gameId: string, tileIdx: number, change: any) {
|
||||
for (let k of Object.keys(change)) {
|
||||
const tile = Util.decodeTile(GAMES[gameId].puzzle.tiles[tileIdx])
|
||||
// @ts-ignore
|
||||
tile[k] = change[k]
|
||||
GAMES[gameId].puzzle.tiles[tileIdx] = Util.encodeTile(tile)
|
||||
}
|
||||
}
|
||||
|
||||
const getTile = (gameId: string, tileIdx: number) => {
|
||||
const getTile = (gameId: string, tileIdx: number): Piece => {
|
||||
return Util.decodeTile(GAMES[gameId].puzzle.tiles[tileIdx])
|
||||
}
|
||||
|
||||
|
|
@ -500,7 +508,7 @@ const freeTileIdxByPos = (gameId: string, pos: Point) => {
|
|||
continue
|
||||
}
|
||||
|
||||
const collisionRect = {
|
||||
const collisionRect: Rect = {
|
||||
x: tile.pos.x,
|
||||
y: tile.pos.y,
|
||||
w: info.tileSize,
|
||||
|
|
@ -531,9 +539,9 @@ const getPlayerName = (gameId: string, playerId: string) => {
|
|||
return p ? p.name : null
|
||||
}
|
||||
|
||||
const getPlayerPoints = (gameId: string, playerId: string) => {
|
||||
const getPlayerPoints = (gameId: string, playerId: string): number => {
|
||||
const p = getPlayer(gameId, playerId)
|
||||
return p ? p.points : null
|
||||
return p ? p.points : 0
|
||||
}
|
||||
|
||||
// determine if two tiles are grouped together
|
||||
|
|
@ -746,13 +754,13 @@ function handleInput(gameId: string, playerId: string, input: any, ts: number) {
|
|||
_tileChanges(tileIdxs)
|
||||
|
||||
let points = getPlayerPoints(gameId, playerId)
|
||||
if (getScoreMode(gameId) === SCORE_MODE_FINAL) {
|
||||
if (getScoreMode(gameId) === ScoreMode.FINAL) {
|
||||
points += tileIdxs.length
|
||||
} else if (getScoreMode(gameId) === SCORE_MODE_ANY) {
|
||||
} else if (getScoreMode(gameId) === ScoreMode.ANY) {
|
||||
points += 1
|
||||
} else {
|
||||
// no score mode... should never occur, because there is a
|
||||
// fallback to SCORE_MODE_FINAL in getScoreMode function
|
||||
// fallback to ScoreMode.FINAL in getScoreMode function
|
||||
}
|
||||
changePlayer(gameId, playerId, { d, ts, points })
|
||||
_playerChange()
|
||||
|
|
@ -809,7 +817,7 @@ function handleInput(gameId: string, playerId: string, input: any, ts: number) {
|
|||
break
|
||||
}
|
||||
}
|
||||
if (snapped && getScoreMode(gameId) === SCORE_MODE_ANY) {
|
||||
if (snapped && getScoreMode(gameId) === ScoreMode.ANY) {
|
||||
const points = getPlayerPoints(gameId, playerId) + 1
|
||||
changePlayer(gameId, playerId, { d, ts, points })
|
||||
_playerChange()
|
||||
|
|
@ -881,6 +889,4 @@ export default {
|
|||
getStartTs,
|
||||
getFinishTs,
|
||||
handleInput,
|
||||
SCORE_MODE_FINAL,
|
||||
SCORE_MODE_ANY,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
interface Point {
|
||||
export interface Point {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
|
||||
interface Rect {
|
||||
export interface Rect {
|
||||
x: number
|
||||
y: number
|
||||
w: number
|
||||
h: number
|
||||
}
|
||||
export interface Dim {
|
||||
w: number
|
||||
h: number
|
||||
}
|
||||
|
||||
function pointSub(a: Point, b: Point): Point {
|
||||
return { x: a.x - b.x, y: a.y - b.y }
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const MIN = SEC * 60
|
|||
const HOUR = MIN * 60
|
||||
const DAY = HOUR * 24
|
||||
|
||||
export const timestamp = () => {
|
||||
export const timestamp = (): number => {
|
||||
const d = new Date();
|
||||
return Date.UTC(
|
||||
d.getUTCFullYear(),
|
||||
|
|
@ -17,7 +17,7 @@ export const timestamp = () => {
|
|||
)
|
||||
}
|
||||
|
||||
export const durationStr = (duration: number) => {
|
||||
export const durationStr = (duration: number): string => {
|
||||
const d = Math.floor(duration / DAY)
|
||||
duration = duration % DAY
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { EncodedPiece, EncodedPieceShape, EncodedPlayer, Piece, PieceShape, Player } from './GameCommon'
|
||||
import { Point } from './Geometry'
|
||||
import { Rng } from './Rng'
|
||||
|
||||
|
||||
|
|
@ -27,10 +29,7 @@ export const logger = (...pre: Array<any>) => {
|
|||
// get a unique id
|
||||
export const uniqId = () => Date.now().toString(36) + Math.random().toString(36).substring(2)
|
||||
|
||||
function encodeShape(data: any): number {
|
||||
if (typeof data === 'number') {
|
||||
return data
|
||||
}
|
||||
function encodeShape(data: PieceShape): EncodedPieceShape {
|
||||
/* encoded in 1 byte:
|
||||
00000000
|
||||
^^ top
|
||||
|
|
@ -44,10 +43,7 @@ function encodeShape(data: any): number {
|
|||
| ((data.left + 1) << 6)
|
||||
}
|
||||
|
||||
function decodeShape(data: any) {
|
||||
if (typeof data !== 'number') {
|
||||
return data
|
||||
}
|
||||
function decodeShape(data: EncodedPieceShape): PieceShape {
|
||||
return {
|
||||
top: (data >> 0 & 0b11) - 1,
|
||||
right: (data >> 2 & 0b11) - 1,
|
||||
|
|
@ -56,17 +52,11 @@ function decodeShape(data: any) {
|
|||
}
|
||||
}
|
||||
|
||||
function encodeTile(data: any): Array<any> {
|
||||
if (Array.isArray(data)) {
|
||||
return data
|
||||
}
|
||||
function encodeTile(data: Piece): EncodedPiece {
|
||||
return [data.idx, data.pos.x, data.pos.y, data.z, data.owner, data.group]
|
||||
}
|
||||
|
||||
function decodeTile(data: any) {
|
||||
if (!Array.isArray(data)) {
|
||||
return data
|
||||
}
|
||||
function decodeTile(data: EncodedPiece): Piece {
|
||||
return {
|
||||
idx: data[0],
|
||||
pos: {
|
||||
|
|
@ -79,10 +69,7 @@ function decodeTile(data: any) {
|
|||
}
|
||||
}
|
||||
|
||||
function encodePlayer(data: any): Array<any> {
|
||||
if (Array.isArray(data)) {
|
||||
return data
|
||||
}
|
||||
function encodePlayer(data: Player): EncodedPlayer {
|
||||
return [
|
||||
data.id,
|
||||
data.x,
|
||||
|
|
@ -96,10 +83,7 @@ function encodePlayer(data: any): Array<any> {
|
|||
]
|
||||
}
|
||||
|
||||
function decodePlayer(data: any) {
|
||||
if (!Array.isArray(data)) {
|
||||
return data
|
||||
}
|
||||
function decodePlayer(data: EncodedPlayer): Player {
|
||||
return {
|
||||
id: data[0],
|
||||
x: data[1],
|
||||
|
|
@ -145,7 +129,7 @@ function decodeGame(data: any) {
|
|||
}
|
||||
}
|
||||
|
||||
function coordByTileIdx(info: any, tileIdx: number) {
|
||||
function coordByTileIdx(info: any, tileIdx: number): Point {
|
||||
const wTiles = info.width / info.tileSize
|
||||
return {
|
||||
x: tileIdx % wTiles,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,10 @@
|
|||
import { Dim, Point } from "../common/Geometry"
|
||||
|
||||
const MIN_ZOOM = .1
|
||||
const MAX_ZOOM = 6
|
||||
const ZOOM_STEP = .05
|
||||
|
||||
type ZOOM_DIR = 'in'|'out'
|
||||
interface Point {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
interface Dim {
|
||||
w: number
|
||||
h: number
|
||||
}
|
||||
|
||||
export default function Camera () {
|
||||
let x = 0
|
||||
|
|
|
|||
|
|
@ -17,15 +17,23 @@ async function loadImageToBitmap(imagePath: string): Promise<ImageBitmap> {
|
|||
})
|
||||
}
|
||||
|
||||
async function resizeBitmap (bitmap: ImageBitmap, width: number, height: number): Promise<ImageBitmap> {
|
||||
async function resizeBitmap (
|
||||
bitmap: ImageBitmap,
|
||||
width: number,
|
||||
height: number
|
||||
): Promise<ImageBitmap> {
|
||||
const c = createCanvas(width, height)
|
||||
const ctx = c.getContext('2d') as CanvasRenderingContext2D
|
||||
ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, width, height)
|
||||
return await createImageBitmap(c)
|
||||
}
|
||||
|
||||
async function colorize(image: ImageBitmap, mask: ImageBitmap, color: string): Promise<ImageBitmap> {
|
||||
const c = createCanvas(image.width, image.height)
|
||||
async function colorize(
|
||||
bitmap: ImageBitmap,
|
||||
mask: ImageBitmap,
|
||||
color: string
|
||||
): Promise<ImageBitmap> {
|
||||
const c = createCanvas(bitmap.width, bitmap.height)
|
||||
const ctx = c.getContext('2d') as CanvasRenderingContext2D
|
||||
ctx.save()
|
||||
ctx.drawImage(mask, 0, 0)
|
||||
|
|
@ -35,7 +43,7 @@ async function colorize(image: ImageBitmap, mask: ImageBitmap, color: string): P
|
|||
ctx.restore()
|
||||
ctx.save()
|
||||
ctx.globalCompositeOperation = "destination-over"
|
||||
ctx.drawImage(image, 0, 0)
|
||||
ctx.drawImage(bitmap, 0, 0)
|
||||
ctx.restore()
|
||||
return await createImageBitmap(c)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
"use strict"
|
||||
|
||||
import Geometry from '../common/Geometry'
|
||||
import Geometry, { Rect } from '../common/Geometry'
|
||||
import Graphics from './Graphics'
|
||||
import Util, { logger } from './../common/Util'
|
||||
import { Puzzle, PuzzleInfo, PieceShape } from './../common/GameCommon'
|
||||
|
||||
const log = logger('PuzzleGraphics.js')
|
||||
|
||||
async function createPuzzleTileBitmaps(img: ImageBitmap, tiles: Array<any>, info: PuzzleInfo) {
|
||||
async function createPuzzleTileBitmaps(
|
||||
img: ImageBitmap,
|
||||
tiles: Array<any>,
|
||||
info: PuzzleInfo
|
||||
): Promise<Array<ImageBitmap>> {
|
||||
log.log('start createPuzzleTileBitmaps')
|
||||
var tileSize = info.tileSize
|
||||
var tileMarginWidth = info.tileMarginWidth
|
||||
|
|
@ -23,7 +27,7 @@ async function createPuzzleTileBitmaps(img: ImageBitmap, tiles: Array<any>, info
|
|||
63, 5, 65, 15, 100, 0
|
||||
];
|
||||
|
||||
const bitmaps = new Array(tiles.length)
|
||||
const bitmaps: Array<ImageBitmap> = new Array(tiles.length)
|
||||
|
||||
const paths: Record<string, Path2D> = {}
|
||||
function pathForShape(shape: PieceShape) {
|
||||
|
|
@ -89,7 +93,7 @@ async function createPuzzleTileBitmaps(img: ImageBitmap, tiles: Array<any>, info
|
|||
const c2 = Graphics.createCanvas(tileDrawSize, tileDrawSize)
|
||||
const ctx2 = c2.getContext('2d') as CanvasRenderingContext2D
|
||||
|
||||
for (let t of tiles) {
|
||||
for (const t of tiles) {
|
||||
const tile = Util.decodeTile(t)
|
||||
const srcRect = srcRectByIdx(info, tile.idx)
|
||||
const path = pathForShape(Util.decodeShape(info.shapes[tile.idx]))
|
||||
|
|
@ -198,7 +202,7 @@ async function createPuzzleTileBitmaps(img: ImageBitmap, tiles: Array<any>, info
|
|||
return bitmaps
|
||||
}
|
||||
|
||||
function srcRectByIdx(puzzleInfo: PuzzleInfo, idx: number) {
|
||||
function srcRectByIdx(puzzleInfo: PuzzleInfo, idx: number): Rect {
|
||||
const c = Util.coordByTileIdx(puzzleInfo, idx)
|
||||
return {
|
||||
x: c.x * puzzleInfo.tileSize,
|
||||
|
|
@ -208,7 +212,7 @@ function srcRectByIdx(puzzleInfo: PuzzleInfo, idx: number) {
|
|||
}
|
||||
}
|
||||
|
||||
async function loadPuzzleBitmaps(puzzle: Puzzle) {
|
||||
async function loadPuzzleBitmaps(puzzle: Puzzle): Promise<Array<ImageBitmap>> {
|
||||
// load bitmap, to determine the original size of the image
|
||||
const bmp = await Graphics.loadImageToBitmap(puzzle.info.imageUrl)
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
import GameCommon from './../../common/GameCommon'
|
||||
import { ScoreMode } from './../../common/GameCommon'
|
||||
import Upload from './../components/Upload.vue'
|
||||
import ImageTeaser from './../components/ImageTeaser.vue'
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ export default defineComponent({
|
|||
return {
|
||||
tiles: 1000,
|
||||
image: '',
|
||||
scoreMode: GameCommon.SCORE_MODE_ANY,
|
||||
scoreMode: ScoreMode.ANY,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import Game, { Player, Piece } from './../common/GameCommon'
|
|||
import fireworksController from './Fireworks'
|
||||
import Protocol from '../common/Protocol'
|
||||
import Time from '../common/Time'
|
||||
import { Dim, Point } from '../common/Geometry'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
|
@ -34,10 +35,6 @@ export const MODE_REPLAY = 'replay'
|
|||
let PIECE_VIEW_FIXED = true
|
||||
let PIECE_VIEW_LOOSE = true
|
||||
|
||||
interface Point {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
interface Hud {
|
||||
setActivePlayers: (v: Array<any>) => void
|
||||
setIdlePlayers: (v: Array<any>) => void
|
||||
|
|
@ -474,10 +471,16 @@ export async function main(
|
|||
RERENDER = true
|
||||
} else if (entryWithTs[0] === Protocol.LOG_UPDATE_PLAYER) {
|
||||
const playerId = Game.getPlayerIdByIndex(gameId, entryWithTs[1])
|
||||
if (!playerId) {
|
||||
throw '[ 2021-05-17 player not found (update player) ]'
|
||||
}
|
||||
Game.addPlayer(gameId, playerId, nextTs)
|
||||
RERENDER = true
|
||||
} else if (entryWithTs[0] === Protocol.LOG_HANDLE_INPUT) {
|
||||
const playerId = Game.getPlayerIdByIndex(gameId, entryWithTs[1])
|
||||
if (!playerId) {
|
||||
throw '[ 2021-05-17 player not found (handle input) ]'
|
||||
}
|
||||
const input = entryWithTs[2]
|
||||
Game.handleInput(gameId, playerId, input, nextTs)
|
||||
RERENDER = true
|
||||
|
|
@ -598,9 +601,9 @@ export async function main(
|
|||
|
||||
const ts = TIME()
|
||||
|
||||
let pos
|
||||
let dim
|
||||
let bmp
|
||||
let pos: Point
|
||||
let dim: Dim
|
||||
let bmp: ImageBitmap
|
||||
|
||||
if (window.DEBUG) Debug.checkpoint_start(0)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
import Scores from './../components/Scores.vue'
|
||||
import PuzzleStatus from './../components/PuzzleStatus.vue'
|
||||
|
|
@ -39,6 +39,7 @@ import ConnectionOverlay from './../components/ConnectionOverlay.vue'
|
|||
import HelpOverlay from './../components/HelpOverlay.vue'
|
||||
|
||||
import { main, MODE_PLAY } from './../game'
|
||||
import { Player } from '../../common/GameCommon'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'game',
|
||||
|
|
@ -52,9 +53,8 @@ export default defineComponent({
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
// TODO: ts Array<Player> type
|
||||
activePlayers: [] as PropType<Array<any>>,
|
||||
idlePlayers: [] as PropType<Array<any>>,
|
||||
activePlayers: [] as Array<Player>,
|
||||
idlePlayers: [] as Array<Player>,
|
||||
|
||||
finished: false,
|
||||
duration: 0,
|
||||
|
|
@ -103,8 +103,8 @@ export default defineComponent({
|
|||
MODE_PLAY,
|
||||
this.$el,
|
||||
{
|
||||
setActivePlayers: (v: Array<any>) => { this.activePlayers = v },
|
||||
setIdlePlayers: (v: Array<any>) => { this.idlePlayers = v },
|
||||
setActivePlayers: (v: Array<Player>) => { this.activePlayers = v },
|
||||
setIdlePlayers: (v: Array<Player>) => { this.idlePlayers = v },
|
||||
setFinished: (v: boolean) => { this.finished = v },
|
||||
setDuration: (v: number) => { this.duration = v },
|
||||
setPiecesDone: (v: number) => { this.piecesDone = v },
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import GameCommon from './../common/GameCommon'
|
||||
import GameCommon, { ScoreMode } from './../common/GameCommon'
|
||||
import Util from './../common/Util'
|
||||
import { Rng } from './../common/Rng'
|
||||
import GameLog from './GameLog'
|
||||
|
|
@ -6,7 +6,13 @@ import { createPuzzle } from './Puzzle'
|
|||
import Protocol from './../common/Protocol'
|
||||
import GameStorage from './GameStorage'
|
||||
|
||||
async function createGameObject(gameId: string, targetTiles: number, image: { file: string, url: string }, ts: number, scoreMode: number) {
|
||||
async function createGameObject(
|
||||
gameId: string,
|
||||
targetTiles: number,
|
||||
image: { file: string, url: string },
|
||||
ts: number,
|
||||
scoreMode: ScoreMode
|
||||
) {
|
||||
const seed = Util.hash(gameId + ' ' + ts)
|
||||
const rng = new Rng(seed)
|
||||
return {
|
||||
|
|
@ -19,7 +25,13 @@ async function createGameObject(gameId: string, targetTiles: number, image: { fi
|
|||
}
|
||||
}
|
||||
|
||||
async function createGame(gameId: string, targetTiles: number, image: { file: string, url: string }, ts: number, scoreMode: number) {
|
||||
async function createGame(
|
||||
gameId: string,
|
||||
targetTiles: number,
|
||||
image: { file: string, url: string },
|
||||
ts: number,
|
||||
scoreMode: ScoreMode
|
||||
) {
|
||||
const gameObject = await createGameObject(gameId, targetTiles, image, ts, scoreMode)
|
||||
|
||||
GameLog.create(gameId)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import fs from 'fs'
|
||||
import GameCommon from './../common/GameCommon'
|
||||
import GameCommon, { ScoreMode } from './../common/GameCommon'
|
||||
import Util, { logger } from './../common/Util'
|
||||
import { Rng } from './../common/Rng'
|
||||
import { DATA_DIR } from './Dirs'
|
||||
|
|
@ -55,7 +55,7 @@ function loadGame(gameId: string): void {
|
|||
puzzle: game.puzzle,
|
||||
players: game.players,
|
||||
evtInfos: {},
|
||||
scoreMode: game.scoreMode || GameCommon.SCORE_MODE_FINAL,
|
||||
scoreMode: game.scoreMode || ScoreMode.FINAL,
|
||||
}
|
||||
GameCommon.setGame(gameObject.id, gameObject)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Util from './../common/Util'
|
||||
import { Rng } from './../common/Rng'
|
||||
import Images from './Images'
|
||||
import { EncodedPiece, EncodedPieceShape, PieceShape } from '../common/GameCommon'
|
||||
|
||||
interface PuzzleInfo {
|
||||
width: number
|
||||
|
|
@ -31,7 +32,7 @@ async function createPuzzle(
|
|||
if (!dim || !dim.width || !dim.height) {
|
||||
throw `[ 2021-05-16 invalid dimension for path ${imagePath} ]`
|
||||
}
|
||||
const info = determinePuzzleInfo(dim.width, dim.height, targetTiles)
|
||||
const info: PuzzleInfo = determinePuzzleInfo(dim.width, dim.height, targetTiles)
|
||||
|
||||
let tiles = new Array(info.tiles)
|
||||
for (let i = 0; i < tiles.length; i++) {
|
||||
|
|
@ -91,7 +92,7 @@ async function createPuzzle(
|
|||
// then shuffle the positions
|
||||
positions = rng.shuffle(positions)
|
||||
|
||||
tiles = tiles.map(tile => {
|
||||
const pieces: Array<EncodedPiece> = tiles.map(tile => {
|
||||
return Util.encodeTile({
|
||||
idx: tile.idx, // index of tile in the array
|
||||
group: 0, // if grouped with other tiles
|
||||
|
|
@ -113,7 +114,7 @@ async function createPuzzle(
|
|||
// Complete puzzle object
|
||||
return {
|
||||
// tiles array
|
||||
tiles,
|
||||
tiles: pieces,
|
||||
// game data for puzzle, data changes during the game
|
||||
data: {
|
||||
// TODO: maybe calculate this each time?
|
||||
|
|
@ -159,10 +160,10 @@ async function createPuzzle(
|
|||
function determinePuzzleTileShapes(
|
||||
rng: Rng,
|
||||
info: PuzzleInfo
|
||||
) {
|
||||
): Array<EncodedPieceShape> {
|
||||
const tabs = [-1, 1]
|
||||
|
||||
const shapes = new Array(info.tiles)
|
||||
const shapes: Array<PieceShape> = new Array(info.tiles)
|
||||
for (let i = 0; i < info.tiles; i++) {
|
||||
let coord = Util.coordByTileIdx(info, i)
|
||||
shapes[i] = {
|
||||
|
|
@ -191,7 +192,11 @@ const determineTilesXY = (w: number, h: number, targetTiles: number) => {
|
|||
}
|
||||
}
|
||||
|
||||
const determinePuzzleInfo = (w: number, h: number, targetTiles: number) => {
|
||||
const determinePuzzleInfo = (
|
||||
w: number,
|
||||
h: number,
|
||||
targetTiles: number
|
||||
): PuzzleInfo => {
|
||||
const {tilesX, tilesY} = determineTilesXY(w, h, targetTiles)
|
||||
const tiles = tilesX * tilesY
|
||||
const tileSize = TILE_SIZE
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import GameSockets from './GameSockets'
|
|||
import Time from './../common/Time'
|
||||
import Images from './Images'
|
||||
import { UPLOAD_DIR, UPLOAD_URL, PUBLIC_DIR } from './Dirs'
|
||||
import GameCommon from '../common/GameCommon'
|
||||
import GameCommon, { ScoreMode } from '../common/GameCommon'
|
||||
import GameStorage from './GameStorage'
|
||||
|
||||
let configFile = ''
|
||||
|
|
@ -158,7 +158,7 @@ wss.on('message', async ({socket, data} : { socket: WebSocket, data: any }) => {
|
|||
log[0][2],
|
||||
log[0][3],
|
||||
log[0][4],
|
||||
log[0][5] || GameCommon.SCORE_MODE_FINAL
|
||||
log[0][5] || ScoreMode.FINAL
|
||||
)
|
||||
notify(
|
||||
[Protocol.EV_SERVER_INIT_REPLAY, Util.encodeGame(game), log],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue