Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Highlighted legal moves on piece selected #138

Merged
merged 4 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 40 additions & 7 deletions development/code/LogicAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { game } from './Game';
import { isAllowedToAct, onPieceFellOffTheBoard, onPlayerAction } from './logic/PieceLogic';
import { isPlayerAllowedToAct, onPieceFellOffTheBoard, onPlayerAction } from './logic/PieceLogic';
import { comparePositions, convertSquareIdToPosition } from './logic/Utilities';
import { Item } from './logic/items/Items';
import { Piece } from './logic/pieces/Pieces';
import { Position, Square } from './logic/pieces/PiecesUtilities';
import { BaseRule } from './logic/rules/BaseRule';
import { destroyElementOnBoard, moveElementOnBoard, spawnItemElementOnBoard, spawnPieceElementOnBoard } from './ui/BoardManager';
import { destroyElementOnBoard, getAllSquareElements, getSquareElementById, highlightSquare, moveElementOnBoard, spawnItemElementOnBoard, spawnPieceElementOnBoard } from './ui/BoardManager';
import { renderPlayersInformation, renderNewRule } from './ui/Screen';

export function renderScreen() {
Expand All @@ -22,7 +22,7 @@ function findPieceAtPosition(
return game.getPieces().find((piece) => comparePositions(piece.position, position));
}

function getSquareIdFromElement(element: HTMLElement): string | undefined {
function getSquareIdByElement(element: HTMLElement): string | undefined {
while (element && !element.getAttribute('square-id')) {
element = element.parentElement as HTMLElement;
}
Expand All @@ -41,14 +41,14 @@ export function onActionTriggered(
targetElement: HTMLElement,
boardId: string,
) {
const originSquareId = getSquareIdFromElement(draggedElement);
const originSquareId = getSquareIdByElement(draggedElement);
if (!originSquareId) return;

const draggedElementPosition = getPositionFromSquareId(originSquareId, boardId);
const draggedPiece = findPieceAtPosition(draggedElementPosition);
if (!draggedPiece) return;

const targetSquareId = getSquareIdFromElement(targetElement);
const targetSquareId = getSquareIdByElement(targetElement);
if (!targetSquareId) return;

const targetElementPosition = getPositionFromSquareId(targetSquareId, boardId);
Expand Down Expand Up @@ -76,16 +76,49 @@ export function onFellOffTheBoardTriggered(
draggedElement: HTMLElement,
boardId: string,
) {
const squareId = getSquareIdFromElement(draggedElement);
const squareId = getSquareIdByElement(draggedElement);
if (!squareId) return;

const draggedElementPosition = getPositionFromSquareId(squareId, boardId);
const draggedPiece = findPieceAtPosition(draggedElementPosition);
if (!draggedPiece || !isAllowedToAct(draggedPiece)) return;
if (!draggedPiece || !isPlayerAllowedToAct(draggedPiece)) return;

onPieceFellOffTheBoard(draggedPiece);
}

function highlightLegalMoves(
piece: Piece,
pieceElement: HTMLElement,
boardId: string,
) {
// Remove all highlights
const allSquareElements = getAllSquareElements(boardId);
for (const squareElement of allSquareElements) {
highlightSquare(squareElement, false, false);
}

const legalMoves = piece.getLegalMoves();
for (const position of legalMoves) {
const positionSquareId = position.coordinates.join(',');
const squareElement = getSquareElementById(positionSquareId, boardId) as HTMLElement;
highlightSquare(squareElement, true, false);
}
}

export function onPieceSelected(
pieceElement: HTMLElement,
boardId: string,
) {
const squareId = getSquareIdByElement(pieceElement);
if (!squareId) return;

const pieceElementPosition = getPositionFromSquareId(squareId, boardId);
const piece = findPieceAtPosition(pieceElementPosition);
if (!piece || !isPlayerAllowedToAct(piece)) return;

highlightLegalMoves(piece, pieceElement, boardId);
}

export function movePieceOnBoard(
draggedPiece: Piece,
targetSquare: Square,
Expand Down
3 changes: 3 additions & 0 deletions development/code/logic/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export const LIGHT_HEAVEN_SQUARE_COLOR = 'water-background';
export const DARK_HEAVEN_SQUARE_COLOR = 'blue-background';
export const GRAY_SQUARE_COLOR = 'light-gray-background';

export const MOUSE_HIGHLIGHT_CLASS = 'mouse-highlight';
export const SELECTED_PIECE_CLASS = 'selected-piece';

export const NOTATIONS_LETTERS = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
export const NOTATIONS_NUMBERS = ['8', '7', '6', '5', '4', '3', '2', '1'];
export const BOARD_WIDTH = 8;
4 changes: 2 additions & 2 deletions development/code/logic/PieceLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function validatePlayerAction(
draggedPiece: Piece,
target: Piece | Square | Item,
): boolean {
if (!isAllowedToAct(draggedPiece)) return false;
if (!isPlayerAllowedToAct(draggedPiece)) return false;
if (draggedPiece === target) return false;
if (draggedPiece.position.boardId !== target.position.boardId) return false;

Expand Down Expand Up @@ -144,7 +144,7 @@ function castle(
return true;
}

export function isAllowedToAct(draggedPiece: Piece) {
export function isPlayerAllowedToAct(draggedPiece: Piece) {
return draggedPiece.player === game.getCurrentPlayer();
}

Expand Down
66 changes: 51 additions & 15 deletions development/code/ui/BoardManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
DARK_HEAVEN_SQUARE_COLOR,
DARK_HELL_SQUARE_COLOR,
DARK_OVERWORLD_SQUARE_COLOR,
GRAY_SQUARE_COLOR,
GRAY_SQUARE_COLOR as LIGHT_GRAY_SQUARE_COLOR,
HEAVEN_BOARD_BUTTON_ID,
HEAVEN_BOARD_ID,
HELL_BOARD_BUTTON_ID,
Expand All @@ -14,6 +14,7 @@ import {
LIGHT_HEAVEN_SQUARE_COLOR,
LIGHT_HELL_SQUARE_COLOR,
LIGHT_OVERWORLD_SQUARE_COLOR,
MOUSE_HIGHLIGHT_CLASS,
NOTATIONS_LETTERS,
NOTATIONS_NUMBERS,
OVERWORLD_BOARD_BUTTON_ID,
Expand Down Expand Up @@ -83,6 +84,14 @@ function getBoardbyId(boardId: string): ChessBoard {
}
}

export function getAllSquareElements(boardId: string): Array<HTMLElement> {
const board = getBoardbyId(boardId);
const boardElement = board.boardElement;

const squares = boardElement.querySelectorAll('[square-id]');
return Array.from(squares) as Array<HTMLElement>;
}

export function createNotationGraphics(notation: string) {
const notationElement = document.createElement('p');
notationElement.classList.add('notation');
Expand All @@ -97,19 +106,27 @@ export function createNotationGraphics(notation: string) {
}
}

export function getSquareElementById(
squareId: string,
boardId: string,
): HTMLElement | undefined {
const board = getBoardbyId(boardId);
return board.boardElement.querySelector(`[square-id="${squareId}"]`) as HTMLElement;
}

export function moveElementOnBoard(
boardId: string,
originSquareId: string,
targetSquareId: string,
) {
const board = getBoardbyId(boardId);

const movedElementSquareElement = board.boardElement.querySelector(`[square-id="${originSquareId}"]`) as HTMLElement;
const targetSquareElement = getSquareElementById(targetSquareId, boardId);
const movedElementSquareElement = getSquareElementById(originSquareId, boardId);
const movedElement = movedElementSquareElement?.firstElementChild as HTMLElement;

const targetSquareElement = board.boardElement.querySelector(`[square-id="${targetSquareId}"]`) as HTMLElement;

board.moveElementOnBoard(movedElement, targetSquareElement);
if (targetSquareElement && movedElementSquareElement) {
const board = getBoardbyId(boardId);
board.moveElementOnBoard(movedElement, targetSquareElement);
}
}

export function destroyElementOnBoard(targetSquareId: string, boardId: string) {
Expand Down Expand Up @@ -141,16 +158,35 @@ export function spawnItemElementOnBoard(item: Item, targetSquareId: string) {
board.spawnElementOnBoard(pieceElement, squareElement);
}

export function highlightSquare(target: HTMLElement, shouldHighlight: boolean) {
while (!target.classList.contains('square')) {
target = target.parentNode as HTMLElement;
function findSquareElement(element: HTMLElement): HTMLElement | undefined {
while (element && !element.classList.contains('square')) {
element = element.parentNode as HTMLElement;
}

if (target.classList.contains('square')) {
if (shouldHighlight) {
target.classList.add(GRAY_SQUARE_COLOR);

return element && element.classList.contains('square') ? element : undefined;
}

export function highlightSquare(targetElement: HTMLElement, shouldAddHighlight: boolean, isMouseHighlight: boolean) {
const squareElement = findSquareElement(targetElement);

if (squareElement) {
if (shouldAddHighlight) {
if (isMouseHighlight && !targetElement.classList.contains(LIGHT_GRAY_SQUARE_COLOR)) {
targetElement.classList.add(MOUSE_HIGHLIGHT_CLASS);
}

targetElement.classList.add(LIGHT_GRAY_SQUARE_COLOR);
} else {
target.classList.remove(GRAY_SQUARE_COLOR);
const shouldRemoveMouseHighlight = isMouseHighlight && targetElement.classList.contains(MOUSE_HIGHLIGHT_CLASS);
const shouldRemoveHighlight = !isMouseHighlight || shouldRemoveMouseHighlight;

if (shouldRemoveMouseHighlight) {
targetElement.classList.remove(MOUSE_HIGHLIGHT_CLASS);
}

if (shouldRemoveHighlight) {
targetElement.classList.remove(LIGHT_GRAY_SQUARE_COLOR);
}
}
}
}
Expand Down
55 changes: 40 additions & 15 deletions development/code/ui/Events.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { onPieceSelected } from '../LogicAdapter';
import { HEAVEN_BOARD_BUTTON_ID, HELL_BOARD_BUTTON_ID, OVERWORLD_BOARD_BUTTON_ID } from '../logic/Constants';
import { HEAVEN_BOARD, HELL_BOARD, OVERWORLD_BOARD } from './BoardManager';

Expand All @@ -19,17 +20,19 @@ const OVERWORLD_BOARD_BUTTON = document.getElementById(
const HELL_BOARD_BUTTON = document.getElementById(HELL_BOARD_BUTTON_ID);
const HEAVEN_BOARD_BUTTON = document.getElementById(HEAVEN_BOARD_BUTTON_ID);

let triggerOnHighlight: (target: HTMLElement, shouldHighlight: boolean) => void;
let triggerOnHighlight: (target: HTMLElement, shouldAddHighlight: boolean, isMouseHighlight: boolean) => void;

export function initializeEventListeners() {
const squares = document.querySelectorAll('.square');
// Listen for mouse events
squares.forEach((square) => {
squares.forEach(square => {
square.addEventListener('dragstart', onDragStart);
square.addEventListener('dragover', onDragOver);
square.addEventListener('drop', onDragDrop);
square.addEventListener('mouseover', onMouseOver);
square.addEventListener('mouseout', onMouseOut);

square.addEventListener('click', onMouseClick);
});

// Support pieces falling off the board
Expand Down Expand Up @@ -57,30 +60,30 @@ function onDragDrop(event: Event) {
targetElement = targetElement.parentNode as HTMLElement;
}

let board = targetElement as HTMLElement;
while (!board.classList.contains('board')) {
board = board.parentNode as HTMLElement;
let boardElement = targetElement as HTMLElement;
while (!boardElement.classList.contains('board')) {
boardElement = boardElement.parentNode as HTMLElement;
}

triggerOnAction(draggedElement, targetElement, board.id);
triggerOnAction(draggedElement, targetElement, boardElement.id);
}

function onDragOver(event: Event) {
event.preventDefault();
}

function onDragOffTheBoard(_: Event) {
let board = draggedElement;
while (!board.classList.contains('board')) {
board = board.parentNode as HTMLElement;
let boardElement = draggedElement;
while (!boardElement.classList.contains('board')) {
boardElement = boardElement.parentNode as HTMLElement;
}

triggerOnFellOffTheBoard(draggedElement, board.id);
triggerOnFellOffTheBoard(draggedElement, boardElement.id);
}

function handleMouseEvents(event: Event, shouldHighlight: boolean) {
const target = event.target as HTMLElement;
triggerOnHighlight(target, shouldHighlight);
function handleMouseEvents(event: Event, shouldAddHighlight: boolean) {
const targetElement = event.target as HTMLElement;
triggerOnHighlight(targetElement, shouldAddHighlight, true);
}

function onMouseOver(event: Event) {
Expand All @@ -91,6 +94,28 @@ function onMouseOut(event: Event) {
handleMouseEvents(event, false);
}

function onMouseClick(event: Event) {
let targetElement = event.target as HTMLElement;
let boardElement = targetElement;

// Make sure target is not a resource
while (targetElement.classList.contains('untargetable')) {
targetElement = targetElement.parentNode as HTMLElement;
}

if (!targetElement.classList.contains('piece')) {
const firstChild = targetElement.firstChild as HTMLElement;
if (firstChild.classList.contains('piece')) targetElement = firstChild;
else return;
}

while (!boardElement.classList.contains('board')) {
boardElement = boardElement.parentNode as HTMLElement;
}

onPieceSelected(targetElement, boardElement.id);
}

export function setOnAction(
_triggerOnAction: (
draggedElement: HTMLElement,
Expand All @@ -104,14 +129,14 @@ export function setOnAction(
export function setOnFellOffTheBoard(
_triggerOnFellOffTheBoard: (
draggedElement: HTMLElement,
board: string,
boardId: string,
) => void,
) {
triggerOnFellOffTheBoard = _triggerOnFellOffTheBoard;
}

export function setOnHighlight(
_triggerOnHighlight: (target: HTMLElement, shouldHighlight: boolean) => void,
_triggerOnHighlight: (target: HTMLElement, shouldAddHighlight: boolean, isMouseHighlight: boolean) => void,
) {
triggerOnHighlight = _triggerOnHighlight;
}
Expand Down
13 changes: 12 additions & 1 deletion development/styles/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,18 @@ path {
}

.light-gray-background {
background-color: #e6e6e6;
position: relative;
}

.light-gray-background::before {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(230, 230, 230, 0.5);
z-index: 1;
}

.black {
Expand Down
Loading