mirror of
https://github.com/sigmasternchen/php-chess
synced 2025-03-15 07:58:54 +00:00
feat: Show possible moves for pieces in UI
This commit is contained in:
parent
fa7719141b
commit
8c194f56a3
7 changed files with 117 additions and 12 deletions
|
@ -7,7 +7,7 @@ use Game\Game;
|
|||
$game = Game::fromStartPosition();
|
||||
|
||||
$content = function() use ($game) {
|
||||
require '../src/View/fragments/board.php';
|
||||
require '../src/View/fragments/game.php';
|
||||
};
|
||||
|
||||
require '../src/View/base.php';
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
.square {
|
||||
width: 12.5%;
|
||||
height: 12.5%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.square.black {
|
||||
|
@ -24,11 +25,24 @@
|
|||
background-color: lightgoldenrodyellow;
|
||||
}
|
||||
|
||||
.square.black.hasMoves {
|
||||
.square.movePossible:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
background: green;
|
||||
width: 25%;
|
||||
height: 25%;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.board:not(.moveSelection) .square.black.hasMoves, .square.black.source {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.square.white.hasMoves {
|
||||
.board:not(.moveSelection) .square.white.hasMoves, .square.white.source {
|
||||
background-color: greenyellow;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,16 @@ class Move {
|
|||
return $result;
|
||||
}
|
||||
|
||||
public function toJS() {
|
||||
return join(",", [
|
||||
$this->piece->toJS(),
|
||||
$this->target,
|
||||
$this->captures ?? "",
|
||||
$this->promoteTo?->getShort() ?? "",
|
||||
$this->castleWith ?? ""
|
||||
]);
|
||||
}
|
||||
|
||||
public function __toString(): string {
|
||||
return $this->getLong();
|
||||
}
|
||||
|
|
|
@ -47,6 +47,14 @@ abstract class Piece {
|
|||
return $this->getType()->getShort() . $this->getPosition();
|
||||
}
|
||||
|
||||
public function toJS() {
|
||||
return join("-", [
|
||||
$this->getSide()->getShort(),
|
||||
$this->getType()->getShort(),
|
||||
$this->getPosition()
|
||||
]);
|
||||
}
|
||||
|
||||
private static function getClassForType(PieceType $type): string {
|
||||
switch ($type) {
|
||||
case PieceType::PAWN:
|
||||
|
|
|
@ -13,4 +13,12 @@ enum Side {
|
|||
return Side::WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
public function getShort(): string {
|
||||
if ($this == Side::WHITE) {
|
||||
return "w";
|
||||
} else {
|
||||
return "b";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,11 +4,9 @@ use Game\Game;
|
|||
use Game\Piece;
|
||||
use Game\Position;use Game\Side;
|
||||
|
||||
$game ??= new Game([], \Game\Side::WHITE);
|
||||
$game ??= new Game([], Side::WHITE);
|
||||
|
||||
$current = Side::WHITE;
|
||||
|
||||
if (($current ?? Side::WHITE) == Side::WHITE) {
|
||||
if (($viewSide ?? Side::WHITE) == Side::WHITE) {
|
||||
$start = 7;
|
||||
$end = -1;
|
||||
$dir = -1;
|
||||
|
@ -18,27 +16,36 @@ if (($current ?? Side::WHITE) == Side::WHITE) {
|
|||
$dir = 1;
|
||||
}
|
||||
|
||||
$interactive ??= false;
|
||||
|
||||
global $boardId;
|
||||
$boardId = ($boardId ?? 0) + 1;
|
||||
|
||||
function getImageForPice(Piece $piece): string {
|
||||
return "/static/pieces/" .
|
||||
($piece->getSide() == Side::WHITE ? "w" : "b") .
|
||||
$piece->getSide()->getShort() .
|
||||
$piece->getType()->getShort() .
|
||||
".svg";
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="board">
|
||||
<div class="board <?= $interactive ? "interactive" : "" ?>" id="board<?= $boardId ?>">
|
||||
<?php
|
||||
for($rank = $start; $rank != $end; $rank += $dir) {
|
||||
for($file = $start; $file != $end; $file += $dir) {
|
||||
$position = new Position($file, $rank);
|
||||
$piece = $game->getPiece($position);
|
||||
$moves = $piece ? $game->getMovesForPiece($piece) : [];
|
||||
?>
|
||||
<div class="square <?= strtolower($position->getSquareColor()->name) ?> <?= count($moves) > 0 ? "hasMoves" : "" ?>">
|
||||
$hasMoves = count($moves) > 0;
|
||||
?>
|
||||
<div class="square <?= strtolower($position->getSquareColor()->name) ?> <?= $hasMoves ? "hasMoves" : "" ?> <?= $position ?>">
|
||||
<?php
|
||||
if ($piece) {
|
||||
?>
|
||||
<div class="piece <?= strtolower($piece->getSide()->name) ?>">
|
||||
<div
|
||||
class="piece <?= strtolower($piece->getSide()->name) ?> <?= $hasMoves ? "hasMoves" : "" ?>"
|
||||
data-moves="<?= join(";", array_map(fn($m) => $m->toJS(), $moves)) ?>"
|
||||
>
|
||||
<img
|
||||
alt="<?= strtolower($piece->getSide()->name) ?> <?= strtolower($piece->getType()->name) ?>"
|
||||
src="<?= getImageForPice($piece) ?>"
|
||||
|
@ -53,3 +60,49 @@ function getImageForPice(Piece $piece): string {
|
|||
}
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
if ($interactive) {
|
||||
?>
|
||||
<script>
|
||||
window.addEventListener("load", () => {
|
||||
const board = document.getElementById("board<?= $boardId ?>");
|
||||
const getSquare = square => board.getElementsByClassName(square)[0];
|
||||
const clearSelection = () => {
|
||||
board.classList.remove("moveSelection");
|
||||
board.querySelectorAll(".source").forEach(element => {
|
||||
element.classList.remove("source")
|
||||
});
|
||||
board.querySelectorAll(".movePossible").forEach(element => {
|
||||
element.classList.remove("movePossible")
|
||||
});
|
||||
};
|
||||
const enterSelection = (moves) => {
|
||||
board.classList.add("moveSelection");
|
||||
for (const move of moves) {
|
||||
getSquare(move.target).classList.add("movePossible");
|
||||
getSquare(move.source).classList.add("source");
|
||||
}
|
||||
}
|
||||
const moveSelected = (move) => {
|
||||
// TODO
|
||||
};
|
||||
|
||||
board.querySelectorAll(".piece.hasMoves").forEach(element => {
|
||||
element.addEventListener("click", event => {
|
||||
clearSelection();
|
||||
const moves = element.getAttribute("data-moves").split(";").map(move => ({
|
||||
encoded: move,
|
||||
source: move.split(",")[0].split("-")[2],
|
||||
target: move.split(",")[1]
|
||||
}));
|
||||
enterSelection(moves);
|
||||
event.stopPropagation();
|
||||
});
|
||||
});
|
||||
board.addEventListener("click", () => {
|
||||
clearSelection();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
|
12
src/View/fragments/game.php
Normal file
12
src/View/fragments/game.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
use Game\Game;
|
||||
use Game\Side;
|
||||
|
||||
$game ??= new Game([], Side::WHITE);
|
||||
|
||||
$viewSide ??= Side::WHITE;
|
||||
|
||||
$interactive = true;
|
||||
|
||||
require "board.php";
|
Loading…
Reference in a new issue