Major changes

- Fully working ship placement system
- Validating ship positions works too
- Client side ship data display works as well
- Changes to field colors to dark grey instead of light. This improves comfort of use and ensures proper contrast on lower quality displays and ease of use.
This commit is contained in:
MaciejkaG 2024-03-03 16:55:38 +01:00
parent 7c4801db2d
commit bb17dc47ba
7 changed files with 116 additions and 50 deletions

View File

@ -238,11 +238,15 @@ io.on('connection', async (socket) => {
if (playerGame.data.state === 'preparation') {
const playerShips = await GInfo.getPlayerShips(socket);
let canPlace = bships.validateShipPosition(playerShips, type, posX, posY, rot);
let shipAvailable = bships.getShipsAvailable(playerShips)[type] > 0;
if (canPlace) {
console.log("placed");
if (!canPlace) {
socket.emit("toast", "Nie możesz postawić tak statku");
} else if (!shipAvailable) {
socket.emit("toast", "Nie masz już statków tego typu");
} else {
socket.emit("toast", "Nie możesz postawić tak statku")
await GInfo.placeShip(socket, { type: type, posX: posX, posY: posY, rot: rot });
socket.emit("placed ship", { type: type, posX: posY, posY: posX, rot: rot });
}
}
});
@ -252,7 +256,7 @@ io.on('connection', async (socket) => {
if (playerGame.data.state === 'action') {
if (bships.checkTurn(playerGame, socket.id)) {
}
}
});

View File

@ -2,9 +2,9 @@
font-size: 20px;
--field: rgb(201, 201, 201);
--mark-line: rgb(136, 136, 136);
--mark-spot: rgb(68, 68, 68);
--field: rgb(36, 36, 36);
--mark-line: rgb(59, 59, 59);
--mark-spot: rgb(90, 90, 90);
--mark-ship-valid: hsl(120, 100%, 80%);
--mark-ship-invalid: hsl(0, 100%, 80%);
--ship-valid: hsl(120, 70%, 55%);
@ -77,13 +77,19 @@ h1,h2,h3,h4,h5,h6 {
background: var(--ship-valid);
pointer-events: none;
opacity: 0;
transition: opacity 0.15s;
transform: scale(0);
transition: opacity 0.25s, transform 0.25s 0.05s;
}
#secondaryBoard .field .shipField {
background: var(--ship-invalid);
}
.field .shipField.active {
transform: scale(1);
opacity: 1;
}
.field svg {
opacity: 0;
width: 100%;

View File

@ -3,7 +3,7 @@ class Battleships {
if (boardSize>0) {
this.boardSize = boardSize;
} else {
throw new Error("Wrong boardSize for the 'Battleships' class");
throw new Error("Incorrect boardSize for the 'Battleships' class");
}
}
@ -22,7 +22,9 @@ class Battleships {
}
getField(x, y) {
if (0 < x && x <= this.boardSize && 0 < y && y <= this.boardSize) {
if (0 <= x && x < this.boardSize && 0 <= y && y < this.boardSize) {
x++;
y++;
return $(`#board .row:nth-child(${y}) .field:nth-child(${x})`);
} else {
throw new RangeError("getField position out of range.");
@ -30,20 +32,50 @@ class Battleships {
}
getRow(row) {
row = parseInt(row)+1
row++;
if (row<=this.boardSize) {
return $(`#board .row:nth-child(${row}) .field`);
} else {
throw new RangeError("getColumn position out of range.");
throw new RangeError("getRow position out of range.");
}
}
getColumn(column) {
column = parseInt(column)+1
column++;
if (column<=this.boardSize) {
return $(`#board .row .field:nth-child(${column})`);
} else {
throw new RangeError("getColumn position out of range.");
}
}
placeShip(data) {
let fields = [];
switch (data.rot) {
case 0:
for (let i = 0; i <= data.type; i++) {
fields.push([data.posX + i, data.posY]);
}
break;
case 1:
for (let i = 0; i <= data.type; i++) {
fields.push([data.posX, data.posY + i]);
}
break;
case 2:
for (let i = 0; i <= data.type; i++) {
fields.push([data.posX - i, data.posY]);
}
break;
case 3:
for (let i = 0; i <= data.type; i++) {
fields.push([data.posX, data.posY - i]);
}
break;
}
fields.forEach(field => {
this.getField(field[0], field[1]).children(".shipField").addClass("active");
});
}
}

View File

@ -10,10 +10,13 @@ var previousRow = $(":not(*)");
var previousColumn = $(":not(*)");
var selectedShip = 0;
var shipRotation = 0;
var shipsLeft = [4, 3, 2, 1];
var changedFields = [];
var hoveredField = null;
refreshBoardView();
$("#board .field").hover(function () {
hoveredField = this;
// Pokaż "miarki"
@ -24,17 +27,15 @@ $("#board .field").hover(function () {
changedFields.push(row, column, $(this));
row.css("background", "rgb(136, 136, 136)");
column.css("background", "rgb(136, 136, 136)");
row.css("background", "var(--mark-line)");
column.css("background", "var(--mark-line)");
$(this).css("background", "rgb(68, 68, 68)");
$(this).css("background", "var(--mark-spot)");
previousRow = row;
previousColumn = column;
// Pokaż podgląd statku
posX++;
posY++;
var fields = [];
switch (shipRotation) {
case 0:
@ -61,7 +62,7 @@ $("#board .field").hover(function () {
var fieldElem;
let failed = false;
for (let i = 0; i < selectedShip+1; i++) {
for (let i = 0; i <= selectedShip; i++) {
const field = fields[i];
try {
@ -74,9 +75,9 @@ $("#board .field").hover(function () {
}
if (failed) {
fieldElem.css("background", "rgb(255, 163, 163)");
fieldElem.css("background", "var(--mark-ship-invalid)");
} else {
fieldElem.css("background", "rgb(163, 255, 163)");
fieldElem.css("background", "var(--mark-ship-valid)");
}
changedFields.push(fieldElem);
}
@ -84,7 +85,7 @@ $("#board .field").hover(function () {
hoveredField = null;
// Wyłącz "miarki" po wyjściu kursora z pola (aby się nie duplikowały w przyszłości)
changedFields.forEach(field => {
field.css("background", "rgb(201, 201, 201)");
field.css("background", "var(--field)");
});
changedFields.length = 0;
});
@ -153,9 +154,17 @@ function switchRotation() {
}
function refreshBoardView() {
let shipsOfType = shipsLeft[selectedShip];
$("#shipsLeft").html(shipsOfType);
if (!shipsOfType) {
$("#shipsLeft").addClass("danger");
} else {
$("#shipsLeft").removeClass("danger");
}
if (hoveredField) {
changedFields.forEach(field => {
field.css("background", "rgb(201, 201, 201)");
field.css("background", "var(--field)");
});
changedFields.length = 0;
@ -166,16 +175,14 @@ function refreshBoardView() {
changedFields.push(row, column, $(hoveredField));
row.css("background", "rgb(136, 136, 136)");
column.css("background", "rgb(136, 136, 136)");
row.css("background", "var(--mark-line)");
column.css("background", "var(--mark-line)");
$(hoveredField).css("background", "rgb(68, 68, 68)");
$(hoveredField).css("background", "var(--mark-field)");
previousRow = row;
previousColumn = column;
posX++;
posY++;
var fields = [];
switch (shipRotation) {
case 0:
@ -202,7 +209,7 @@ function refreshBoardView() {
var fieldElem;
let failed = false;
for (let i = 0; i < selectedShip + 1; i++) {
for (let i = 0; i <= selectedShip; i++) {
const field = fields[i];
try {
@ -215,9 +222,9 @@ function refreshBoardView() {
}
if (failed) {
fieldElem.css("background", "rgb(255, 163, 163)");
fieldElem.css("background", "var(--mark-ship-invalid)");
} else {
fieldElem.css("background", "rgb(163, 255, 163)");
fieldElem.css("background", "var(--mark-ship-valid)");
}
changedFields.push(fieldElem);
}

View File

@ -5,7 +5,6 @@ var timerDestination = null;
var gamePhase = 'pregame';
$('.field').on('click', function () {
console.log("Clicked");
socket.emit("place ship", selectedShip, $(this).data('pos-x'), $(this).data('pos-y'), shipRotation);
});
@ -21,6 +20,12 @@ socket.on('toast', (msg) => {
}).showToast();
});
socket.on("placed ship", (data) => {
bsc.placeShip(data);
shipsLeft[data.type]--;
refreshBoardView();
});
socket.on('connect', () => {
$(".cover h1").html("Oczekiwanie na serwer...");
});
@ -30,9 +35,7 @@ socket.on("players ready", () => {
});
socket.on("player idx", (idx) => {
console.log(idx);
playerIdx = idx;
console.log(playerIdx);
});
socket.on('turn update', (turnData) => {

View File

@ -35,14 +35,23 @@ export class GameInfo {
const gameId = socket.session.activeGame;
const key = `game:${gameId}`;
await this.redis.json.set(key, '$.state', 'action');
let nextPlayer = await this.redis.json.get(key, '$.nextPlayer');
await this.redis.json.set(key, '.state', 'action');
let nextPlayer = await this.redis.json.get(key, '.nextPlayer');
nextPlayer = nextPlayer === 0 ? 1 : 0;
await this.redis.json.set(key, '$.nextPlayer', nextPlayer);
await this.redis.json.set(key, '.nextPlayer', nextPlayer);
const UTCTs = Math.floor((new Date()).getTime() / 1000 + 30);
this.io.to(gameId).emit('turn update', { turn: 0, phase: "action", timerToUTC: UTCTs });
}
async placeShip(socket, shipData) {
const gameId = socket.session.activeGame;
const key = `game:${gameId}`;
const hostId = (await this.redis.json.get(key, {path: '$.hostId'}))[0];
const playerIdx = socket.request.session.id === hostId ? 0 : 1;
let res = await this.redis.json.arrAppend(key, `.boards[${playerIdx}].ships`, shipData);
}
}
export function isPlayerInRoom(socket) {
@ -95,12 +104,10 @@ export function resetTimers() {
// });
// }
export function getShipsAvailable(data, playerIdx) {
export function getShipsAvailable(ships) {
let shipsLeft = [4, 3, 2, 1];
const playerShips = shipsLeft.boards[playerIdx].ships;
playerShips.forEach(ship => {
ships.forEach(ship => {
shipsLeft[ship.type]--;
});
@ -152,8 +159,6 @@ export function checkHit(data, playerIdx, posX, posY) {
}
export function validateShipPosition(ships, type, posX, posY, rot) {
let multips;
let boardRender = [];
for (let i = 0; i < 10; i++) {
@ -165,6 +170,7 @@ export function validateShipPosition(ships, type, posX, posY, rot) {
}
ships.forEach(ship => {
let multips;
switch (ship.rot) {
@ -181,7 +187,7 @@ export function validateShipPosition(ships, type, posX, posY, rot) {
break;
case 3:
multips = [1, 0];
multips = [-1, 0];
break;
}
@ -190,6 +196,8 @@ export function validateShipPosition(ships, type, posX, posY, rot) {
}
});
let multips;
switch (rot) {
case 0:
multips = [0, 1];
@ -204,16 +212,22 @@ export function validateShipPosition(ships, type, posX, posY, rot) {
break;
case 3:
multips = [1, 0];
multips = [-1, 0];
break;
}
for (let i = 0; i < type + 1; i++) {
if (posY + multips[1] * i > 9 || posY + multips[1] * i < 0 || posX + multips[0] * i > 9 || posX + multips[0] * i < 0) {
for (let x = 0; x <= type; x++) {
if (posY + multips[1] * x > 9 || posY + multips[1] * x < 0 || posX + multips[0] * x > 9 || posX + multips[0] * x < 0) {
return false;
}
if (boardRender[posY + multips[1] * i][posX + multips[0] * i]) {
return false;
let subtrahents = [[0, 0], [0, 1], [1, 0], [0, -1], [-1, 0], [1, 1], [-1, -1], [1, -1], [-1, 1]]; // Usuń cztery ostatnie elementy jeżeli chcesz by statki mogły się stykać rogami
for (let y = 0; y < subtrahents.length; y++) {
const idxY = posY - subtrahents[y][0] + multips[1] * x;
const idxX = posX - subtrahents[y][1] + multips[0] * x;
if (!(idxY < 0 || idxY > 9 || idxX < 0 || idxX > 9) && boardRender[idxY][idxX]) {
return false;
}
}
}

View File

@ -10,7 +10,7 @@
<div class="ownBoardInfo">
<h3>Wybrany statek</h3>
<h2 class="dynamic" id="selectedShip">Jednomasztowiec</h2>
<h3>Dostępne: <span class="dynamic danger">1</span></h3>
<h3>Dostępne: <span class="dynamic danger" id="shipsLeft">1</span></h3>
</div>
<span class="break"></span>
<h2>Sterowanie</h2>