Randomise ink colours each game

This commit is contained in:
Andrio Celos
2023-10-21 18:33:06 +11:00
parent 4a2bd4d5f9
commit e430d7f3d8
6 changed files with 200 additions and 135 deletions

View File

@@ -139,7 +139,8 @@ function initReplay() {
flipButton.hidden = false;
gameButtonsContainer.hidden = false;
gamePage.dataset.myPlayerIndex = '0';
gamePage.dataset.uiBaseColourIsSpecialColour = 'true';
updateColours();
gamePage.dataset.uiBaseColourIsSpecialColour = currentGame!.game.players[0].uiBaseColourIsSpecialColour?.toString();
canPlay = false;
showPage('game');
clearPlayContainers();
@@ -169,7 +170,7 @@ function initTest(stage: Stage) {
testUndoButton.enabled = false;
clearChildren(testPlacementList);
gamePage.dataset.myPlayerIndex = '0';
gamePage.dataset.uiBaseColourIsSpecialColour = 'true';
gamePage.dataset.uiBaseColourIsSpecialColour = uiBaseColourIsSpecialColourOutOfGame.toString();
gameButtonsContainer.hidden = false;
testControls.hidden = false;
clearPlayContainers();
@@ -497,16 +498,28 @@ function loadPlayers(players: Player[]) {
playerBars[i].name = player.name;
playerBars[i].winCounter.wins = players[i].gamesWon;
updateStats(i, scores);
if (player.colour.r || player.colour.g || player.colour.b) {
document.body.style.setProperty(`--primary-colour-${i + 1}`, `rgb(${player.colour.r}, ${player.colour.g}, ${player.colour.b})`);
document.body.style.setProperty(`--special-colour-${i + 1}`, `rgb(${player.specialColour.r}, ${player.specialColour.g}, ${player.specialColour.b})`);
document.body.style.setProperty(`--special-accent-colour-${i + 1}`, `rgb(${player.specialAccentColour.r}, ${player.specialAccentColour.g}, ${player.specialAccentColour.b})`);
}
}
for (let i = 0; i < playerBars.length; i++) {
playerBars[i].visible = i < players.length;
playContainers[i].hidden = i >= players.length;
}
updateColours();
}
function updateColours() {
if (currentGame == null) return;
for (let i = 0; i < currentGame.game.players.length; i++) {
if (currentGame.game.players[i].colour.r > 0 || currentGame.game.players[i].colour.g > 0 || currentGame.game.players[i].colour.b > 0) {
setColour(i, 0, currentGame.game.players[i].colour);
setColour(i, 1, currentGame.game.players[i].specialColour);
setColour(i, 2, currentGame.game.players[i].specialAccentColour);
for (let j = 0; j < 3; j++) {
updateHSL(i, j);
updateRGB(i, j);
}
}
}
uiBaseColourIsSpecialColourOutOfGame = currentGame.game.players[0].uiBaseColourIsSpecialColour ?? true;
}
function updateStats(playerIndex: number, scores: number[]) {
@@ -587,99 +600,103 @@ async function playInkAnimations(data: {
placements: Placement[],
specialSpacesActivated: Point[]
}, abortSignal?: AbortSignal) {
if (!currentGame) return;
try {
if (!currentGame) return;
const inkPlaced = new Set<number>();
const placements = data.placements;
board.clearHighlight();
board.cardPlaying = null;
board.autoHighlight = false;
board.specialAttack = false;
canPlay = false;
timeLabel.faded = true;
const inkPlaced = new Set<number>();
const placements = data.placements;
board.clearHighlight();
board.cardPlaying = null;
board.autoHighlight = false;
board.specialAttack = false;
canPlay = false;
timeLabel.faded = true;
// Show the cards that were played.
let anySpecialAttacks = false;
for (let i = 0; i < currentGame.game.players.length; i++) {
const player = currentGame.game.players[i];
const move = data.moves[i];
if ((move as PlayMove).isSpecialAttack)
anySpecialAttacks = true;
// Show the cards that were played.
let anySpecialAttacks = false;
for (let i = 0; i < currentGame.game.players.length; i++) {
const player = currentGame.game.players[i];
const move = data.moves[i];
if ((move as PlayMove).isSpecialAttack)
anySpecialAttacks = true;
function addCardDisplay() {
clearChildren(playContainers[i]);
const display = new CardDisplay(move.card, 1);
playContainers[i].append(display.element);
if ((move as PlayMove).isSpecialAttack) {
if (currentReplay) player.specialPoints -= (move as PlayMove).card.specialCost;
const el = document.createElement('div');
el.className = 'specialAttackLabel';
el.innerText = 'Special Attack!';
playContainers[i].appendChild(el);
display.element.classList.add('specialAttack');
} else if (move.isPass) {
if (currentReplay) {
player.passes++;
player.specialPoints++;
function addCardDisplay() {
clearChildren(playContainers[i]);
const display = new CardDisplay(move.card, 1);
playContainers[i].append(display.element);
if ((move as PlayMove).isSpecialAttack) {
if (currentReplay) player.specialPoints -= (move as PlayMove).card.specialCost;
const el = document.createElement('div');
el.className = 'specialAttackLabel';
el.innerText = 'Special Attack!';
playContainers[i].appendChild(el);
display.element.classList.add('specialAttack');
} else if (move.isPass) {
if (currentReplay) {
player.passes++;
player.specialPoints++;
}
const el = document.createElement('div');
el.className = 'passLabel';
el.innerText = 'Pass';
playContainers[i].appendChild(el);
}
const el = document.createElement('div');
el.className = 'passLabel';
el.innerText = 'Pass';
playContainers[i].appendChild(el);
}
const back = playContainers[i].firstElementChild as HTMLElement;
if (back) {
back.style.setProperty('animation', '0.1s ease-in forwards flipCardOut');
back.addEventListener('animationend', addCardDisplay);
} else
addCardDisplay();
}
await delay(anySpecialAttacks ? 3000 : 1000, abortSignal);
for (let i = 0; i < data.game.players.length; i++) {
if ((data.moves[i] as PlayMove).isSpecialAttack)
playerBars[i].specialPoints -= data.moves[i].card.specialCost;
playerBars[i].highlightSpecialPoints = 0;
}
board.enableInkAnimations();
for (const placement of placements) {
// Skip the delay when cards don't overlap.
if (placement.spacesAffected.find(p => inkPlaced.has(p.space.y * 37 + p.space.x))) {
inkPlaced.clear();
await delay(500, abortSignal);
board.clearInkAnimations();
await delay(500, abortSignal);
board.enableInkAnimations();
}
for (const p of placement.spacesAffected) {
inkPlaced.add(p.space.y * 37 + p.space.x);
board.setDisplayedSpace(p.space.x, p.space.y, p.newState);
board.showInkAnimation(p.space.x, p.space.y);
}
}
await delay(500, abortSignal);
board.clearInkAnimations();
await delay(500, abortSignal);
const back = playContainers[i].firstElementChild as HTMLElement;
if (back) {
back.style.setProperty('animation', '0.1s ease-in forwards flipCardOut');
back.addEventListener('animationend', addCardDisplay);
} else
addCardDisplay();
}
await delay(anySpecialAttacks ? 3000 : 1000, abortSignal);
for (let i = 0; i < data.game.players.length; i++) {
if ((data.moves[i] as PlayMove).isSpecialAttack)
playerBars[i].specialPoints -= data.moves[i].card.specialCost;
playerBars[i].highlightSpecialPoints = 0;
}
board.enableInkAnimations();
for (const placement of placements) {
// Skip the delay when cards don't overlap.
if (placement.spacesAffected.find(p => inkPlaced.has(p.space.y * 37 + p.space.x))) {
inkPlaced.clear();
await delay(500, abortSignal);
board.clearInkAnimations();
await delay(500, abortSignal);
board.enableInkAnimations();
// Show special spaces.
if (data.game.board)
board.grid = data.game.board;
board.refresh();
if (data.specialSpacesActivated.length > 0)
await delay(1000, abortSignal); // Delay if we expect that this changed the board.
const scores = board.getScores();
for (let i = 0; i < data.game.players.length; i++) {
playerBars[i].specialPoints = data.game.players[i].specialPoints;
playerBars[i].pointsDelta = scores[i] - playerBars[i].points;
}
for (const p of placement.spacesAffected) {
inkPlaced.add(p.space.y * 37 + p.space.x);
board.setDisplayedSpace(p.space.x, p.space.y, p.newState);
board.showInkAnimation(p.space.x, p.space.y);
await delay(1000, abortSignal);
for (let i = 0; i < data.game.players.length; i++) {
updateStats(i, scores);
}
await delay(1000, abortSignal);
} catch (ex) {
if (!(ex instanceof DOMException) || ex.name != 'AbortError') console.error(ex);
}
await delay(500, abortSignal);
board.clearInkAnimations();
await delay(500, abortSignal);
// Show special spaces.
if (data.game.board)
board.grid = data.game.board;
board.refresh();
if (data.specialSpacesActivated.length > 0)
await delay(1000, abortSignal); // Delay if we expect that this changed the board.
const scores = board.getScores();
for (let i = 0; i < data.game.players.length; i++) {
playerBars[i].specialPoints = data.game.players[i].specialPoints;
playerBars[i].pointsDelta = scores[i] - playerBars[i].points;
}
await delay(1000, abortSignal);
for (let i = 0; i < data.game.players.length; i++) {
updateStats(i, scores);
}
await delay(1000, abortSignal);
}
function showResult() {
@@ -1206,6 +1223,10 @@ function leaveButton_click(e: MouseEvent) {
leaveButton.addEventListener('click', leaveButton_click);
function showColourDebug() {
document.getElementById('debugColour')!.hidden = false;
}
const colBoxes = [
[
[ document.getElementById("colH0I") as HTMLInputElement, document.getElementById("colS0I") as HTMLInputElement, document.getElementById("colL0I") as HTMLInputElement, document.getElementById("colRGB0I") as HTMLInputElement ],
@@ -1229,14 +1250,40 @@ const colBoxes = [
]
];
function colHSL_change(e: Event) {
var p = parseInt((e.target as HTMLInputElement).dataset.player!);
var c = parseInt((e.target as HTMLInputElement).dataset.index!);
updateRGB(p, c);
const box = e.target as HTMLInputElement;
const playerIndex = parseInt(box.dataset.player!);
const colourIndex = parseInt(box.dataset.index!);
const h = (parseInt(colBoxes[playerIndex][colourIndex][0].value) % 360 + 360) % 360; // degrees
const s = Math.min(100, Math.max(0, parseInt(colBoxes[playerIndex][colourIndex][1].value))); // %
const l = Math.min(100, Math.max(0, parseInt(colBoxes[playerIndex][colourIndex][2].value))); // %
const c = (100 - Math.abs(2 * l - 100)) * s; // × 1/10000
const x = c * (60 - Math.abs(h % 120 - 60)); // × 1/600000
const min = (l * 100 - c / 2) * 60; // × 1/600000
const rgb1 =
h < 60 ? { r: c * 60, g: x, b: 0 } :
h < 120 ? { r: x, g: c * 60, b: 0 } :
h < 180 ? { r: 0, g: c * 60, b: x } :
h < 240 ? { r: 0, g: x, b: c * 60 } :
h < 300 ? { r: x, g: 0, b: c * 60 } :
{ r: c * 60, g: 0, b: x }; // × 1/600000
const rgb = { r: Math.round((rgb1.r + min) * 255 / 600000), g: Math.round((rgb1.g + min) * 255 / 600000), b: Math.round((rgb1.b + min) * 255 / 600000) };
setColour(playerIndex, colourIndex, rgb);
updateRGB(playerIndex, colourIndex);
}
function colRGB_change(e: Event) {
var p = parseInt((e.target as HTMLInputElement).dataset.player!);
var c = parseInt((e.target as HTMLInputElement).dataset.index!);
updateHSL(p, c);
const box = e.target as HTMLInputElement;
const playerIndex = parseInt(box.dataset.player!);
const colourIndex = parseInt(box.dataset.index!);
let colourStr = colBoxes[playerIndex][colourIndex][3].value;
if (colourStr.startsWith('#')) colourStr = colourStr.substring(1);
if (colourStr.length >= 8) colourStr = colourStr.substring(colourStr.length - 6);
const rgb = { r: parseInt(colourStr.substring(0, 2), 16), g: parseInt(colourStr.substring(2, 4), 16), b: parseInt(colourStr.substring(4, 6), 16) };
setColour(playerIndex, colourIndex, rgb);
updateHSL(playerIndex, colourIndex);
}
for (const a of colBoxes) {
for (const a2 of a) {
@@ -1255,8 +1302,11 @@ function updateHSL(playerIndex: number, colourIndex: number) {
let colourStr = colBoxes[playerIndex][colourIndex][3].value;
if (colourStr.startsWith('#')) colourStr = colourStr.substring(1);
if (colourStr.length == 8) colourStr = colourStr.substring(2);
const colour = { r: parseInt(colourStr.substring(0, 2), 16), g: parseInt(colourStr.substring(2, 4), 16), b: parseInt(colourStr.substring(4, 6), 16) };
setColour(playerIndex, colourIndex, colour);
const colour = currentGame != null
? (colourIndex == 0 ? currentGame!.game.players[playerIndex].colour :
colourIndex == 1 ? currentGame!.game.players[playerIndex].specialColour :
currentGame!.game.players[playerIndex].specialAccentColour)
: defaultColours[playerIndex][colourIndex];
const max = Math.max(colour.r, colour.g, colour.b); // × 1/255
const min = Math.min(colour.r, colour.g, colour.b); // × 1/255
const c = max - min; // × 1/255
@@ -1273,22 +1323,12 @@ function updateHSL(playerIndex: number, colourIndex: number) {
colBoxes[playerIndex][colourIndex][2].value = l.toString();
}
function updateRGB(playerIndex: number, colourIndex: number) {
const h = (parseInt(colBoxes[playerIndex][colourIndex][0].value) % 360 + 360) % 360; // degrees
const s = Math.min(100, Math.max(0, parseInt(colBoxes[playerIndex][colourIndex][1].value))); // %
const l = Math.min(100, Math.max(0, parseInt(colBoxes[playerIndex][colourIndex][2].value))); // %
const c = (100 - Math.abs(2 * l - 100)) * s; // × 1/10000
const x = c * (60 - Math.abs(h % 120 - 60)); // × 1/600000
const min = (l * 100 - c / 2) * 60; // × 1/600000
const rgb1 =
h < 60 ? { r: c * 60, g: x, b: 0 } :
h < 120 ? { r: x, g: c * 60, b: 0 } :
h < 180 ? { r: 0, g: c * 60, b: x } :
h < 240 ? { r: 0, g: x, b: c * 60 } :
h < 300 ? { r: x, g: 0, b: c * 60 } :
{ r: c * 60, g: 0, b: x }; // × 1/600000
const rgb = { r: Math.round((rgb1.r + min) * 255 / 600000), g: Math.round((rgb1.g + min) * 255 / 600000), b: Math.round((rgb1.b + min) * 255 / 600000) };
colBoxes[playerIndex][colourIndex][3].value = `#${rgb.r.toString(16).padStart(2, '0')}${rgb.g.toString(16).padStart(2, '0')}${rgb.b.toString(16).padStart(2, '0')}`;
setColour(playerIndex, colourIndex, rgb);
const colour = currentGame != null
? (colourIndex == 0 ? currentGame!.game.players[playerIndex].colour :
colourIndex == 1 ? currentGame!.game.players[playerIndex].specialColour :
currentGame!.game.players[playerIndex].specialAccentColour)
: defaultColours[playerIndex][colourIndex];
colBoxes[playerIndex][colourIndex][3].value = `#${colour.r.toString(16).padStart(2, '0')}${colour.g.toString(16).padStart(2, '0')}${colour.b.toString(16).padStart(2, '0')}`;
}
function setColour(playerIndex: number, colourIndex: number, colour: Colour) {
if (!currentGame || playerIndex >= currentGame.game.players.length) return;

View File

@@ -1,5 +1,13 @@
declare var baseUrl: string;
const defaultColours = [
[ { r: 236, g: 249, b: 1 }, { r: 250, g: 158, b: 0 }, { r: 249, g: 249, b: 31 } ],
[ { r: 74, g: 92, b: 252 }, { r: 1, g: 237, b: 254 }, { r: 213, g: 225, b: 225 } ],
[ { r: 249, g: 6, b: 224 }, { r: 128, g: 6, b: 249 }, { r: 235, g: 180, b: 253 } ],
[ { r: 6, g: 249, b: 148 }, { r: 6, g: 249, b: 6 }, { r: 180, g: 253, b: 199 } ]
];
let uiBaseColourIsSpecialColourOutOfGame = true;
const errorDialog = document.getElementById('errorDialog') as HTMLDialogElement;
const errorMessage = document.getElementById('errorMessage')!;
const errorDialogForm = document.getElementById('errorDialogForm') as HTMLFormElement;
@@ -259,6 +267,7 @@ function setupWebSocket(gameID: string) {
me: payload.playerData,
webSocket: webSocket
};
updateColours();
lobbyResetSlots();
for (let i = 0; i < currentGame.game.players.length; i++)
@@ -393,6 +402,7 @@ function setupWebSocket(gameID: string) {
});
webSocket.addEventListener('close', webSocket_close);
}
function webSocket_close() {
communicationError();
}