Add pawn promotion
This commit is contained in:
@@ -26,6 +26,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="promotionModal" style="display: none;">
|
||||||
|
<p>Promote your pawn to:</p>
|
||||||
|
<div id="promotionBtnContainer">
|
||||||
|
<button onclick="selectPromotion(4)">
|
||||||
|
<img src="/images/Chess Images/WhiteQueen.svg" alt="Queen" />
|
||||||
|
</button>
|
||||||
|
<button onclick="selectPromotion(1)">
|
||||||
|
<img src="/images/Chess Images/WhiteRook.svg" alt="Rook" />
|
||||||
|
</button>
|
||||||
|
<button onclick="selectPromotion(3)">
|
||||||
|
<img src="/images/Chess Images/WhiteBishop.svg" alt="Bishop" />
|
||||||
|
</button>
|
||||||
|
<button onclick="selectPromotion(2)">
|
||||||
|
<img src="/images/Chess Images/WhiteKnight.svg" alt="Knight" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
<script src="~/js/signalr/signalr.min.js"></script>
|
<script src="~/js/signalr/signalr.min.js"></script>
|
||||||
<script src="~/js/ChessScripts/chessLogic.js"></script>
|
<script src="~/js/ChessScripts/chessLogic.js"></script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@{
|
@{
|
||||||
Layout = null;
|
Layout = null;
|
||||||
ViewData["cssVersion"] = "1.0.1"; // <--- change this once to bust cache
|
ViewData["cssVersion"] = "1.0.2"; // <--- change this once to bust cache
|
||||||
}
|
}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
|||||||
@@ -33,10 +33,16 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chessSquare.legal {
|
.legalOverlay {
|
||||||
border: 4px dashed red;
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none; /* Let clicks go through */
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
cursor: pointer;
|
border: 4px dashed red;
|
||||||
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
#chessBoard.flipped {
|
#chessBoard.flipped {
|
||||||
@@ -46,9 +52,58 @@
|
|||||||
.chessSquare.previous-start {
|
.chessSquare.previous-start {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 4px solid #ffd700; /* gold or whatever you like */
|
border: 4px solid #ffd700; /* gold or whatever you like */
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chessSquare.previous-end {
|
.chessSquare.previous-end {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
border: 4px solid #ff8c00; /* orange */
|
border: 4px solid #ff8c00; /* orange */
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#promotionModal {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 0 20px rgba(0,0,0,0.6);
|
||||||
|
color: white;
|
||||||
|
z-index: 1000;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#promotionModal p {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#promotionBtnContainer {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#promotionBtnContainer button {
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
border: none;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
#promotionBtnContainer button:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
background-color: #3a3a3a;
|
||||||
|
}
|
||||||
|
|
||||||
|
#promotionBtnContainer img {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
pointer-events: none; /* ensures img doesn't steal the click */
|
||||||
}
|
}
|
||||||
@@ -137,6 +137,10 @@ function highlightLegalMoves(moves) {
|
|||||||
const img = square.querySelector("img");
|
const img = square.querySelector("img");
|
||||||
if (img) img.onclick = null;
|
if (img) img.onclick = null;
|
||||||
|
|
||||||
|
let overlay = document.createElement("div");
|
||||||
|
overlay.className = "legalOverlay";
|
||||||
|
square.appendChild(overlay);
|
||||||
|
|
||||||
// Let the square itself handle the move
|
// Let the square itself handle the move
|
||||||
square.onclick = () => handleMove(r, c);
|
square.onclick = () => handleMove(r, c);
|
||||||
});
|
});
|
||||||
@@ -145,6 +149,18 @@ function highlightLegalMoves(moves) {
|
|||||||
async function handleMove(targetRow, targetCol) {
|
async function handleMove(targetRow, targetCol) {
|
||||||
if (!selectedPiece) return;
|
if (!selectedPiece) return;
|
||||||
|
|
||||||
|
const isPawn = selectedPiece.type === 0; // Assuming 0 = pawn
|
||||||
|
const reachedEnd = (Number(selectedPiece.color) === 0 && Number(targetRow) === 0) ||
|
||||||
|
(Number(selectedPiece.color) === 1 && Number(targetRow) === 0);
|
||||||
|
|
||||||
|
let choice = null;
|
||||||
|
|
||||||
|
if (isPawn && reachedEnd) {
|
||||||
|
// Show promotion UI
|
||||||
|
choice = await promptPromotion(); // function you’ll define
|
||||||
|
if (!choice) return; // user cancelled?
|
||||||
|
}
|
||||||
|
|
||||||
[targetRow, targetCol] = flipCoordinates(targetRow, targetCol);
|
[targetRow, targetCol] = flipCoordinates(targetRow, targetCol);
|
||||||
|
|
||||||
const moveDto = {
|
const moveDto = {
|
||||||
@@ -155,7 +171,7 @@ async function handleMove(targetRow, targetCol) {
|
|||||||
SourceCol: selectedPiece.col,
|
SourceCol: selectedPiece.col,
|
||||||
TargetRow: targetRow,
|
TargetRow: targetRow,
|
||||||
TargetCol: targetCol,
|
TargetCol: targetCol,
|
||||||
PromotionChoice: null // optional
|
PromotionChoice: choice
|
||||||
};
|
};
|
||||||
|
|
||||||
previousMoveStart = [selectedPiece.row, selectedPiece.col];
|
previousMoveStart = [selectedPiece.row, selectedPiece.col];
|
||||||
@@ -190,6 +206,10 @@ function clearHighlights() {
|
|||||||
for (let i = 0; i < 64; i++) {
|
for (let i = 0; i < 64; i++) {
|
||||||
const square = document.getElementById(`square-${i}`);
|
const square = document.getElementById(`square-${i}`);
|
||||||
|
|
||||||
|
// Remove legal overlays
|
||||||
|
const overlay = square.querySelector(".legalOverlay");
|
||||||
|
if (overlay) square.removeChild(overlay);
|
||||||
|
|
||||||
// Remove legal move markers and their onclicks
|
// Remove legal move markers and their onclicks
|
||||||
if (square.classList.contains("legal")) {
|
if (square.classList.contains("legal")) {
|
||||||
square.classList.remove("legal");
|
square.classList.remove("legal");
|
||||||
@@ -273,6 +293,32 @@ async function setupSignalRConnection() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function promptPromotion() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
|
||||||
|
let color = 1;
|
||||||
|
if (currentPlayerIsWhite)
|
||||||
|
color = 0;
|
||||||
|
|
||||||
|
updatePromotionModalImages(color);
|
||||||
|
|
||||||
|
document.getElementById("promotionModal").style.display = "block";
|
||||||
|
window.selectPromotion = (piece) => {
|
||||||
|
document.getElementById("promotionModal").style.display = "none";
|
||||||
|
resolve(piece);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePromotionModalImages(color) {
|
||||||
|
const pieceNames = ["Queen", "Rook", "Bishop", "Knight"];
|
||||||
|
const buttons = document.querySelectorAll("#promotionModal button img");
|
||||||
|
|
||||||
|
buttons.forEach((img, index) => {
|
||||||
|
img.src = `/images/Chess Images/${color === 0 ? "White" : "Black"}${pieceNames[index]}.svg`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
console.log("chessLogic.js loaded");
|
console.log("chessLogic.js loaded");
|
||||||
window.startNewGame = startNewGame;
|
window.startNewGame = startNewGame;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user