COrner and road selection is possible
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
ade3bb0830
commit
63a41723be
@ -30,5 +30,61 @@
|
||||
.Pip {
|
||||
position: absolute;
|
||||
background-size: 600% auto; /* pip-numbers is a 6x6 grid of pip images */
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
transform: translate(-50%, -50%);
|
||||
clip-path: circle(48%);
|
||||
}
|
||||
|
||||
.Roads[disabled],
|
||||
.Corners[disabled] {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.Corner {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid transparent;
|
||||
/* border: 2px solid black;*/
|
||||
border-radius: 50%;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.Corner .Option {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.Corner:hover {
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
.Road {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-items: center;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid transparent;
|
||||
/* border: 2px solid black; */
|
||||
transform-origin: 50% 0;
|
||||
width: 1.75em;
|
||||
height: 2.5em;
|
||||
}
|
||||
|
||||
.Road .Option {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.Road:hover {
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
.Selected {
|
||||
background-color: rgba(255, 238, 0, 0.5);
|
||||
box-shadow: 5px 5px 5px black;
|
||||
}
|
@ -5,32 +5,218 @@ const base = process.env.PUBLIC_URL;
|
||||
const assetsPath = `${base}/assets`;
|
||||
|
||||
const Board = ({ game }) => {
|
||||
const rows = [3, 4, 5, 4, 3];
|
||||
const rows = [3, 4, 5, 4, 3, 2]; /* The final row of 2 is to place roads and corners */
|
||||
const [signature, setSignature] = useState("");
|
||||
const [pips, setPips] = useState(<></>);
|
||||
const [borders, setBorders] = useState(<></>);
|
||||
const [tiles, setTiles] = useState(<></>);
|
||||
const [corners, setCorners] = useState(<></>);
|
||||
const [roads, setRoads] = useState(<></>);
|
||||
|
||||
const [transform, setTransform] = useState(1);
|
||||
|
||||
const scale = 1;
|
||||
const
|
||||
hexRatio = 1.1547,
|
||||
tileWidth = scale * 67,
|
||||
tileWidth = 67,
|
||||
tileHalfWidth = tileWidth * 0.5,
|
||||
tileHeight = tileWidth * hexRatio,
|
||||
borderOffset = scale * 86; /* ~1/10th border image width... hand tuned */
|
||||
tileHalfHeight = tileHeight * 0.5,
|
||||
radius = tileHeight * 2,
|
||||
borderOffset = 86; /* ~1/10th border image width... hand tuned */
|
||||
|
||||
/* Actual sizing */
|
||||
const
|
||||
tileImageWidth = scale * 90, /* Based on hand tuned and image width */
|
||||
tileImageWidth = 90, /* Based on hand tuned and image width */
|
||||
tileImageHeight = tileImageWidth/hexRatio,
|
||||
borderImageWidth = (2 + 2/3) * tileImageWidth, /* 2.667 * .Tile.width */
|
||||
borderImageHeight = borderImageWidth * 0.29; /* 0.29 * .Border.height */
|
||||
|
||||
const Road = ({road}) => {
|
||||
const onClick = (event) => {
|
||||
console.log(`Road clicked: ${road.index}`);
|
||||
const nodes = document.querySelectorAll('.Road.Selected');
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const el = nodes[i];
|
||||
if (el !== event.target) {
|
||||
el.classList.remove('Selected');
|
||||
}
|
||||
}
|
||||
event.target.classList.toggle('Selected');
|
||||
};
|
||||
return <div className="Road"
|
||||
onClick={onClick}
|
||||
style={{
|
||||
transform: `translate(-50%, -50%) rotate(${road.angle}deg)`,
|
||||
top: `${road.top}px`,
|
||||
left: `${road.left}px`
|
||||
}}
|
||||
/>;
|
||||
};
|
||||
|
||||
const Corner = ({corner}) => {
|
||||
const onClick = (event) => {
|
||||
console.log(`Corner clicked: ${corner.index}`);
|
||||
const nodes = document.querySelectorAll('.Corner.Selected');
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const el = nodes[i];
|
||||
if (el !== event.target) {
|
||||
el.classList.remove('Selected');
|
||||
}
|
||||
}
|
||||
event.target.classList.toggle('Selected');
|
||||
};
|
||||
return <div className="Corner"
|
||||
onClick={onClick}
|
||||
style={{
|
||||
top: `${corner.top}px`,
|
||||
left: `${corner.left}px`
|
||||
}}
|
||||
/>;
|
||||
};
|
||||
|
||||
const generateRoads = () => {
|
||||
let row = 0, rowCount = 0;
|
||||
let y = -2.5 + tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||
x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
|
||||
|
||||
let index = 0;
|
||||
let road;
|
||||
|
||||
const corners = [];
|
||||
|
||||
for (let i = 0; i < 21; i++) {
|
||||
const lastRow = row === rows.length - 1;
|
||||
if (row > 2 && rowCount === 0) {
|
||||
road = {
|
||||
index: index++,
|
||||
angle: -60,
|
||||
top: y-0.5*tileHalfHeight,
|
||||
left: x-tileHalfHeight
|
||||
};
|
||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||
}
|
||||
|
||||
road = {
|
||||
index: index++,
|
||||
angle: 240,
|
||||
top: y,
|
||||
left: x
|
||||
};
|
||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||
|
||||
road = {
|
||||
index: index++,
|
||||
angle: -60,
|
||||
top: y-0.5*tileHalfHeight,
|
||||
left: x+tileHalfHeight
|
||||
};
|
||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||
|
||||
if (!lastRow) {
|
||||
road = {
|
||||
index: index++,
|
||||
angle: 0,
|
||||
top: y,
|
||||
left: x
|
||||
};
|
||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||
}
|
||||
|
||||
if (++rowCount === rows[row]) {
|
||||
if (!lastRow) {
|
||||
road = {
|
||||
index: index++,
|
||||
angle: 0,
|
||||
top: y,
|
||||
left: x+2.*tileHalfHeight
|
||||
};
|
||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||
}
|
||||
|
||||
if (row > 2) {
|
||||
road = {
|
||||
index: index++,
|
||||
angle: 60,
|
||||
top: y-0.5*tileHalfHeight,
|
||||
left: x+3.*tileHalfHeight
|
||||
};
|
||||
corners.push(<Road key={`road-${index}}`} road={road}/>);
|
||||
}
|
||||
|
||||
row++;
|
||||
rowCount = 0;
|
||||
y += tileHeight - 10.5;
|
||||
x = -tileHalfHeight - (rows[row] - 1) * 0.5 * tileHeight;
|
||||
} else {
|
||||
x += tileHeight;
|
||||
}
|
||||
}
|
||||
return corners;
|
||||
}
|
||||
|
||||
const generateCorners = () => {
|
||||
let row = 0, rowCount = 0;
|
||||
let y = -8 + 0.5 * tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||
x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
|
||||
let index = 0;
|
||||
const corners = [];
|
||||
let corner;
|
||||
|
||||
for (let i = 0; i < 21; i++) {
|
||||
if (row > 2 && rowCount === 0) {
|
||||
corner = {
|
||||
index: index++,
|
||||
top: y-0.5*tileHalfHeight,
|
||||
left: x-tileHalfHeight
|
||||
};
|
||||
corners.push(<Corner key={`corner-${index}}`} corner={corner}/>);
|
||||
}
|
||||
|
||||
corner = {
|
||||
index: index++,
|
||||
top: y,
|
||||
left: x
|
||||
};
|
||||
corners.push(<Corner key={`corner-${index}}`} corner={corner}/>);
|
||||
|
||||
corner = {
|
||||
index: index++,
|
||||
top: y-0.5*tileHalfHeight,
|
||||
left: x+tileHalfHeight
|
||||
};
|
||||
corners.push(<Corner key={`corner-${index}}`} corner={corner}/>);
|
||||
|
||||
if (++rowCount === rows[row]) {
|
||||
corner = {
|
||||
index: index++,
|
||||
top: y,
|
||||
left: x+2.*tileHalfHeight
|
||||
};
|
||||
corners.push(<Corner key={`corner-${index}}`} corner={corner}/>);
|
||||
|
||||
if (row > 2) {
|
||||
corner = {
|
||||
index: index++,
|
||||
top: y-0.5*tileHalfHeight,
|
||||
left: x+3.*tileHalfHeight
|
||||
};
|
||||
corners.push(<Corner key={`corner-${index}}`} corner={corner}/>);
|
||||
}
|
||||
|
||||
row++;
|
||||
rowCount = 0;
|
||||
y += tileHeight - 10.5;
|
||||
x = -tileHalfHeight - (rows[row] - 1) * 0.5 * tileHeight;
|
||||
} else {
|
||||
x += tileHeight;
|
||||
}
|
||||
}
|
||||
return corners;
|
||||
}
|
||||
|
||||
const generatePips = () => {
|
||||
let row = 0, rowCount = 0;
|
||||
let y = tileHalfWidth - rows.length * 0.5 * tileWidth,
|
||||
let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||
x = -(rows[row] - 1) * 0.5 * tileHeight;
|
||||
return game.pipOrder.map(order => {
|
||||
const pip = game.pips[order];
|
||||
@ -39,8 +225,6 @@ const Board = ({ game }) => {
|
||||
key={`pip-${order}`}
|
||||
className="Pip"
|
||||
style={{
|
||||
width: `${scale*2}em`,
|
||||
height: `${scale*2}em`,
|
||||
top: `${y}px`,
|
||||
left: `${x}px`,
|
||||
backgroundImage: `url(${assetsPath}/gfx/pip-numbers.png)`,
|
||||
@ -64,7 +248,7 @@ const Board = ({ game }) => {
|
||||
|
||||
const generateTiles = () => {
|
||||
let row = 0, rowCount = 0;
|
||||
let y = tileHalfWidth - rows.length * 0.5 * tileWidth,
|
||||
let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
|
||||
x = -(rows[row] - 1) * 0.5 * tileHeight;
|
||||
return game.tileOrder.map(order => {
|
||||
const tile = game.tiles[order];
|
||||
@ -95,8 +279,7 @@ const Board = ({ game }) => {
|
||||
};
|
||||
|
||||
const generateBorders = () => {
|
||||
const radius = tileHeight * 2,
|
||||
sides = 6;
|
||||
const sides = 6;
|
||||
let side = -1;
|
||||
return game.borderOrder.map(order => {
|
||||
const border = game.borders[order];
|
||||
@ -121,11 +304,15 @@ const Board = ({ game }) => {
|
||||
});
|
||||
};
|
||||
|
||||
/* If the game is loaded, and the signature is different,
|
||||
* regenerate everything */
|
||||
if (game && game.signature !== signature) {
|
||||
console.log(`Generate for ${game.signature}`);
|
||||
setPips(generatePips);
|
||||
setBorders(generateBorders);
|
||||
setTiles(generateTiles);
|
||||
setCorners(generateCorners);
|
||||
setRoads(generateRoads);
|
||||
setSignature(game.signature);
|
||||
} else {
|
||||
if (!game) {
|
||||
@ -133,6 +320,8 @@ const Board = ({ game }) => {
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the 'transform: scale' for the BoardBox
|
||||
* so the board fills the Board */
|
||||
const board = document.querySelector('.Board');
|
||||
if (board) {
|
||||
const width = board.offsetWidth,
|
||||
@ -143,7 +332,7 @@ const Board = ({ game }) => {
|
||||
} else {
|
||||
_transform = width / (450. * hexRatio);
|
||||
}
|
||||
if (_transform != transform) {
|
||||
if (_transform !== transform) {
|
||||
const boardBox = board.querySelector('.BoardBox');
|
||||
if (boardBox) {
|
||||
console.log(`Setting transofrm scale to ${_transform}`);
|
||||
@ -159,6 +348,14 @@ const Board = ({ game }) => {
|
||||
{ borders }
|
||||
{ tiles }
|
||||
{ pips }
|
||||
{ game && <>
|
||||
<div className="Corners" disabled={game.state !== 'active'}>
|
||||
{ corners }
|
||||
</div>
|
||||
<div className="Roads" disabled={true || game.state !== 'active'}>
|
||||
{ roads }
|
||||
</div>
|
||||
</> }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -1021,50 +1021,52 @@ class Table extends React.Component {
|
||||
<GameOrder table={this}/>
|
||||
}
|
||||
|
||||
<div className="Cards">
|
||||
{ game && game.state === "active" && <>
|
||||
<div>In hand</div>
|
||||
<div className="Hand">
|
||||
<Resource type="wood" count={this.state.wood}/>
|
||||
<Resource type="wheat" count={this.state.wheat}/>
|
||||
<Resource type="stone" count={this.state.stone}/>
|
||||
<Resource type="brick" count={this.state.brick}/>
|
||||
<Resource type="sheep" count={this.state.sheep}/>
|
||||
</div>
|
||||
<div>Available to play</div>
|
||||
<div className="Hand">
|
||||
<Development type="monopoly" count="1"/>
|
||||
<Development type="army-" max="14" count="4"/>
|
||||
<div className="Stack">
|
||||
<Development type="vp-library" count="1"/>
|
||||
<Development type="vp-market" count="1"/>
|
||||
{ game && game.showCards &&
|
||||
<div className="Cards">
|
||||
{ game && game.state === "active" && <>
|
||||
<div>In hand</div>
|
||||
<div className="Hand">
|
||||
<Resource type="wood" count={this.state.wood}/>
|
||||
<Resource type="wheat" count={this.state.wheat}/>
|
||||
<Resource type="stone" count={this.state.stone}/>
|
||||
<Resource type="brick" count={this.state.brick}/>
|
||||
<Resource type="sheep" count={this.state.sheep}/>
|
||||
</div>
|
||||
</div>
|
||||
<div>Points</div>
|
||||
<div className="Hand">
|
||||
<div className="Stack">
|
||||
<Development type="vp-library" count="1"/>
|
||||
<Development type="vp-palace" count="1"/>
|
||||
<Development type="army-" max="14" count="6"/>
|
||||
<div>Available to play</div>
|
||||
<div className="Hand">
|
||||
<Development type="monopoly" count="1"/>
|
||||
<Development type="army-" max="14" count="4"/>
|
||||
<div className="Stack">
|
||||
<Development type="vp-library" count="1"/>
|
||||
<Development type="vp-market" count="1"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="Hand">
|
||||
<Placard type="largest-army" count="1"/>
|
||||
<Placard type="longest-road" count="1"/>
|
||||
</div>
|
||||
<div className="Statistics">
|
||||
<div>Stats</div>
|
||||
<div>
|
||||
<div>Points: 7</div>
|
||||
<div>Cards: {this.state.total} </div>
|
||||
<div>Roads remaining: 4</div>
|
||||
<div>Longest road: 7</div>
|
||||
<div>Cities remaining: 4</div>
|
||||
<div>Settlements remaining: 5</div>
|
||||
<div>Points</div>
|
||||
<div className="Hand">
|
||||
<div className="Stack">
|
||||
<Development type="vp-library" count="1"/>
|
||||
<Development type="vp-palace" count="1"/>
|
||||
<Development type="army-" max="14" count="6"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</> }
|
||||
</div>
|
||||
<div className="Hand">
|
||||
<Placard type="largest-army" count="1"/>
|
||||
<Placard type="longest-road" count="1"/>
|
||||
</div>
|
||||
<div className="Statistics">
|
||||
<div>Stats</div>
|
||||
<div>
|
||||
<div>Points: 7</div>
|
||||
<div>Cards: {this.state.total} </div>
|
||||
<div>Roads remaining: 4</div>
|
||||
<div>Longest road: 7</div>
|
||||
<div>Cities remaining: 4</div>
|
||||
<div>Settlements remaining: 5</div>
|
||||
</div>
|
||||
</div>
|
||||
</> }
|
||||
</div>
|
||||
}
|
||||
|
||||
{ this.state.error && <Paper className="Error"><div>{this.state.error}</div></Paper> }
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
Loading…
x
Reference in New Issue
Block a user