Game now sets up correct tile and pip order!
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
27cf10ad48
commit
7af8d02802
@ -3,95 +3,13 @@ import "./Board.css";
|
|||||||
|
|
||||||
const base = process.env.PUBLIC_URL;
|
const base = process.env.PUBLIC_URL;
|
||||||
const assetsPath = `${base}/assets`;
|
const assetsPath = `${base}/assets`;
|
||||||
const images = {};
|
|
||||||
|
|
||||||
const getPlayerColors = (color) => {
|
|
||||||
switch (color) {
|
|
||||||
case "O":
|
|
||||||
return {
|
|
||||||
strokeStyle: "white",
|
|
||||||
fillStyle: "#ff5722"
|
|
||||||
}
|
|
||||||
case "R":
|
|
||||||
return {
|
|
||||||
strokeStyle: "white",
|
|
||||||
fillStyle: "#f44336"
|
|
||||||
}
|
|
||||||
case "W":
|
|
||||||
return {
|
|
||||||
strokeStyle: "black",
|
|
||||||
fillStyle: "#9e9e9e"
|
|
||||||
}
|
|
||||||
case "B":
|
|
||||||
return {
|
|
||||||
strokeStyle: "black",
|
|
||||||
fillStyle: "#03a9f4"
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return {
|
|
||||||
strokeStyle: "rgb(16, 16, 16)",
|
|
||||||
fillStyle: "rgb(64, 64, 64)"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const hexagonRatio = 1.1547005,
|
|
||||||
tileHeight = 0.16,
|
|
||||||
tileWidth = tileHeight * hexagonRatio,
|
|
||||||
roadSize = tileHeight * 0.5 * (5. / 8.),
|
|
||||||
settlementSize = tileHeight * 0.5 - roadSize;
|
|
||||||
|
|
||||||
const imageLoaded = (event) => {
|
|
||||||
const image = event.target;
|
|
||||||
console.log(`Done loading ${image.src}`);
|
|
||||||
image.removeEventListener("load", imageLoaded);
|
|
||||||
image.removeEventListener("error", imageLoadError);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (image.drawFrame) {
|
|
||||||
window.requestAnimationFrame(image.drawFrame);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
image.board = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const imageLoadError = (event) => {
|
|
||||||
const image = event.target;
|
|
||||||
console.log(`Error loading ${image.src}`);
|
|
||||||
image.removeEventListener("load", imageLoaded);
|
|
||||||
image.removeEventListener("error", imageLoadError);
|
|
||||||
console.log(`Error loading ${image.src}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const loadImage = (file, drawFrame) => {
|
|
||||||
if (file in images) {
|
|
||||||
images[file].drawFrame = drawFrame;
|
|
||||||
return images[file];
|
|
||||||
}
|
|
||||||
|
|
||||||
const image = new Image();
|
|
||||||
image.drawFrame = drawFrame;
|
|
||||||
images[file] = image;
|
|
||||||
|
|
||||||
image.addEventListener("load", imageLoaded);
|
|
||||||
image.addEventListener("error", imageLoadError);
|
|
||||||
|
|
||||||
image.src = `${assetsPath}/gfx/${file}`;
|
|
||||||
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Board = ({ game }) => {
|
const Board = ({ game }) => {
|
||||||
const [closest, setClosest] = useState({
|
|
||||||
info: {},
|
|
||||||
tile: null,
|
|
||||||
road: null,
|
|
||||||
tradeToken: null,
|
|
||||||
settlement: null
|
|
||||||
});
|
|
||||||
|
|
||||||
const center = { x: 300, y: 350 }, rows = [3, 4, 5, 4, 3];
|
const center = { x: 300, y: 350 }, rows = [3, 4, 5, 4, 3];
|
||||||
|
const [signature, setSignature] = useState("");
|
||||||
|
const [pips, setPips] = useState(<></>);
|
||||||
|
const [borders, setBorders] = useState(<></>);
|
||||||
|
const [tiles, setTiles] = useState(<></>);
|
||||||
|
|
||||||
const generatePips = () => {
|
const generatePips = () => {
|
||||||
let row = 0, rowCount = 0;
|
let row = 0, rowCount = 0;
|
||||||
@ -104,7 +22,7 @@ const Board = ({ game }) => {
|
|||||||
: String.fromCharCode(65 + i);
|
: String.fromCharCode(65 + i);
|
||||||
divs.push(
|
divs.push(
|
||||||
<div
|
<div
|
||||||
key={`pip-${code}`}
|
key={`pip-${(i).toString(16)}`}
|
||||||
className="Pip"
|
className="Pip"
|
||||||
style={{
|
style={{
|
||||||
top: `${y}px`,
|
top: `${y}px`,
|
||||||
@ -132,7 +50,7 @@ const Board = ({ game }) => {
|
|||||||
let y = center.y - rows.length * 0.5 * 67,
|
let y = center.y - rows.length * 0.5 * 67,
|
||||||
x = center.x - (rows[row] - 1) * 0.5 * 77.5;
|
x = center.x - (rows[row] - 1) * 0.5 * 77.5;
|
||||||
|
|
||||||
return [ "robber", "brick", "wood", "sheep", "stone", "wheat" ].map((type) => {
|
return [ "wood", "wheat", "stone", "sheep", "brick", "robber" ].map((type) => {
|
||||||
let count;
|
let count;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "robber":
|
case "robber":
|
||||||
@ -162,7 +80,7 @@ const Board = ({ game }) => {
|
|||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
divs.push(
|
divs.push(
|
||||||
<div
|
<div
|
||||||
key={`${type}-${i}`}
|
key={`${type}-${(i).toString(16)}`}
|
||||||
className="Tile"
|
className="Tile"
|
||||||
style={{
|
style={{
|
||||||
top: `${y}px`,
|
top: `${y}px`,
|
||||||
@ -196,7 +114,7 @@ const Board = ({ game }) => {
|
|||||||
let prev = (side == 0) ? 6 : side;
|
let prev = (side == 0) ? 6 : side;
|
||||||
const file = `borders-${side+1}.${prev}.png`;
|
const file = `borders-${side+1}.${prev}.png`;
|
||||||
divs.push(<div
|
divs.push(<div
|
||||||
key={`border-${side}`}
|
key={`border-${side.toString(16)}`}
|
||||||
className="Border"
|
className="Border"
|
||||||
style={{
|
style={{
|
||||||
top: `${y}px`,
|
top: `${y}px`,
|
||||||
@ -208,9 +126,24 @@ const Board = ({ game }) => {
|
|||||||
return divs;
|
return divs;
|
||||||
};
|
};
|
||||||
|
|
||||||
const tiles = generateTiles(),
|
const updateBorders = () => {
|
||||||
pips = generatePips(),
|
for (let i = 0; i < 6; i++) {
|
||||||
borders = generateBorders();
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
if (game && game.signature != signature) {
|
||||||
|
console.log(`Generate for ${game.signature}`);
|
||||||
|
setPips(generatePips);
|
||||||
|
setBorders(generateBorders);
|
||||||
|
setTiles(generateTiles);
|
||||||
|
setSignature(game.signature);
|
||||||
|
} else {
|
||||||
|
if (!game) {
|
||||||
|
console.log(`No game in Board`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [ setPips, setBorders, setTiles, setSignature, game]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="Board" style={{backgroundImage: `url(${assetsPath}/gfx/tabletop.png)`}}>
|
<div className="Board" style={{backgroundImage: `url(${assetsPath}/gfx/tabletop.png)`}}>
|
||||||
|
@ -360,6 +360,9 @@ const Players = ({ table }) => {
|
|||||||
|
|
||||||
const players = [];
|
const players = [];
|
||||||
|
|
||||||
|
if (!table.game) {
|
||||||
|
return (<></>);
|
||||||
|
}
|
||||||
for (let color in table.game.players) {
|
for (let color in table.game.players) {
|
||||||
const item = table.game.players[color], inLobby = table.game.state === 'lobby';
|
const item = table.game.players[color], inLobby = table.game.state === 'lobby';
|
||||||
if (!inLobby && item.status === 'Not active') {
|
if (!inLobby && item.status === 'Not active') {
|
||||||
@ -788,19 +791,19 @@ class Table extends React.Component {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
const signature =
|
const signature =
|
||||||
game.borders.map(border => border.file.replace(/borders-(.).*/, "$1")).join('') +
|
game.borderOrder.map(border => Number(border).toString(16)).join('') + '-' +
|
||||||
game.pips.map(pip => pip.roll.toString()).join('') +
|
game.pipOrder.map(pip => Number(pip).toString(16)).join('') + '-' +
|
||||||
game.tiles.map(tile => tile.type.charAt(0)).join('');
|
game.tileOrder.map(tile => Number(tile).toString(16)).join('');
|
||||||
|
|
||||||
return signature;
|
return signature;
|
||||||
};
|
};
|
||||||
|
|
||||||
updateGame(game) {
|
updateGame(game) {
|
||||||
|
|
||||||
if (this.state.signature !== this.gameSignature(game)) {
|
if (this.state.signature !== this.gameSignature(game)) {
|
||||||
this.setState({ signature: this.gameSignature(game), game: game });
|
game.signature = this.gameSignature(game);
|
||||||
}
|
}
|
||||||
// console.log("Update Game", game);
|
// console.log("Update Game", game);
|
||||||
|
this.setState( { game: game });
|
||||||
this.game = game;
|
this.game = game;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,54 +36,54 @@ function shuffle(array) {
|
|||||||
|
|
||||||
const assetData = {
|
const assetData = {
|
||||||
tiles: [
|
tiles: [
|
||||||
{ type: "wood", y: 0. / 4. },
|
"wood",
|
||||||
{ type: "wood", y: 1. / 4. },
|
"wood",
|
||||||
{ type: "wood", y: 2. / 4. },
|
"wood",
|
||||||
{ type: "wood", y: 3. / 4. },
|
"wood",
|
||||||
{ type: "wheat", y: 0. / 4. },
|
"wheat",
|
||||||
{ type: "wheat", y: 1. / 4. },
|
"wheat",
|
||||||
{ type: "wheat", y: 2. / 4. },
|
"wheat",
|
||||||
{ type: "wheat", y: 3. / 4. },
|
"wheat",
|
||||||
{ type: "stone", y: 0. / 4. },
|
"stone",
|
||||||
{ type: "stone", y: 1. / 4. },
|
"stone",
|
||||||
{ type: "stone", y: 2. / 4. },
|
"stone",
|
||||||
{ type: "sheep", y: 0. / 4. },
|
"sheep",
|
||||||
{ type: "sheep", y: 1. / 4. },
|
"sheep",
|
||||||
{ type: "sheep", y: 2. / 4. },
|
"sheep",
|
||||||
{ type: "sheep", y: 3. / 4. },
|
"sheep",
|
||||||
{ type: "brick", y: 0. / 4. },
|
"brick",
|
||||||
{ type: "brick", y: 1. / 4. },
|
"brick",
|
||||||
{ type: "brick", y: 2. / 4. },
|
"brick",
|
||||||
{ type: "robber", y: 0 }
|
"robber"
|
||||||
],
|
],
|
||||||
pips: [
|
pips: [
|
||||||
{ roll: 7, pips: 0, y: 3. / 6., x: 0. / 6. },
|
{ roll: 7, pips: 0 },
|
||||||
{ roll: 5, pips: 4, y: 0. / 6., x: 0. / 6. },
|
{ roll: 5, pips: 4 },
|
||||||
{ roll: 2, pips: 1, y: 0. / 6., x: 1. / 6. },
|
{ roll: 2, pips: 1 },
|
||||||
{ roll: 6, pips: 5, y: 0. / 6., x: 2. / 6. },
|
{ roll: 6, pips: 5 },
|
||||||
{ roll: 3, pips: 2, y: 0. / 6., x: 3. / 6. },
|
{ roll: 3, pips: 2 },
|
||||||
{ roll: 8, pips: 5, y: 0. / 6., x: 4. / 6. },
|
{ roll: 8, pips: 5 },
|
||||||
{ roll: 10, pips: 3, y: 0. / 6., x: 5. / 6. },
|
{ roll: 10, pips: 3 },
|
||||||
{ roll: 9, pips: 4, y: 1. / 6., x: 0. / 6. },
|
{ roll: 9, pips: 4 },
|
||||||
{ roll: 12, pips: 1, y: 1. / 6., x: 1. / 6. },
|
{ roll: 12, pips: 1 },
|
||||||
{ roll: 11, pips: 2, y: 1. / 6., x: 2. / 6. },
|
{ roll: 11, pips: 2 },
|
||||||
{ roll: 4, pips: 3, y: 1. / 6., x: 3. / 6. },
|
{ roll: 4, pips: 3 },
|
||||||
{ roll: 8, pips: 5, y: 1. / 6., x: 4. / 6. },
|
{ roll: 8, pips: 5 },
|
||||||
{ roll: 10, pips: 3, y: 1. / 6., x: 5. / 6. },
|
{ roll: 10, pips: 3 },
|
||||||
{ roll: 9, pips: 4, y: 2. / 6., x: 0. / 6. },
|
{ roll: 9, pips: 4 },
|
||||||
{ roll: 4, pips: 3, y: 2. / 6., x: 1. / 6. },
|
{ roll: 4, pips: 3 },
|
||||||
{ roll: 5, pips: 4, y: 2. / 6., x: 2. / 6. },
|
{ roll: 5, pips: 4 },
|
||||||
{ roll: 6, pips: 6, y: 2. / 6., x: 3. / 6. },
|
{ roll: 6, pips: 6 },
|
||||||
{ roll: 3, pips: 2, y: 2. / 6., x: 4. / 6. },
|
{ roll: 3, pips: 2 },
|
||||||
{ roll: 11, pips: 2, y: 2. / 6., x: 5. / 6. }
|
{ roll: 11, pips: 2 }
|
||||||
],
|
],
|
||||||
borders: [
|
borders: [
|
||||||
{ file: 'borders-1.6.png', left: "sheep", right: "bank" },
|
{ left: "sheep", right: "bank" },
|
||||||
{ file: 'borders-2.1.png', center: "sheep" },
|
{ center: "sheep" },
|
||||||
{ file: 'borders-3.2.png', left: "wheat", right: "bank" },
|
{ left: "wheat", right: "bank" },
|
||||||
{ file: 'borders-4.3.png', center: "wood" },
|
{ center: "wood" },
|
||||||
{ file: 'borders-5.4.png', left: "sheep", right: "bank" },
|
{ left: "sheep", right: "bank" },
|
||||||
{ file: 'borders-6.5.png', center: "bank" }
|
{ center: "bank" }
|
||||||
],
|
],
|
||||||
developmentCards: []
|
developmentCards: []
|
||||||
};
|
};
|
||||||
@ -201,6 +201,17 @@ const loadGame = async (id) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!game.pipOrder || !game.borderOrder || !game.tileOrder) {
|
||||||
|
console.log("Shuffling old save file");
|
||||||
|
shuffleBoard(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!game.pips || !game.borders || !game.tiles) {
|
||||||
|
[ "pips", "borders", "tiles" ].forEach((field) => {
|
||||||
|
game[field] = assetData[field]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/* Reconnect session player colors to the player objects */
|
/* Reconnect session player colors to the player objects */
|
||||||
for (let id in game.sessions) {
|
for (let id in game.sessions) {
|
||||||
const session = game.sessions[id];
|
const session = game.sessions[id];
|
||||||
@ -590,9 +601,6 @@ const createGame = (id) => {
|
|||||||
startTime: Date.now(),
|
startTime: Date.now(),
|
||||||
turns: 0,
|
turns: 0,
|
||||||
state: "lobby", /* lobby, active, finished */
|
state: "lobby", /* lobby, active, finished */
|
||||||
tiles: [],
|
|
||||||
pips: [],
|
|
||||||
borders: [],
|
|
||||||
tokens: [],
|
tokens: [],
|
||||||
players: {
|
players: {
|
||||||
R: getPlayer(),
|
R: getPlayer(),
|
||||||
@ -612,6 +620,11 @@ const createGame = (id) => {
|
|||||||
chat: [ { date: Date.now(), message: `New game started for ${id}` } ],
|
chat: [ { date: Date.now(), message: `New game started for ${id}` } ],
|
||||||
id: id
|
id: id
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[ "pips", "borders", "tiles" ].forEach((field) => {
|
||||||
|
game[field] = assetData[field]
|
||||||
|
});
|
||||||
|
|
||||||
games[game.id] = game;
|
games[game.id] = game;
|
||||||
shuffleBoard(game);
|
shuffleBoard(game);
|
||||||
console.log(`New game created: ${game.id}`);
|
console.log(`New game created: ${game.id}`);
|
||||||
@ -633,32 +646,52 @@ router.post("/:id?", (req, res/*, next*/) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const shuffleBoard = (game) => {
|
const shuffleBoard = (game) => {
|
||||||
[ "tiles", "pips", "borders" ].forEach((field) => {
|
const seq = [];
|
||||||
game[field] = []
|
for (let i = 0; i < 6; i++) {
|
||||||
for (let i = 0; i < assetData[field].length; i++) {
|
seq.push(i);
|
||||||
game[field].push(i);
|
}
|
||||||
}
|
shuffle(seq);
|
||||||
/* Shuffle an array of indexes */
|
game.borderOrder = seq.slice();
|
||||||
shuffle(game[field]);
|
for (let i = 6; i < 19; i++) {
|
||||||
/* Convert from an index array to a full array */
|
seq.push(i);
|
||||||
for (let i = 0; i < assetData[field].length; i++) {
|
}
|
||||||
game[field][i] = assetData[field][game[field][i]];
|
shuffle(seq);
|
||||||
}
|
game.tileOrder = seq.slice();
|
||||||
});
|
|
||||||
|
|
||||||
/* Walk through the board looking for the robber and
|
/* Pip order is from one of the random corners, then rotate around
|
||||||
* if it isn't on the desert, swap with the desert to
|
* and skip over the desert (robber) */
|
||||||
* be under the robber */
|
|
||||||
const robberIndex = game.pips.findIndex((pip) => pip.roll === 7),
|
/* Board:
|
||||||
desertIndex = game.tiles.findIndex((tile) => tile.type === 'robber');
|
* 0 1 2
|
||||||
|
* 3 4 5 6
|
||||||
if (robberIndex !== desertIndex) {
|
* 7 8 9 10 11
|
||||||
let tmp = game.tiles[desertIndex];
|
* 12 13 14 15
|
||||||
game.tiles[desertIndex] = game.tiles[robberIndex];
|
* 16 17 18
|
||||||
game.tiles[robberIndex] = tmp;
|
*/
|
||||||
|
const order = [
|
||||||
|
[ 0, 1, 2, 6, 11, 15, 18, 17, 16, 12, 7, 3, 4, 5, 10, 14, 13, 8, 9 ],
|
||||||
|
[ 2, 6, 11, 15, 18, 17, 16, 12, 7, 3, 0, 1, 5, 10, 14, 13, 8, 4, 9 ],
|
||||||
|
[ 11, 15, 18, 17, 16, 12, 7, 3, 0, 1, 2, 6, 10, 14, 13, 8, 4, 5, 9 ],
|
||||||
|
[ 18, 17, 16, 12, 7, 3, 0, 1, 2, 6, 11, 15, 14, 13, 8, 4, 5, 10, 9 ],
|
||||||
|
[ 16, 12, 7, 3, 0, 1, 2, 6, 11, 15, 18, 17, 13, 8, 4, 5, 10, 14, 9 ],
|
||||||
|
[ 7, 3, 0, 1, 2, 6, 11, 15, 18, 17, 16, 12, 8, 4, 5, 10, 14, 13, 9 ]
|
||||||
|
]
|
||||||
|
const sequence = order[Math.floor(Math.random() * order.length)];
|
||||||
|
game.pipOrder = [];
|
||||||
|
for (let i = 0, p = 0; i < sequence.length; i++) {
|
||||||
|
const target = sequence[i];
|
||||||
|
/* If the target tile is the desert (18), then set the
|
||||||
|
* pip value to the robber (0) otherwise set
|
||||||
|
* the target pip value to the currently incremeneting
|
||||||
|
* pip value. */
|
||||||
|
if (game.tileOrder[target] === 18) {
|
||||||
|
game.pipOrder[target] = 0;
|
||||||
|
} else {
|
||||||
|
game.pipOrder[target] = p++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shuffle(game.developmentCards)
|
shuffle(game.developmentCards)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user