add other snap mode
This commit is contained in:
parent
42aaf10679
commit
2a12900614
11 changed files with 164 additions and 27 deletions
File diff suppressed because one or more lines are too long
1
build/public/assets/index.6e65c5cb.js
Normal file
1
build/public/assets/index.6e65c5cb.js
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -4,7 +4,7 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
<title>🧩 jigsaw.hyottoko.club</title>
|
<title>🧩 jigsaw.hyottoko.club</title>
|
||||||
<script type="module" crossorigin src="/assets/index.4d5f4980.js"></script>
|
<script type="module" crossorigin src="/assets/index.6e65c5cb.js"></script>
|
||||||
<link rel="modulepreload" href="/assets/vendor.684f7bc8.js">
|
<link rel="modulepreload" href="/assets/vendor.684f7bc8.js">
|
||||||
<link rel="stylesheet" href="/assets/index.6748df9f.css">
|
<link rel="stylesheet" href="/assets/index.6748df9f.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,12 @@ var ShapeMode;
|
||||||
ShapeMode[ShapeMode["NORMAL"] = 0] = "NORMAL";
|
ShapeMode[ShapeMode["NORMAL"] = 0] = "NORMAL";
|
||||||
ShapeMode[ShapeMode["ANY"] = 1] = "ANY";
|
ShapeMode[ShapeMode["ANY"] = 1] = "ANY";
|
||||||
ShapeMode[ShapeMode["FLAT"] = 2] = "FLAT";
|
ShapeMode[ShapeMode["FLAT"] = 2] = "FLAT";
|
||||||
})(ShapeMode || (ShapeMode = {}));
|
})(ShapeMode || (ShapeMode = {}));
|
||||||
|
var SnapMode;
|
||||||
|
(function (SnapMode) {
|
||||||
|
SnapMode[SnapMode["NORMAL"] = 0] = "NORMAL";
|
||||||
|
SnapMode[SnapMode["REAL"] = 1] = "REAL";
|
||||||
|
})(SnapMode || (SnapMode = {}));
|
||||||
|
|
||||||
class Rng {
|
class Rng {
|
||||||
constructor(seed) {
|
constructor(seed) {
|
||||||
|
|
@ -173,6 +178,8 @@ function encodeGame(data) {
|
||||||
data.players,
|
data.players,
|
||||||
data.evtInfos,
|
data.evtInfos,
|
||||||
data.scoreMode || ScoreMode.FINAL,
|
data.scoreMode || ScoreMode.FINAL,
|
||||||
|
data.shapeMode || ShapeMode.ANY,
|
||||||
|
data.snapMode || SnapMode.NORMAL,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
function decodeGame(data) {
|
function decodeGame(data) {
|
||||||
|
|
@ -186,6 +193,8 @@ function decodeGame(data) {
|
||||||
players: data[4],
|
players: data[4],
|
||||||
evtInfos: data[5],
|
evtInfos: data[5],
|
||||||
scoreMode: data[6],
|
scoreMode: data[6],
|
||||||
|
shapeMode: data[7],
|
||||||
|
snapMode: data[8],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function coordByPieceIdx(info, pieceIdx) {
|
function coordByPieceIdx(info, pieceIdx) {
|
||||||
|
|
@ -599,6 +608,9 @@ function setImageUrl(gameId, imageUrl) {
|
||||||
function getScoreMode(gameId) {
|
function getScoreMode(gameId) {
|
||||||
return GAMES[gameId].scoreMode || ScoreMode.FINAL;
|
return GAMES[gameId].scoreMode || ScoreMode.FINAL;
|
||||||
}
|
}
|
||||||
|
function getSnapMode(gameId) {
|
||||||
|
return GAMES[gameId].snapMode || SnapMode.NORMAL;
|
||||||
|
}
|
||||||
function isFinished(gameId) {
|
function isFinished(gameId) {
|
||||||
return getFinishedPiecesCount(gameId) === getPieceCount(gameId);
|
return getFinishedPiecesCount(gameId) === getPieceCount(gameId);
|
||||||
}
|
}
|
||||||
|
|
@ -647,6 +659,14 @@ const getPieceGroup = (gameId, tileIdx) => {
|
||||||
const tile = getPiece(gameId, tileIdx);
|
const tile = getPiece(gameId, tileIdx);
|
||||||
return tile.group;
|
return tile.group;
|
||||||
};
|
};
|
||||||
|
const isCornerPiece = (gameId, tileIdx) => {
|
||||||
|
const info = GAMES[gameId].puzzle.info;
|
||||||
|
return (tileIdx === 0 // top left corner
|
||||||
|
|| tileIdx === (info.tilesX - 1) // top right corner
|
||||||
|
|| tileIdx === (info.tiles - info.tilesX) // bottom left corner
|
||||||
|
|| tileIdx === (info.tiles - 1) // bottom right corner
|
||||||
|
);
|
||||||
|
};
|
||||||
const getFinalPiecePos = (gameId, tileIdx) => {
|
const getFinalPiecePos = (gameId, tileIdx) => {
|
||||||
const info = GAMES[gameId].puzzle.info;
|
const info = GAMES[gameId].puzzle.info;
|
||||||
const boardPos = {
|
const boardPos = {
|
||||||
|
|
@ -784,6 +804,12 @@ const movePiecesDiff = (gameId, pieceIdxs, diff) => {
|
||||||
moveTileDiff(gameId, pieceIdx, cappedDiff);
|
moveTileDiff(gameId, pieceIdx, cappedDiff);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const isFinishedPiece = (gameId, pieceIdx) => {
|
||||||
|
return getPieceOwner(gameId, pieceIdx) === -1;
|
||||||
|
};
|
||||||
|
const getPieceOwner = (gameId, pieceIdx) => {
|
||||||
|
return getPiece(gameId, pieceIdx).owner;
|
||||||
|
};
|
||||||
const finishPieces = (gameId, pieceIdxs) => {
|
const finishPieces = (gameId, pieceIdxs) => {
|
||||||
for (const pieceIdx of pieceIdxs) {
|
for (const pieceIdx of pieceIdxs) {
|
||||||
changePiece(gameId, pieceIdx, { owner: -1, z: 1 });
|
changePiece(gameId, pieceIdx, { owner: -1, z: 1 });
|
||||||
|
|
@ -1052,7 +1078,23 @@ function handleInput$1(gameId, playerId, input, ts, onSnap) {
|
||||||
// Check if the tile was dropped near the final location
|
// Check if the tile was dropped near the final location
|
||||||
const tilePos = getPiecePos(gameId, pieceIdx);
|
const tilePos = getPiecePos(gameId, pieceIdx);
|
||||||
const finalPos = getFinalPiecePos(gameId, pieceIdx);
|
const finalPos = getFinalPiecePos(gameId, pieceIdx);
|
||||||
if (Geometry.pointDistance(finalPos, tilePos) < puzzle.info.snapDistance) {
|
let canSnapToFinal = false;
|
||||||
|
console.log(getSnapMode(gameId));
|
||||||
|
if (getSnapMode(gameId) === SnapMode.REAL) {
|
||||||
|
// only can snap to final if any of the grouped pieces are
|
||||||
|
// corner pieces
|
||||||
|
for (const pieceIdxTmp of pieceIdxs) {
|
||||||
|
if (isCornerPiece(gameId, pieceIdxTmp)) {
|
||||||
|
canSnapToFinal = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
canSnapToFinal = true;
|
||||||
|
}
|
||||||
|
if (canSnapToFinal
|
||||||
|
&& Geometry.pointDistance(finalPos, tilePos) < puzzle.info.snapDistance) {
|
||||||
const diff = Geometry.pointSub(finalPos, tilePos);
|
const diff = Geometry.pointSub(finalPos, tilePos);
|
||||||
// Snap the tile to the final destination
|
// Snap the tile to the final destination
|
||||||
movePiecesDiff(gameId, pieceIdxs, diff);
|
movePiecesDiff(gameId, pieceIdxs, diff);
|
||||||
|
|
@ -1095,8 +1137,13 @@ function handleInput$1(gameId, playerId, input, ts, onSnap) {
|
||||||
movePiecesDiff(gameId, pieceIdxs, diff);
|
movePiecesDiff(gameId, pieceIdxs, diff);
|
||||||
groupTiles(gameId, tileIdx, otherTileIdx);
|
groupTiles(gameId, tileIdx, otherTileIdx);
|
||||||
pieceIdxs = getGroupedPieceIdxs(gameId, tileIdx);
|
pieceIdxs = getGroupedPieceIdxs(gameId, tileIdx);
|
||||||
const zIndex = getMaxZIndexByPieceIdxs(gameId, pieceIdxs);
|
if (isFinishedPiece(gameId, otherTileIdx)) {
|
||||||
setPiecesZIndex(gameId, pieceIdxs, zIndex);
|
finishPieces(gameId, pieceIdxs);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const zIndex = getMaxZIndexByPieceIdxs(gameId, pieceIdxs);
|
||||||
|
setPiecesZIndex(gameId, pieceIdxs, zIndex);
|
||||||
|
}
|
||||||
_pieceChanges(pieceIdxs);
|
_pieceChanges(pieceIdxs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1687,6 +1734,8 @@ function loadGame(gameId) {
|
||||||
players: game.players,
|
players: game.players,
|
||||||
evtInfos: {},
|
evtInfos: {},
|
||||||
scoreMode: game.scoreMode || ScoreMode.FINAL,
|
scoreMode: game.scoreMode || ScoreMode.FINAL,
|
||||||
|
shapeMode: game.shapeMode || ShapeMode.ANY,
|
||||||
|
snapMode: game.snapMode || SnapMode.NORMAL,
|
||||||
};
|
};
|
||||||
GameCommon.setGame(gameObject.id, gameObject);
|
GameCommon.setGame(gameObject.id, gameObject);
|
||||||
}
|
}
|
||||||
|
|
@ -1713,6 +1762,8 @@ function persistGame(gameId) {
|
||||||
puzzle: game.puzzle,
|
puzzle: game.puzzle,
|
||||||
players: game.players,
|
players: game.players,
|
||||||
scoreMode: game.scoreMode,
|
scoreMode: game.scoreMode,
|
||||||
|
shapeMode: game.shapeMode,
|
||||||
|
snapMode: game.snapMode,
|
||||||
}));
|
}));
|
||||||
log$3.info(`[INFO] persisted game ${game.id}`);
|
log$3.info(`[INFO] persisted game ${game.id}`);
|
||||||
}
|
}
|
||||||
|
|
@ -1724,7 +1775,7 @@ var GameStorage = {
|
||||||
setDirty,
|
setDirty,
|
||||||
};
|
};
|
||||||
|
|
||||||
async function createGameObject(gameId, targetTiles, image, ts, scoreMode, shapeMode) {
|
async function createGameObject(gameId, targetTiles, image, ts, scoreMode, shapeMode, snapMode) {
|
||||||
const seed = Util.hash(gameId + ' ' + ts);
|
const seed = Util.hash(gameId + ' ' + ts);
|
||||||
const rng = new Rng(seed);
|
const rng = new Rng(seed);
|
||||||
return {
|
return {
|
||||||
|
|
@ -1735,12 +1786,13 @@ async function createGameObject(gameId, targetTiles, image, ts, scoreMode, shape
|
||||||
evtInfos: {},
|
evtInfos: {},
|
||||||
scoreMode,
|
scoreMode,
|
||||||
shapeMode,
|
shapeMode,
|
||||||
|
snapMode,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function createGame(gameId, targetTiles, image, ts, scoreMode, shapeMode) {
|
async function createGame(gameId, targetTiles, image, ts, scoreMode, shapeMode, snapMode) {
|
||||||
const gameObject = await createGameObject(gameId, targetTiles, image, ts, scoreMode, shapeMode);
|
const gameObject = await createGameObject(gameId, targetTiles, image, ts, scoreMode, shapeMode, snapMode);
|
||||||
GameLog.create(gameId);
|
GameLog.create(gameId);
|
||||||
GameLog.log(gameId, Protocol.LOG_HEADER, 1, targetTiles, image, ts, scoreMode, shapeMode);
|
GameLog.log(gameId, Protocol.LOG_HEADER, 1, targetTiles, image, ts, scoreMode, shapeMode, snapMode);
|
||||||
GameCommon.setGame(gameObject.id, gameObject);
|
GameCommon.setGame(gameObject.id, gameObject);
|
||||||
GameStorage.setDirty(gameId);
|
GameStorage.setDirty(gameId);
|
||||||
}
|
}
|
||||||
|
|
@ -2014,7 +2066,7 @@ app.get('/api/replay-data', async (req, res) => {
|
||||||
let game = null;
|
let game = null;
|
||||||
if (offset === 0) {
|
if (offset === 0) {
|
||||||
// also need the game
|
// also need the game
|
||||||
game = await Game.createGameObject(gameId, log[0][2], log[0][3], log[0][4], log[0][5] || ScoreMode.FINAL, log[0][6] || ShapeMode.NORMAL);
|
game = await Game.createGameObject(gameId, log[0][2], log[0][3], log[0][4], log[0][5] || ScoreMode.FINAL, log[0][6] || ShapeMode.NORMAL, log[0][7] || SnapMode.NORMAL);
|
||||||
}
|
}
|
||||||
res.send({ log, game: game ? Util.encodeGame(game) : null });
|
res.send({ log, game: game ? Util.encodeGame(game) : null });
|
||||||
});
|
});
|
||||||
|
|
@ -2102,7 +2154,7 @@ app.post('/api/newgame', express.json(), async (req, res) => {
|
||||||
const gameId = Util.uniqId();
|
const gameId = Util.uniqId();
|
||||||
if (!GameCommon.exists(gameId)) {
|
if (!GameCommon.exists(gameId)) {
|
||||||
const ts = Time.timestamp();
|
const ts = Time.timestamp();
|
||||||
await Game.createGame(gameId, gameSettings.tiles, gameSettings.image, ts, gameSettings.scoreMode, gameSettings.shapeMode);
|
await Game.createGame(gameId, gameSettings.tiles, gameSettings.image, ts, gameSettings.scoreMode, gameSettings.shapeMode, gameSettings.snapMode);
|
||||||
}
|
}
|
||||||
res.send({ id: gameId });
|
res.send({ id: gameId });
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
PuzzleData,
|
PuzzleData,
|
||||||
PuzzleDataChange,
|
PuzzleDataChange,
|
||||||
ScoreMode,
|
ScoreMode,
|
||||||
|
SnapMode,
|
||||||
Timestamp
|
Timestamp
|
||||||
} from './Types'
|
} from './Types'
|
||||||
import Util from './Util'
|
import Util from './Util'
|
||||||
|
|
@ -172,6 +173,10 @@ function getScoreMode(gameId: string): ScoreMode {
|
||||||
return GAMES[gameId].scoreMode || ScoreMode.FINAL
|
return GAMES[gameId].scoreMode || ScoreMode.FINAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSnapMode(gameId: string): SnapMode {
|
||||||
|
return GAMES[gameId].snapMode || SnapMode.NORMAL
|
||||||
|
}
|
||||||
|
|
||||||
function isFinished(gameId: string): boolean {
|
function isFinished(gameId: string): boolean {
|
||||||
return getFinishedPiecesCount(gameId) === getPieceCount(gameId)
|
return getFinishedPiecesCount(gameId) === getPieceCount(gameId)
|
||||||
}
|
}
|
||||||
|
|
@ -237,6 +242,16 @@ const getPieceGroup = (gameId: string, tileIdx: number): number => {
|
||||||
return tile.group
|
return tile.group
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isCornerPiece = (gameId: string, tileIdx: number): boolean => {
|
||||||
|
const info = GAMES[gameId].puzzle.info
|
||||||
|
return (
|
||||||
|
tileIdx === 0 // top left corner
|
||||||
|
|| tileIdx === (info.tilesX - 1) // top right corner
|
||||||
|
|| tileIdx === (info.tiles - info.tilesX) // bottom left corner
|
||||||
|
|| tileIdx === (info.tiles - 1) // bottom right corner
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const getFinalPiecePos = (gameId: string, tileIdx: number): Point => {
|
const getFinalPiecePos = (gameId: string, tileIdx: number): Point => {
|
||||||
const info = GAMES[gameId].puzzle.info
|
const info = GAMES[gameId].puzzle.info
|
||||||
const boardPos = {
|
const boardPos = {
|
||||||
|
|
@ -406,6 +421,14 @@ const movePiecesDiff = (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isFinishedPiece = (gameId: string, pieceIdx: number): boolean => {
|
||||||
|
return getPieceOwner(gameId, pieceIdx) === -1
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPieceOwner = (gameId: string, pieceIdx: number): string|number => {
|
||||||
|
return getPiece(gameId, pieceIdx).owner
|
||||||
|
}
|
||||||
|
|
||||||
const finishPieces = (gameId: string, pieceIdxs: Array<number>): void => {
|
const finishPieces = (gameId: string, pieceIdxs: Array<number>): void => {
|
||||||
for (const pieceIdx of pieceIdxs) {
|
for (const pieceIdx of pieceIdxs) {
|
||||||
changePiece(gameId, pieceIdx, { owner: -1, z: 1 })
|
changePiece(gameId, pieceIdx, { owner: -1, z: 1 })
|
||||||
|
|
@ -721,7 +744,26 @@ function handleInput(
|
||||||
// Check if the tile was dropped near the final location
|
// Check if the tile was dropped near the final location
|
||||||
const tilePos = getPiecePos(gameId, pieceIdx)
|
const tilePos = getPiecePos(gameId, pieceIdx)
|
||||||
const finalPos = getFinalPiecePos(gameId, pieceIdx)
|
const finalPos = getFinalPiecePos(gameId, pieceIdx)
|
||||||
if (Geometry.pointDistance(finalPos, tilePos) < puzzle.info.snapDistance) {
|
|
||||||
|
let canSnapToFinal = false
|
||||||
|
console.log(getSnapMode(gameId))
|
||||||
|
if (getSnapMode(gameId) === SnapMode.REAL) {
|
||||||
|
// only can snap to final if any of the grouped pieces are
|
||||||
|
// corner pieces
|
||||||
|
for (const pieceIdxTmp of pieceIdxs) {
|
||||||
|
if (isCornerPiece(gameId, pieceIdxTmp)) {
|
||||||
|
canSnapToFinal = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
canSnapToFinal = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
canSnapToFinal
|
||||||
|
&& Geometry.pointDistance(finalPos, tilePos) < puzzle.info.snapDistance
|
||||||
|
) {
|
||||||
const diff = Geometry.pointSub(finalPos, tilePos)
|
const diff = Geometry.pointSub(finalPos, tilePos)
|
||||||
// Snap the tile to the final destination
|
// Snap the tile to the final destination
|
||||||
movePiecesDiff(gameId, pieceIdxs, diff)
|
movePiecesDiff(gameId, pieceIdxs, diff)
|
||||||
|
|
@ -774,8 +816,12 @@ function handleInput(
|
||||||
movePiecesDiff(gameId, pieceIdxs, diff)
|
movePiecesDiff(gameId, pieceIdxs, diff)
|
||||||
groupTiles(gameId, tileIdx, otherTileIdx)
|
groupTiles(gameId, tileIdx, otherTileIdx)
|
||||||
pieceIdxs = getGroupedPieceIdxs(gameId, tileIdx)
|
pieceIdxs = getGroupedPieceIdxs(gameId, tileIdx)
|
||||||
const zIndex = getMaxZIndexByPieceIdxs(gameId, pieceIdxs)
|
if (isFinishedPiece(gameId, otherTileIdx)) {
|
||||||
setPiecesZIndex(gameId, pieceIdxs, zIndex)
|
finishPieces(gameId, pieceIdxs)
|
||||||
|
} else {
|
||||||
|
const zIndex = getMaxZIndexByPieceIdxs(gameId, pieceIdxs)
|
||||||
|
setPiecesZIndex(gameId, pieceIdxs, zIndex)
|
||||||
|
}
|
||||||
_pieceChanges(pieceIdxs)
|
_pieceChanges(pieceIdxs)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,8 @@ export type EncodedGame = FixedLengthArray<[
|
||||||
Array<EncodedPlayer>,
|
Array<EncodedPlayer>,
|
||||||
Record<string, EvtInfo>,
|
Record<string, EvtInfo>,
|
||||||
ScoreMode,
|
ScoreMode,
|
||||||
|
ShapeMode,
|
||||||
|
SnapMode,
|
||||||
]>
|
]>
|
||||||
|
|
||||||
export interface ReplayData {
|
export interface ReplayData {
|
||||||
|
|
@ -75,6 +77,7 @@ export interface Game {
|
||||||
evtInfos: Record<string, EvtInfo>
|
evtInfos: Record<string, EvtInfo>
|
||||||
scoreMode?: ScoreMode
|
scoreMode?: ScoreMode
|
||||||
shapeMode?: ShapeMode
|
shapeMode?: ShapeMode
|
||||||
|
snapMode?: SnapMode
|
||||||
rng: GameRng
|
rng: GameRng
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -93,6 +96,7 @@ export interface GameSettings {
|
||||||
image: Image
|
image: Image
|
||||||
scoreMode: ScoreMode
|
scoreMode: ScoreMode
|
||||||
shapeMode: ShapeMode
|
shapeMode: ShapeMode
|
||||||
|
snapMode: SnapMode
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Puzzle {
|
export interface Puzzle {
|
||||||
|
|
@ -207,3 +211,8 @@ export enum ShapeMode {
|
||||||
ANY = 1,
|
ANY = 1,
|
||||||
FLAT = 2,
|
FLAT = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum SnapMode {
|
||||||
|
NORMAL = 0,
|
||||||
|
REAL = 1,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ import {
|
||||||
PieceShape,
|
PieceShape,
|
||||||
Player,
|
Player,
|
||||||
PuzzleInfo,
|
PuzzleInfo,
|
||||||
ScoreMode
|
ScoreMode,
|
||||||
|
ShapeMode,
|
||||||
|
SnapMode
|
||||||
} from './Types'
|
} from './Types'
|
||||||
import { Point } from './Geometry'
|
import { Point } from './Geometry'
|
||||||
import { Rng } from './Rng'
|
import { Rng } from './Rng'
|
||||||
|
|
@ -129,6 +131,8 @@ function encodeGame(data: Game): EncodedGame {
|
||||||
data.players,
|
data.players,
|
||||||
data.evtInfos,
|
data.evtInfos,
|
||||||
data.scoreMode || ScoreMode.FINAL,
|
data.scoreMode || ScoreMode.FINAL,
|
||||||
|
data.shapeMode || ShapeMode.ANY,
|
||||||
|
data.snapMode || SnapMode.NORMAL,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,6 +147,8 @@ function decodeGame(data: EncodedGame): Game {
|
||||||
players: data[4],
|
players: data[4],
|
||||||
evtInfos: data[5],
|
evtInfos: data[5],
|
||||||
scoreMode: data[6],
|
scoreMode: data[6],
|
||||||
|
shapeMode: data[7],
|
||||||
|
snapMode: data[8],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,14 @@
|
||||||
<label><input type="radio" v-model="shapeMode" value="2" /> Flat (all pieces flat on all sides)</label>
|
<label><input type="radio" v-model="shapeMode" value="2" /> Flat (all pieces flat on all sides)</label>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><label>Snapping: </label></td>
|
||||||
|
<td>
|
||||||
|
<label><input type="radio" v-model="snapMode" value="0" /> Normal (pieces snap to final destination and to each other)</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="radio" v-model="snapMode" value="1" /> Real (pieces snap only to corners, already snapped pieces and to each other)</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -46,7 +54,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue'
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
import { GameSettings, ScoreMode, ShapeMode } from './../../common/Types'
|
import { GameSettings, ScoreMode, ShapeMode, SnapMode } from './../../common/Types'
|
||||||
import ResponsiveImage from './ResponsiveImage.vue'
|
import ResponsiveImage from './ResponsiveImage.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
|
@ -69,6 +77,7 @@ export default defineComponent({
|
||||||
tiles: 1000,
|
tiles: 1000,
|
||||||
scoreMode: ScoreMode.ANY,
|
scoreMode: ScoreMode.ANY,
|
||||||
shapeMode: ShapeMode.NORMAL,
|
shapeMode: ShapeMode.NORMAL,
|
||||||
|
snapMode: SnapMode.NORMAL,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -78,6 +87,7 @@ export default defineComponent({
|
||||||
image: this.image,
|
image: this.image,
|
||||||
scoreMode: this.scoreModeInt,
|
scoreMode: this.scoreModeInt,
|
||||||
shapeMode: this.shapeModeInt,
|
shapeMode: this.shapeModeInt,
|
||||||
|
snapMode: this.snapModeInt,
|
||||||
} as GameSettings)
|
} as GameSettings)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -99,6 +109,9 @@ export default defineComponent({
|
||||||
shapeModeInt (): number {
|
shapeModeInt (): number {
|
||||||
return parseInt(`${this.shapeMode}`, 10)
|
return parseInt(`${this.shapeMode}`, 10)
|
||||||
},
|
},
|
||||||
|
snapModeInt (): number {
|
||||||
|
return parseInt(`${this.snapMode}`, 10)
|
||||||
|
},
|
||||||
tilesInt (): number {
|
tilesInt (): number {
|
||||||
return parseInt(`${this.tiles}`, 10)
|
return parseInt(`${this.tiles}`, 10)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import GameCommon from './../common/GameCommon'
|
import GameCommon from './../common/GameCommon'
|
||||||
import { Change, Game, Input, ScoreMode, ShapeMode, Timestamp } from './../common/Types'
|
import { Change, Game, Input, ScoreMode, ShapeMode, SnapMode, Timestamp } from './../common/Types'
|
||||||
import Util, { logger } from './../common/Util'
|
import Util, { logger } from './../common/Util'
|
||||||
import { Rng } from './../common/Rng'
|
import { Rng } from './../common/Rng'
|
||||||
import GameLog from './GameLog'
|
import GameLog from './GameLog'
|
||||||
|
|
@ -15,7 +15,8 @@ async function createGameObject(
|
||||||
image: PuzzleCreationImageInfo,
|
image: PuzzleCreationImageInfo,
|
||||||
ts: Timestamp,
|
ts: Timestamp,
|
||||||
scoreMode: ScoreMode,
|
scoreMode: ScoreMode,
|
||||||
shapeMode: ShapeMode
|
shapeMode: ShapeMode,
|
||||||
|
snapMode: SnapMode
|
||||||
): Promise<Game> {
|
): Promise<Game> {
|
||||||
const seed = Util.hash(gameId + ' ' + ts)
|
const seed = Util.hash(gameId + ' ' + ts)
|
||||||
const rng = new Rng(seed)
|
const rng = new Rng(seed)
|
||||||
|
|
@ -27,6 +28,7 @@ async function createGameObject(
|
||||||
evtInfos: {},
|
evtInfos: {},
|
||||||
scoreMode,
|
scoreMode,
|
||||||
shapeMode,
|
shapeMode,
|
||||||
|
snapMode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,7 +38,8 @@ async function createGame(
|
||||||
image: PuzzleCreationImageInfo,
|
image: PuzzleCreationImageInfo,
|
||||||
ts: Timestamp,
|
ts: Timestamp,
|
||||||
scoreMode: ScoreMode,
|
scoreMode: ScoreMode,
|
||||||
shapeMode: ShapeMode
|
shapeMode: ShapeMode,
|
||||||
|
snapMode: SnapMode
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const gameObject = await createGameObject(
|
const gameObject = await createGameObject(
|
||||||
gameId,
|
gameId,
|
||||||
|
|
@ -44,7 +47,8 @@ async function createGame(
|
||||||
image,
|
image,
|
||||||
ts,
|
ts,
|
||||||
scoreMode,
|
scoreMode,
|
||||||
shapeMode
|
shapeMode,
|
||||||
|
snapMode
|
||||||
)
|
)
|
||||||
|
|
||||||
GameLog.create(gameId)
|
GameLog.create(gameId)
|
||||||
|
|
@ -56,7 +60,8 @@ async function createGame(
|
||||||
image,
|
image,
|
||||||
ts,
|
ts,
|
||||||
scoreMode,
|
scoreMode,
|
||||||
shapeMode
|
shapeMode,
|
||||||
|
snapMode
|
||||||
)
|
)
|
||||||
|
|
||||||
GameCommon.setGame(gameObject.id, gameObject)
|
GameCommon.setGame(gameObject.id, gameObject)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import GameCommon from './../common/GameCommon'
|
import GameCommon from './../common/GameCommon'
|
||||||
import { Piece, ScoreMode } from './../common/Types'
|
import { Game, Piece, ScoreMode, ShapeMode, SnapMode } from './../common/Types'
|
||||||
import Util, { logger } from './../common/Util'
|
import Util, { logger } from './../common/Util'
|
||||||
import { Rng } from './../common/Rng'
|
import { Rng } from './../common/Rng'
|
||||||
import { DATA_DIR } from './Dirs'
|
import { DATA_DIR } from './Dirs'
|
||||||
|
|
@ -49,7 +49,7 @@ function loadGame(gameId: string): void {
|
||||||
if (!Array.isArray(game.players)) {
|
if (!Array.isArray(game.players)) {
|
||||||
game.players = Object.values(game.players)
|
game.players = Object.values(game.players)
|
||||||
}
|
}
|
||||||
const gameObject = {
|
const gameObject: Game = {
|
||||||
id: game.id,
|
id: game.id,
|
||||||
rng: {
|
rng: {
|
||||||
type: game.rng ? game.rng.type : '_fake_',
|
type: game.rng ? game.rng.type : '_fake_',
|
||||||
|
|
@ -59,6 +59,8 @@ function loadGame(gameId: string): void {
|
||||||
players: game.players,
|
players: game.players,
|
||||||
evtInfos: {},
|
evtInfos: {},
|
||||||
scoreMode: game.scoreMode || ScoreMode.FINAL,
|
scoreMode: game.scoreMode || ScoreMode.FINAL,
|
||||||
|
shapeMode: game.shapeMode || ShapeMode.ANY,
|
||||||
|
snapMode: game.snapMode || SnapMode.NORMAL,
|
||||||
}
|
}
|
||||||
GameCommon.setGame(gameObject.id, gameObject)
|
GameCommon.setGame(gameObject.id, gameObject)
|
||||||
}
|
}
|
||||||
|
|
@ -88,6 +90,8 @@ function persistGame(gameId: string): void {
|
||||||
puzzle: game.puzzle,
|
puzzle: game.puzzle,
|
||||||
players: game.players,
|
players: game.players,
|
||||||
scoreMode: game.scoreMode,
|
scoreMode: game.scoreMode,
|
||||||
|
shapeMode: game.shapeMode,
|
||||||
|
snapMode: game.snapMode,
|
||||||
}))
|
}))
|
||||||
log.info(`[INFO] persisted game ${game.id}`)
|
log.info(`[INFO] persisted game ${game.id}`)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import {
|
||||||
UPLOAD_DIR,
|
UPLOAD_DIR,
|
||||||
} from './Dirs'
|
} from './Dirs'
|
||||||
import GameCommon from '../common/GameCommon'
|
import GameCommon from '../common/GameCommon'
|
||||||
import { ServerEvent, Game as GameType, GameSettings, ScoreMode, ShapeMode } from '../common/Types'
|
import { ServerEvent, Game as GameType, GameSettings, ScoreMode, ShapeMode, SnapMode } from '../common/Types'
|
||||||
import GameStorage from './GameStorage'
|
import GameStorage from './GameStorage'
|
||||||
import Db from './Db'
|
import Db from './Db'
|
||||||
|
|
||||||
|
|
@ -90,7 +90,8 @@ app.get('/api/replay-data', async (req, res): Promise<void> => {
|
||||||
log[0][3],
|
log[0][3],
|
||||||
log[0][4],
|
log[0][4],
|
||||||
log[0][5] || ScoreMode.FINAL,
|
log[0][5] || ScoreMode.FINAL,
|
||||||
log[0][6] || ShapeMode.NORMAL
|
log[0][6] || ShapeMode.NORMAL,
|
||||||
|
log[0][7] || SnapMode.NORMAL,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
res.send({ log, game: game ? Util.encodeGame(game) : null })
|
res.send({ log, game: game ? Util.encodeGame(game) : null })
|
||||||
|
|
@ -203,7 +204,8 @@ app.post('/api/newgame', express.json(), async (req, res): Promise<void> => {
|
||||||
gameSettings.image,
|
gameSettings.image,
|
||||||
ts,
|
ts,
|
||||||
gameSettings.scoreMode,
|
gameSettings.scoreMode,
|
||||||
gameSettings.shapeMode
|
gameSettings.shapeMode,
|
||||||
|
gameSettings.snapMode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
res.send({ id: gameId })
|
res.send({ id: gameId })
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue