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();
|
$game = Game::fromStartPosition();
|
||||||
|
|
||||||
$content = function() use ($game) {
|
$content = function() use ($game) {
|
||||||
require '../src/View/fragments/board.php';
|
require '../src/View/fragments/game.php';
|
||||||
};
|
};
|
||||||
|
|
||||||
require '../src/View/base.php';
|
require '../src/View/base.php';
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
.square {
|
.square {
|
||||||
width: 12.5%;
|
width: 12.5%;
|
||||||
height: 12.5%;
|
height: 12.5%;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.square.black {
|
.square.black {
|
||||||
|
@ -24,11 +25,24 @@
|
||||||
background-color: lightgoldenrodyellow;
|
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;
|
background-color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
.square.white.hasMoves {
|
.board:not(.moveSelection) .square.white.hasMoves, .square.white.source {
|
||||||
background-color: greenyellow;
|
background-color: greenyellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -161,6 +161,16 @@ class Move {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function toJS() {
|
||||||
|
return join(",", [
|
||||||
|
$this->piece->toJS(),
|
||||||
|
$this->target,
|
||||||
|
$this->captures ?? "",
|
||||||
|
$this->promoteTo?->getShort() ?? "",
|
||||||
|
$this->castleWith ?? ""
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function __toString(): string {
|
public function __toString(): string {
|
||||||
return $this->getLong();
|
return $this->getLong();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,14 @@ abstract class Piece {
|
||||||
return $this->getType()->getShort() . $this->getPosition();
|
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 {
|
private static function getClassForType(PieceType $type): string {
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case PieceType::PAWN:
|
case PieceType::PAWN:
|
||||||
|
|
|
@ -13,4 +13,12 @@ enum Side {
|
||||||
return Side::WHITE;
|
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\Piece;
|
||||||
use Game\Position;use Game\Side;
|
use Game\Position;use Game\Side;
|
||||||
|
|
||||||
$game ??= new Game([], \Game\Side::WHITE);
|
$game ??= new Game([], Side::WHITE);
|
||||||
|
|
||||||
$current = Side::WHITE;
|
if (($viewSide ?? Side::WHITE) == Side::WHITE) {
|
||||||
|
|
||||||
if (($current ?? Side::WHITE) == Side::WHITE) {
|
|
||||||
$start = 7;
|
$start = 7;
|
||||||
$end = -1;
|
$end = -1;
|
||||||
$dir = -1;
|
$dir = -1;
|
||||||
|
@ -18,27 +16,36 @@ if (($current ?? Side::WHITE) == Side::WHITE) {
|
||||||
$dir = 1;
|
$dir = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$interactive ??= false;
|
||||||
|
|
||||||
|
global $boardId;
|
||||||
|
$boardId = ($boardId ?? 0) + 1;
|
||||||
|
|
||||||
function getImageForPice(Piece $piece): string {
|
function getImageForPice(Piece $piece): string {
|
||||||
return "/static/pieces/" .
|
return "/static/pieces/" .
|
||||||
($piece->getSide() == Side::WHITE ? "w" : "b") .
|
$piece->getSide()->getShort() .
|
||||||
$piece->getType()->getShort() .
|
$piece->getType()->getShort() .
|
||||||
".svg";
|
".svg";
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<div class="board">
|
<div class="board <?= $interactive ? "interactive" : "" ?>" id="board<?= $boardId ?>">
|
||||||
<?php
|
<?php
|
||||||
for($rank = $start; $rank != $end; $rank += $dir) {
|
for($rank = $start; $rank != $end; $rank += $dir) {
|
||||||
for($file = $start; $file != $end; $file += $dir) {
|
for($file = $start; $file != $end; $file += $dir) {
|
||||||
$position = new Position($file, $rank);
|
$position = new Position($file, $rank);
|
||||||
$piece = $game->getPiece($position);
|
$piece = $game->getPiece($position);
|
||||||
$moves = $piece ? $game->getMovesForPiece($piece) : [];
|
$moves = $piece ? $game->getMovesForPiece($piece) : [];
|
||||||
?>
|
$hasMoves = count($moves) > 0;
|
||||||
<div class="square <?= strtolower($position->getSquareColor()->name) ?> <?= count($moves) > 0 ? "hasMoves" : "" ?>">
|
?>
|
||||||
|
<div class="square <?= strtolower($position->getSquareColor()->name) ?> <?= $hasMoves ? "hasMoves" : "" ?> <?= $position ?>">
|
||||||
<?php
|
<?php
|
||||||
if ($piece) {
|
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
|
<img
|
||||||
alt="<?= strtolower($piece->getSide()->name) ?> <?= strtolower($piece->getType()->name) ?>"
|
alt="<?= strtolower($piece->getSide()->name) ?> <?= strtolower($piece->getType()->name) ?>"
|
||||||
src="<?= getImageForPice($piece) ?>"
|
src="<?= getImageForPice($piece) ?>"
|
||||||
|
@ -53,3 +60,49 @@ function getImageForPice(Piece $piece): string {
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</div>
|
</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