BIG CHANGES
This commit is contained in:
390
index.html
390
index.html
@@ -1,9 +1,10 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Document</title>
|
<title>شرطنج</title>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -12,68 +13,379 @@
|
|||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
color: 262942;
|
color: 262942;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: #f8e8d3;
|
background-color: #f8e8d3;
|
||||||
}
|
}
|
||||||
.title {
|
|
||||||
font-family: 'Times New Roman', Times, serif;
|
|
||||||
text-transform: lowercase;
|
|
||||||
letter-spacing: 0.25rem;
|
|
||||||
font-size: 4rem;
|
|
||||||
font-weight: 100;
|
|
||||||
color: #48517b;
|
|
||||||
padding: 0 0.5rem 0.5rem 0.5rem;
|
|
||||||
display: block;
|
|
||||||
width: min-content;
|
|
||||||
border-bottom: 2px solid #48517b;
|
|
||||||
}
|
|
||||||
header {
|
header {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 1rem;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
height: 230px;
|
||||||
}
|
}
|
||||||
#board {
|
|
||||||
width: 38rem;
|
|
||||||
height: 38rem;
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(8, 1fr);
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
.center {
|
.center {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
margin: 24px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.join-menu {
|
||||||
|
display: flex;
|
||||||
|
width: min-content;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid #48517b56;
|
||||||
|
}
|
||||||
|
|
||||||
|
.join-menu * {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
button {
|
||||||
|
outline: none;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 8px 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.piece {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 20;
|
||||||
|
position: relative;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.game {
|
||||||
|
width: 600px;
|
||||||
|
height: 600px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<h1 class="title">shatranj</h1>
|
<img src="/static/logo.png" alt="">
|
||||||
</header>
|
</header>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<div id="board">
|
<div id="join-menu" class="join-menu"><input type="text" id="room-id" placeholder="Room ID"><button
|
||||||
|
id="join-submit">Join</button></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
<canvas class="game" id="canvas"></canvas>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
const container = document.getElementById("board");
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const canvas = document.getElementById('canvas');
|
||||||
|
canvas.width = canvas.clientWidth;
|
||||||
|
canvas.height = canvas.clientHeight;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
const cols = ["A", "B", "C", "D", "E", "F", "G", "H"];
|
const width = canvas.width;
|
||||||
|
const height = canvas.height;
|
||||||
|
|
||||||
for (let i = 0; i < 64; i++) {
|
const primary = '#f0d9b5';
|
||||||
let col = i % 8;
|
const accent = '#b58863';
|
||||||
let row = Math.floor(i/8);
|
|
||||||
const div = document.createElement("div");
|
ctx.font = 'bolder 16px Arial';
|
||||||
div.className = "house";
|
|
||||||
div.id = cols[col] + (row+1).toString()
|
let mouse = [0, 0];
|
||||||
if (i % 2 == row % 2) {
|
let mHouse = [0, 0];
|
||||||
div.style.backgroundColor = "#262942"
|
const textures = {};
|
||||||
} else {
|
|
||||||
div.style.backgroundColor = "#faf5f0"
|
let color = 0;
|
||||||
|
let turn = 0;
|
||||||
|
let ready = false;
|
||||||
|
let letterMap = ' ';
|
||||||
|
let numberMap = ' ';
|
||||||
|
let board = undefined;
|
||||||
|
let UID = undefined;
|
||||||
|
let ROOM_ID = undefined;
|
||||||
|
|
||||||
|
let selected = undefined;
|
||||||
|
let moves = [];
|
||||||
|
|
||||||
|
canvas.addEventListener('mousemove', (e) => {
|
||||||
|
const rect = canvas.getBoundingClientRect();
|
||||||
|
const x = ((e.clientX - rect.left) / rect.width) * width;
|
||||||
|
const y = ((e.clientY - rect.top) / rect.height) * height;
|
||||||
|
mouse = [x, y];
|
||||||
|
i = Math.floor((x / width) * 8);
|
||||||
|
j = Math.floor((y / height) * 8);
|
||||||
|
if (ready) {
|
||||||
|
canvas.style.cursor = 'default';
|
||||||
|
if (board) {
|
||||||
|
if (color == 0) {
|
||||||
|
j = 7 - j;
|
||||||
|
} else {
|
||||||
|
i = 7 - i;
|
||||||
|
}
|
||||||
|
mHouse = [i, j];
|
||||||
|
if (board[j][i] !== "E" && (board[j][i] === board[j][i].toUpperCase() ? 0 : 1) === color && turn == color) {
|
||||||
|
canvas.style.cursor = 'pointer';
|
||||||
|
}
|
||||||
|
moves.forEach(move => {
|
||||||
|
if (move[0] == i && move[1] == j) {
|
||||||
|
canvas.style.cursor = 'pointer';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
canvas.style.cursor = 'not-allowed';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
canvas.addEventListener('mouseup', (e) => {
|
||||||
|
i = mHouse[0];
|
||||||
|
j = mHouse[1];
|
||||||
|
if (ready && board) {
|
||||||
|
console.log(turn);
|
||||||
|
console.log(color);
|
||||||
|
console.log(selected);
|
||||||
|
if (board[j][i] !== "E" && (board[j][i] === board[j][i].toUpperCase() ? 0 : 1) === color && turn == color) {
|
||||||
|
|
||||||
|
selected = [i, j];
|
||||||
|
moves = [];
|
||||||
|
fetch('{{ API_ROOT }}/moves/' + ROOM_ID, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ from: "ABCDEFGH"[i] + "12345678"[j] })
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
moves_str = data.moves.split(",");
|
||||||
|
console.log(data.moves);
|
||||||
|
moves_str.forEach(move => {
|
||||||
|
moves.push(["abcdefgh".indexOf(move[0].toLowerCase()), "12345678".indexOf(move[1])])
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => console.error('Error:', error));
|
||||||
|
} else if (turn == color && selected) {
|
||||||
|
moves.forEach(move => {
|
||||||
|
console.log(move);
|
||||||
|
if (move[0] == i && move[1] == j) {
|
||||||
|
console.log("YAY");
|
||||||
|
fetch('{{ API_ROOT }}/move/' + ROOM_ID, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ uid: UID, from: "ABCDEFGH"[selected[0]] + "12345678"[selected[1]], to: "ABCDEFGH"[i] + "12345678"[j] })
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
board = data.board.grid;
|
||||||
|
console.log(data);
|
||||||
|
selected = undefined;
|
||||||
|
moves = [];
|
||||||
|
})
|
||||||
|
.catch((error) => console.error('Error:', error));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
moves = [];
|
||||||
|
selected = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
if (ROOM_ID) {
|
||||||
|
fetch('{{ API_ROOT }}/poll/' + ROOM_ID, {
|
||||||
|
method: 'GET',
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
ready = data.ready;
|
||||||
|
turn = data.turn;
|
||||||
|
board = data.board.grid;
|
||||||
|
})
|
||||||
|
.catch((error) => console.error('Error:', error));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
container.appendChild(div);
|
|
||||||
}
|
setInterval(update, 1500);
|
||||||
|
|
||||||
|
function extractIdFromPath() {
|
||||||
|
const currentPath = window.location.pathname;
|
||||||
|
|
||||||
|
const idRegex = /^\/([^/]+)$/;
|
||||||
|
|
||||||
|
const match = currentPath.match(idRegex);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
const extractedId = match[1];
|
||||||
|
return extractedId;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function join(rid) {
|
||||||
|
if (rid.length > 0 && /^[a-zA-Z0-9_-]+$/.test(rid)) {
|
||||||
|
fetch('{{ API_ROOT }}/join/' + rid, {
|
||||||
|
method: 'POST',
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
if (data.code === "FULL") {
|
||||||
|
alert("Game is full you can only spectate.");
|
||||||
|
} else {
|
||||||
|
UID = data.id;
|
||||||
|
color = data.color;
|
||||||
|
ready = data.ready;
|
||||||
|
turn = data.turn;
|
||||||
|
}
|
||||||
|
ROOM_ID = rid;
|
||||||
|
board = data.board.grid;
|
||||||
|
numberMap = "12345678";
|
||||||
|
letterMap = "abcdefgh";
|
||||||
|
document.getElementById('join-menu').outerHTML = '';
|
||||||
|
const urlID = extractIdFromPath();
|
||||||
|
if (urlID == null) {
|
||||||
|
history.pushState({ pageId: ROOM_ID }, '', `/${ROOM_ID}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => console.error('Error:', error));
|
||||||
|
} else {
|
||||||
|
alert("Invalid Room ID");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const urlID = extractIdFromPath();
|
||||||
|
if (urlID != null) {
|
||||||
|
join(urlID);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('join-submit').onclick = () => {
|
||||||
|
let rid = document.getElementById('room-id').value.trim();
|
||||||
|
join(rid);
|
||||||
|
};
|
||||||
|
|
||||||
|
function drawCenter(texture, x, y, width, height, padding) {
|
||||||
|
ctx.drawImage(
|
||||||
|
texture, x + padding, y + padding, width - padding * 2,
|
||||||
|
height - padding * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
ctx.clearRect(0, 0, width, height);
|
||||||
|
const w = width / 8;
|
||||||
|
const h = height / 8;
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
for (let j = 0; j < 8; j++) {
|
||||||
|
let I = i;
|
||||||
|
let J = j;
|
||||||
|
if (color == 0) {
|
||||||
|
J = 7 - J;
|
||||||
|
} else {
|
||||||
|
I = 7 - I;
|
||||||
|
}
|
||||||
|
ctx.beginPath();
|
||||||
|
if ((i * 8 + j) % 2 == i % 2) {
|
||||||
|
ctx.fillStyle = primary;
|
||||||
|
} else {
|
||||||
|
ctx.fillStyle = accent;
|
||||||
|
}
|
||||||
|
ctx.rect(i * w, j * h, w, h);
|
||||||
|
ctx.fill();
|
||||||
|
if (selected && selected[0] == I && selected[1] == J) {
|
||||||
|
ctx.fillStyle = "#00f0f0aa"
|
||||||
|
ctx.rect(i * w, j * h, w, h);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
moves.forEach(move => {
|
||||||
|
if (move[0] == I && move[1] == J) {
|
||||||
|
if (board[J][I] !== 'E') {
|
||||||
|
ctx.fillStyle = "#fa2026aa"
|
||||||
|
} else {
|
||||||
|
ctx.fillStyle = "#f0f000aa"
|
||||||
|
}
|
||||||
|
ctx.rect(i * w, j * h, w, h);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if ((i * 8 + j) % 2 == i % 2) {
|
||||||
|
ctx.fillStyle = accent;
|
||||||
|
} else {
|
||||||
|
ctx.fillStyle = primary;
|
||||||
|
}
|
||||||
|
if (i == 7) {
|
||||||
|
ctx.fillText(numberMap[J], i * w + w - 16, j * h + 16);
|
||||||
|
}
|
||||||
|
if (j == 7) {
|
||||||
|
ctx.fillText(letterMap[I], i * w + 6, j * h + h - 6);
|
||||||
|
}
|
||||||
|
if (board) {
|
||||||
|
if (board[J][I] !== 'E') {
|
||||||
|
drawCenter(textures[board[J][I]], i * w, j * h, w, h, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ctx.beginPath();
|
||||||
|
// ctx.fillStyle = 'red';
|
||||||
|
// ctx.arc(mouse[0], mouse[1], 6, 0, Math.PI * 2);
|
||||||
|
// ctx.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loop() {
|
||||||
|
draw();
|
||||||
|
requestAnimationFrame(loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
const assets = {
|
||||||
|
p: '/static/black_pawn.png',
|
||||||
|
r: '/static/black_rook.png',
|
||||||
|
c: '/static/black_castle.png',
|
||||||
|
b: '/static/black_bishop.png',
|
||||||
|
k: '/static/black_king.png',
|
||||||
|
q: '/static/black_queen.png',
|
||||||
|
|
||||||
|
P: '/static/white_pawn.png',
|
||||||
|
R: '/static/white_rook.png',
|
||||||
|
C: '/static/white_castle.png',
|
||||||
|
B: '/static/white_bishop.png',
|
||||||
|
K: '/static/white_king.png',
|
||||||
|
Q: '/static/white_queen.png',
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadPromises = Object.entries(assets).map(([key, src]) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = src;
|
||||||
|
img.onload = () => resolve({ key, img });
|
||||||
|
img.onerror = () => reject(new Error(`Failed to load ${src}`));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(loadPromises)
|
||||||
|
.then((loadedAssets) => {
|
||||||
|
loadedAssets.forEach(({ key, img }) => {
|
||||||
|
textures[key] = img;
|
||||||
|
});
|
||||||
|
loop();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Failed to load assets:', err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user