Skip to content
Open
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
253 changes: 131 additions & 122 deletions reactjs-projects/chess-app/src/components/Chessboard/Chessboard.tsx
Original file line number Diff line number Diff line change
@@ -1,137 +1,146 @@
import { useRef, useState } from "react";
import "./Chessboard.css";
import Tile from "../Tile/Tile";
import {
VERTICAL_AXIS,
HORIZONTAL_AXIS,
GRID_SIZE,
} from "../../Constants";
import { VERTICAL_AXIS, HORIZONTAL_AXIS, GRID_SIZE } from "../../Constants";
import { Piece, Position } from "../../models";

interface Props {
playMove: (piece: Piece, position: Position) => boolean;
pieces: Piece[];
playMove: (piece: Piece, position: Position) => boolean;
pieces: Piece[];
}

export default function Chessboard({playMove, pieces} : Props) {
const [activePiece, setActivePiece] = useState<HTMLElement | null>(null);
const [grabPosition, setGrabPosition] = useState<Position>(new Position(-1, -1));
const chessboardRef = useRef<HTMLDivElement>(null);

function grabPiece(e: React.MouseEvent) {
const element = e.target as HTMLElement;
const chessboard = chessboardRef.current;
if (element.classList.contains("chess-piece") && chessboard) {
const grabX = Math.floor((e.clientX - chessboard.offsetLeft) / GRID_SIZE);
const grabY = Math.abs(
Math.ceil((e.clientY - chessboard.offsetTop - 800) / GRID_SIZE)
);
setGrabPosition(new Position(grabX, grabY));

const x = e.clientX - GRID_SIZE / 2;
const y = e.clientY - GRID_SIZE / 2;
element.style.position = "absolute";
element.style.left = `${x}px`;
element.style.top = `${y}px`;

setActivePiece(element);
}
}

function movePiece(e: React.MouseEvent) {
const chessboard = chessboardRef.current;
if (activePiece && chessboard) {
const minX = chessboard.offsetLeft - 25;
const minY = chessboard.offsetTop - 25;
const maxX = chessboard.offsetLeft + chessboard.clientWidth - 75;
const maxY = chessboard.offsetTop + chessboard.clientHeight - 75;
const x = e.clientX - 50;
const y = e.clientY - 50;
activePiece.style.position = "absolute";

//If x is smaller than minimum amount
if (x < minX) {
activePiece.style.left = `${minX}px`;
}
//If x is bigger than maximum amount
else if (x > maxX) {
activePiece.style.left = `${maxX}px`;
}
//If x is in the constraints
else {
activePiece.style.left = `${x}px`;
}

//If y is smaller than minimum amount
if (y < minY) {
activePiece.style.top = `${minY}px`;
}
//If y is bigger than maximum amount
else if (y > maxY) {
activePiece.style.top = `${maxY}px`;
}
//If y is in the constraints
else {
activePiece.style.top = `${y}px`;
}
}
}

function dropPiece(e: React.MouseEvent) {
const chessboard = chessboardRef.current;
if (activePiece && chessboard) {
const x = Math.floor((e.clientX - chessboard.offsetLeft) / GRID_SIZE);
const y = Math.abs(
Math.ceil((e.clientY - chessboard.offsetTop - 800) / GRID_SIZE)
);

const currentPiece = pieces.find((p) =>
p.samePosition(grabPosition)
);

if (currentPiece) {
var succes = playMove(currentPiece.clone(), new Position(x, y));

if(!succes) {
//RESETS THE PIECE POSITION
activePiece.style.position = "relative";
activePiece.style.removeProperty("top");
activePiece.style.removeProperty("left");
export default function Chessboard({ playMove, pieces }: Props) {
const [activePiece, setActivePiece] = useState<HTMLElement | null>(null);
const [grabPosition, setGrabPosition] = useState<Position>(
new Position(-1, -1)
);
const chessboardRef = useRef<HTMLDivElement>(null);

function grabPiece(e: React.MouseEvent) {
const element = e.target as HTMLElement;
const chessboard = chessboardRef.current;
if (element.classList.contains("chess-piece") && chessboard) {
const grabX = Math.floor(
(e.clientX - chessboard.offsetLeft) / GRID_SIZE
);
const grabY = Math.abs(
Math.ceil((e.clientY - chessboard.offsetTop - 800) / GRID_SIZE)
);
setGrabPosition(new Position(grabX, grabY));

const x = e.clientX - GRID_SIZE / 2;
const y = e.clientY - GRID_SIZE / 2;
element.style.position = "absolute";
element.style.left = `${x}px`;
element.style.top = `${y}px`;

setActivePiece(element);
}
}
setActivePiece(null);
}
}

let board = [];

for (let j = VERTICAL_AXIS.length - 1; j >= 0; j--) {
for (let i = 0; i < HORIZONTAL_AXIS.length; i++) {
const number = j + i + 2;
const piece = pieces.find((p) =>
p.samePosition(new Position(i, j))
);
let image = piece ? piece.image : undefined;
function movePiece(e: React.MouseEvent) {
const chessboard = chessboardRef.current;
if (activePiece && chessboard) {
const minX = chessboard.offsetLeft - 25;
const minY = chessboard.offsetTop - 25;
const maxX = chessboard.offsetLeft + chessboard.clientWidth - 75;
const maxY = chessboard.offsetTop + chessboard.clientHeight - 75;
const x = e.clientX - 50;
const y = e.clientY - 50;
activePiece.style.position = "absolute";

//If x is smaller than minimum amount
if (x < minX) {
activePiece.style.left = `${minX}px`;
}
//If x is bigger than maximum amount
else if (x > maxX) {
activePiece.style.left = `${maxX}px`;
}
//If x is in the constraints
else {
activePiece.style.left = `${x}px`;
}

//If y is smaller than minimum amount
if (y < minY) {
activePiece.style.top = `${minY}px`;
}
//If y is bigger than maximum amount
else if (y > maxY) {
activePiece.style.top = `${maxY}px`;
}
//If y is in the constraints
else {
activePiece.style.top = `${y}px`;
}
}
}

let currentPiece = activePiece != null ? pieces.find(p => p.samePosition(grabPosition)) : undefined;
let highlight = currentPiece?.possibleMoves ?
currentPiece.possibleMoves.some(p => p.samePosition(new Position(i, j))) : false;
function dropPiece(e: React.MouseEvent) {
const chessboard = chessboardRef.current;
if (activePiece && chessboard) {
const x = Math.floor(
(e.clientX - chessboard.offsetLeft) / GRID_SIZE
);
const y = Math.abs(
Math.ceil((e.clientY - chessboard.offsetTop - 800) / GRID_SIZE)
);

const currentPiece = pieces.find((p) =>
p.samePosition(grabPosition)
);

if (currentPiece) {
var succes = playMove(currentPiece.clone(), new Position(x, y));

if (!succes) {
//RESETS THE PIECE POSITION
activePiece.style.position = "relative";
activePiece.style.removeProperty("top");
activePiece.style.removeProperty("left");
}
}
setActivePiece(null);
}
}

board.push(<Tile key={`${j},${i}`} image={image} number={number} highlight={highlight} />);
let board = [];

for (let j = VERTICAL_AXIS.length - 1; j >= 0; j--) {
for (let i = 0; i < HORIZONTAL_AXIS.length; i++) {
const piece = pieces.find((p) =>
p.samePosition(new Position(i, j))
);
let image = piece ? piece.image : undefined;

let currentPiece =
activePiece != null
? pieces.find((p) => p.samePosition(grabPosition))
: undefined;
let highlight = currentPiece?.possibleMoves
? currentPiece.possibleMoves.some((p) =>
p.samePosition(new Position(i, j))
)
: false;

board.push(
<Tile key={`${j},${i}`} image={image} highlight={highlight} />
);
}
}
}

return (
<>
<div
onMouseMove={(e) => movePiece(e)}
onMouseDown={(e) => grabPiece(e)}
onMouseUp={(e) => dropPiece(e)}
id="chessboard"
ref={chessboardRef}
>
{board}
</div>
</>
);

return (
<>
<div
onMouseMove={(e) => movePiece(e)}
onMouseDown={(e) => grabPiece(e)}
onMouseUp={(e) => dropPiece(e)}
id="chessboard"
ref={chessboardRef}
>
{board}
</div>
</>
);
}
22 changes: 13 additions & 9 deletions reactjs-projects/chess-app/src/components/Tile/Tile.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
place-content: center;
width: 100px;
height: 100px;
background-color: #779556;
}

.tile:nth-child(16n + 1),
.tile:nth-child(16n + 3),
.tile:nth-child(16n + 5),
.tile:nth-child(16n + 7),
.tile:nth-child(16n + 10),
.tile:nth-child(16n + 12),
.tile:nth-child(16n + 14),
.tile:nth-child(16n + 16) {
background-color: #ebecd0;
}

.tile .chess-piece {
Expand All @@ -21,14 +33,6 @@
cursor: grabbing;
}

.black-tile {
background-color: #779556;
}

.white-tile {
background-color: #ebecd0;
}

.tile img {
width: 80px;
}
Expand All @@ -48,4 +52,4 @@
height: 90px;
border: 5px solid rgba(0, 0, 0, 0.4);
border-radius: 50%;
}
}
35 changes: 18 additions & 17 deletions reactjs-projects/chess-app/src/components/Tile/Tile.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import "./Tile.css";

interface Props {
image?: string;
number: number;
highlight: boolean;
image?: string;
highlight: boolean;
}

export default function Tile({ number, image, highlight }: Props) {
const className: string = ["tile",
number % 2 === 0 && "black-tile",
number % 2 !== 0 && "white-tile",
highlight && "tile-highlight",
image && "chess-piece-tile"].filter(Boolean).join(' ');


return (
<div className={className}>
{image && <div style={{ backgroundImage: `url(${image})` }} className="chess-piece"></div>}
</div>
);
}
export default function Tile({ image, highlight }: Props) {
return (
<div
className={`tile ${highlight && "tile-highlight"} ${
image && "chess-piece-tile"
}`}
>
{image && (
<div
style={{ backgroundImage: `url(${image})` }}
className="chess-piece"
></div>
)}
</div>
);
}