Implement board view based on board builder

landing-page-layout
MiguelMLorente 2024-11-24 15:07:10 +01:00
parent 37a84be3c3
commit d90942624b
5 changed files with 141 additions and 123 deletions

View File

@ -60,14 +60,19 @@ function createBoard(): Cell[][] {
function connectAdjacentCells(board: Cell[][]) {
const indexes = Array.from(Array(boardSize).keys());
for (const rowIndex of indexes.slice(0, -1)) {
for (const colIndex of indexes.slice(0, -1)) {
for (const colIndex of indexes) {
const cell = board[rowIndex][colIndex];
const rightCell = board[rowIndex][colIndex + 1];
const bottomCell = board[rowIndex + 1][colIndex];
cell
.getNodeAt(Direction.SOUTH)
.linkToNode(bottomCell.getNodeAt(Direction.NORTH));
}
}
for (const rowIndex of indexes) {
for (const colIndex of indexes.slice(0, -1)) {
const cell = board[rowIndex][colIndex];
const rightCell = board[rowIndex][colIndex + 1];
cell
.getNodeAt(Direction.EAST)
.linkToNode(rightCell.getNodeAt(Direction.WEST));

View File

@ -4,3 +4,10 @@ export enum Direction {
EAST = "EAST",
WEST = "WEST",
}
export const directions: Direction[] = [
Direction.NORTH,
Direction.SOUTH,
Direction.EAST,
Direction.WEST,
];

View File

@ -15,10 +15,15 @@ export class ExternalNode extends Node {
public linkToNode(other: ExternalNode | Exit) {
this.border = new Border(this, other);
if (other instanceof ExternalNode) {
other.border = this.border;
}
}
public traverseBorder(): ExternalNode | Exit {
if (!this.border) throw Error(`Missing border for node`);
if (!this.border) {
throw Error(`Missing border for node`);
}
return (this.border as Border).traverseFrom(this);
}
}

View File

@ -1,79 +1,125 @@
.game-board {
height: 700px;
width: 700px;
height: 850px;
width: 850px;
display: grid;
grid-template-columns: repeat(11, auto);
grid-template-columns: repeat(7, auto);
gap: auto;
padding: 10px;
padding: 50px;
.cell {
width: 60px;
height: 60px;
width: 100px;
height: 100px;
border: 2px solid black;
border-radius: 10%;
}
.v-exit {
width: 60px;
height: 30px;
> div {
width: 20px;
height: 100%;
margin: auto;
&.house {
background-color: blue;
}
&.university {
background-color: orange;
}
&.factory {
background-color: grey;
}
.exit:has(.exit-road) {
border: solid black;
border-width: 0 1px;
.dotted {
.exit-road {
margin: auto;
width: 0;
height: 100%;
border: dashed black;
border-width: 0 1px;
height: 100%;
transform: translate(calc(50% - 1px));
}
}
.exit:has(.exit-road) {
border: solid black;
border-width: 0 1px;
.exit-road {
margin: auto;
width: 0;
height: 100%;
border: dashed black;
border-width: 0 1px;
transform: translate(calc(50% - 1px));
}
}
&:has(.v-exit-up) {
margin-bottom: -9px;
.exit:has(.exit-rail) {
border-width: 0 1px;
.exit-rail {
margin: auto;
width: 0;
height: 100%;
border: solid black;
border-width: 0 1px;
transform: translate(calc(50% - 1px));
}
}
&:has(.v-exit-down) {
margin-top: -9px;
.exit:has(.exit-ambivalent) {
border-width: 0 1px;
border-style: dotted;
.exit-ambivalent {
margin: auto;
width: 0;
height: 100%;
border: dotted black;
border-width: 0 1px 0 0;
transform: translate(calc(50%));
}
}
}
}
.exit {
position: relative;
width: 20px;
height: 20px;
&:has(.exit-north) {
left: 50%;
transform: translate(calc(-50% - 1px), -100%);
}
&:has(.exit-south) {
left: 50%;
top: 100%;
transform: translate(calc(-50% - 1px), 0%);
}
&:has(.exit-east) {
left: 100%;
top: 50%;
transform: rotate(90deg) translate(-50%, 0);
}
&:has(.exit-west) {
left: 0%;
top: 50%;
transform: rotate(90deg) translate(-50%, 100%);
}
&:has(.exit-north), &:has(.exit-south) {
+ .exit:has(.exit-east) {
left: 100%;
transform: rotate(90deg) translate(-150%, 0);
}
}
.h-exit {
height: 60px;
width: 30px;
> div {
height: 20px;
width: 100%;
margin: auto;
border: solid black;
border-width: 1px 0;
position: relative;
&:has(.exit-north), &:has(.exit-south) {
+ .exit:has(.exit-west) {
top: 50%;
transform: translateY(-50%);
.dotted {
margin: auto;
border: dashed black;
border-width: 1px 0;
width: 100%;
height: 0;
position: relative;
top: 50%;
transform: translateY(-50%);
}
}
&:has(.h-exit-left) {
margin-right: -9px;
}
&:has(.h-exit-right) {
margin-left: -9px;
transform: rotate(90deg) translate(-150%, 100%);
}
}
}

View File

@ -1,76 +1,31 @@
import { buildBoard, Cell, directions, Exit } from "interface";
const GameBoard = () => {
const range = (n: number) => Array.from(Array(n).keys());
const cells = range(11).flatMap((rowIndex) => {
return range(11).map((colIndex) => {
return { rowIndex, colIndex };
});
});
const board: Cell[][] = buildBoard();
return (
<div className="game-board">
{cells.map(({ rowIndex, colIndex }) => {
if (
(rowIndex === 0 || rowIndex === 10) &&
(colIndex === 0 || colIndex === 10)
) {
return <div className="corner" />;
}
if (rowIndex === 0) {
return (
<div className="v-exit">
<div className="v-exit-up">
<div className="dotted" />
</div>
</div>
);
}
if (rowIndex === 10) {
return (
<div className="v-exit">
<div className="v-exit-down">
<div className="dotted" />
</div>
</div>
);
}
if (colIndex === 0) {
return (
<div className="h-exit">
<div className="h-exit-left">
<div className="dotted" />
</div>
</div>
);
}
if (colIndex === 10) {
return (
<div className="h-exit">
<div className="h-exit-right">
<div className="dotted" />
</div>
</div>
);
}
return <div className="cell"></div>;
})}
{board.flatMap((row) =>
row.map((cell) => (
<div className={"cell " + cell.cellType.toLowerCase()}>
{directions.map((direction) => {
const traversedNode = cell.getNodeAt(direction).traverseBorder();
const isExit = traversedNode instanceof Exit;
if (!isExit) return;
const className =
`exit-${direction.toLowerCase()}` +
` exit-${(traversedNode as Exit).type.toLowerCase()}`;
return (
<div className="exit">
<div className={className} />
</div>
);
})}
</div>
)),
)}
</div>
);
/*
{range(9).map(() => (
<div className="v-exit v-exit-up">
<div className="dotted"></div>
</div>
))}
{range(81).map(() => (
<div className="cell"></div>
))}
{range(9).map(() => (
<div className="v-exit v-exit-down">
<div className="dotted"></div>
</div>
))}
*/
};
export default GameBoard;