refactors cards to nested array
This commit is contained in:
parent
ab1bad8842
commit
7b9e05b122
14 changed files with 1801 additions and 356 deletions
4
.env
4
.env
|
|
@ -1,5 +1,5 @@
|
|||
VITE_ENVIRONMENT=dev
|
||||
VITE_BACKEND_URL=https://skyjo-backend.voltvector.org
|
||||
|
||||
#VITE_ENVIRONMENT=local
|
||||
#VITE_BACKEND_URL=http://localhost:3001
|
||||
VITE_ENVIRONMENT=local
|
||||
VITE_BACKEND_URL=http://localhost:3001
|
||||
|
|
@ -7,9 +7,9 @@
|
|||
rel="stylesheet"
|
||||
as="style"
|
||||
/>
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="/card-back.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Play Skyjo!</title>
|
||||
<title>Play Skylo!</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
|
|
|||
1631
public/card-back.svg
Normal file
1631
public/card-back.svg
Normal file
File diff suppressed because it is too large
Load diff
|
After Width: | Height: | Size: 93 KiB |
|
|
@ -62,8 +62,6 @@ export default function App() {
|
|||
};
|
||||
}, []);
|
||||
|
||||
console.log(messageDispaly);
|
||||
|
||||
return (
|
||||
<div className="bg-gray-900 w-screen h-screen">
|
||||
{!gameData && (
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ export const Footer: FC<Footer> = ({
|
|||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{gameData.players.map((player) => (
|
||||
<div className="mb-3 pt-2 mt-2 border-t border-gray-600">
|
||||
{gameData.players.map((player, index) => (
|
||||
<div key={index} className="mb-3 pt-2 mt-2 border-t border-gray-600">
|
||||
<div className="flex justify-between items-center">
|
||||
<Text>
|
||||
{player?.name} {player.socketId == socket.id && "👤"}{" "}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { FC } from "react";
|
||||
|
||||
import PlayerCards from "../components/PlayerCards";
|
||||
import PlayerDecks from "./PlayerDecks";
|
||||
import { Game } from "../types/gameTypes";
|
||||
import CardStackStaple from "./CardStackStaple";
|
||||
import DiscardPile from "./DiscardPile";
|
||||
|
|
@ -14,7 +14,7 @@ const PlayArea: FC<PlayAreaProps> = ({ gameData }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<PlayerCards playersData={gameData.players} />
|
||||
<PlayerDecks playersData={gameData.players} />
|
||||
<CardStackStaple cardStackData={gameData.cardStack} />
|
||||
<DiscardPile discardPileData={gameData.discardPile} />
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -2,22 +2,25 @@ import { FC, useState, useEffect } from "react";
|
|||
import { Object3D, Object3DEventMap } from "three";
|
||||
// import { useFrame } from "@react-three/fiber";
|
||||
import { socket } from "../socket";
|
||||
import { PlayerWithVisualCards } from "../types/gameTypes";
|
||||
import { PlayerVisualDeck } from "../types/gameTypes";
|
||||
|
||||
type PlayerCardProps = {
|
||||
card: Object3D<Object3DEventMap>;
|
||||
index: number;
|
||||
columnIndex: number;
|
||||
cardIndex: number;
|
||||
isCurrentPlayer: boolean;
|
||||
playerWithCards: PlayerWithVisualCards;
|
||||
visualPlayerDeck: PlayerVisualDeck;
|
||||
};
|
||||
|
||||
const PlayerCard: FC<PlayerCardProps> = ({
|
||||
card,
|
||||
index,
|
||||
columnIndex,
|
||||
cardIndex,
|
||||
isCurrentPlayer,
|
||||
playerWithCards,
|
||||
visualPlayerDeck,
|
||||
}) => {
|
||||
const isCardRevealed = playerWithCards.player.knownCardPositions[index];
|
||||
const isCardRevealed =
|
||||
visualPlayerDeck.player.knownCardPositions[columnIndex][cardIndex];
|
||||
const [cardObject, setCardObject] =
|
||||
useState<Object3D<Object3DEventMap>>(card);
|
||||
|
||||
|
|
@ -54,16 +57,15 @@ const PlayerCard: FC<PlayerCardProps> = ({
|
|||
const clickCard = () => {
|
||||
if (!isCurrentPlayer) return;
|
||||
console.log("Clicked on one of my cards");
|
||||
socket.emit("click-card", index, (response: string) => {
|
||||
console.log("Response:", response);
|
||||
/*if (rotationGoal === 0) {
|
||||
setRotationGoal(Math.PI);
|
||||
} else {
|
||||
setRotationGoal(0);
|
||||
}*/
|
||||
});
|
||||
socket.emit("click-card", [columnIndex, cardIndex]);
|
||||
};
|
||||
return <primitive object={cardObject} onClick={() => clickCard()} />;
|
||||
return (
|
||||
<primitive
|
||||
key={columnIndex + cardIndex * 4}
|
||||
object={cardObject}
|
||||
onClick={() => clickCard()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlayerCard;
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
import { FC, useState, useEffect } from "react";
|
||||
import { socket } from "../socket";
|
||||
import { Vector3 } from "three";
|
||||
|
||||
import { createPlayerCards } from "../objects/cards";
|
||||
import PlayerCard from "./PlayerCard";
|
||||
import { PlayerWithVisualCards, Player } from "../types/gameTypes";
|
||||
import CardCache from "./CardCache";
|
||||
|
||||
type PlayerCardsProps = {
|
||||
playersData: Player[];
|
||||
};
|
||||
|
||||
const PlayerCards: FC<PlayerCardsProps> = ({ playersData }) => {
|
||||
const [playersWithCards, setPlayersWithCards] = useState<
|
||||
PlayerWithVisualCards[]
|
||||
>([]);
|
||||
|
||||
const updatePlayerCards = (playersData: Player[]) => {
|
||||
const playersWithCards: PlayerWithVisualCards[] = [];
|
||||
const currentPlayerWithCards: PlayerWithVisualCards[] = [];
|
||||
let nonCurrentPlayerIndex = 1;
|
||||
playersData.forEach((player) => {
|
||||
const positionOffset = 14;
|
||||
const playerWithCards: PlayerWithVisualCards = {
|
||||
player,
|
||||
cards: [],
|
||||
};
|
||||
if (player.socketId === socket.id) {
|
||||
playerWithCards.cards = createPlayerCards(
|
||||
player.cards,
|
||||
new Vector3(0, 20, positionOffset)
|
||||
);
|
||||
currentPlayerWithCards.push(playerWithCards);
|
||||
} else {
|
||||
const playerOffset = positionOffset + nonCurrentPlayerIndex * -20;
|
||||
playerWithCards.cards = createPlayerCards(
|
||||
player.cards,
|
||||
new Vector3(0, 20, playerOffset)
|
||||
);
|
||||
playersWithCards.push(playerWithCards);
|
||||
nonCurrentPlayerIndex++;
|
||||
}
|
||||
});
|
||||
setPlayersWithCards([...currentPlayerWithCards, ...playersWithCards]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!playersData) return;
|
||||
updatePlayerCards(playersData);
|
||||
}, [playersData]);
|
||||
|
||||
if (!playersWithCards) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{playersWithCards.map((playerWithCards, playerIndex) => (
|
||||
<>
|
||||
{playerWithCards.cards.map((card, index) => (
|
||||
<PlayerCard
|
||||
key={index}
|
||||
card={card}
|
||||
playerWithCards={playerWithCards}
|
||||
index={index}
|
||||
isCurrentPlayer={playerIndex === 0}
|
||||
/>
|
||||
))}
|
||||
<CardCache
|
||||
playerData={playerWithCards.player}
|
||||
// current player is always at index 0
|
||||
position={new Vector3(9, 20, 6 - playerIndex * 12)}
|
||||
/>
|
||||
</>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlayerCards;
|
||||
// ich (0) --> 4
|
||||
// andere (1) --> -8
|
||||
86
src/components/PlayerDecks.tsx
Normal file
86
src/components/PlayerDecks.tsx
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
import { FC, useState, useEffect } from "react";
|
||||
import { socket } from "../socket";
|
||||
import { Vector3 } from "three";
|
||||
|
||||
import { createPlayerCards as createPlayerDeck } from "../objects/cards";
|
||||
import PlayerCard from "./PlayerCard";
|
||||
import { PlayerVisualDeck, Player } from "../types/gameTypes";
|
||||
import CardCache from "./CardCache";
|
||||
|
||||
type PlayerDecksProps = {
|
||||
playersData: Player[];
|
||||
};
|
||||
|
||||
const PlayerDecks: FC<PlayerDecksProps> = ({ playersData }) => {
|
||||
const [visualPlayerDecks, setVisualPlayerDecks] = useState<
|
||||
PlayerVisualDeck[]
|
||||
>([]);
|
||||
|
||||
const updatePlayerCards = (playersData: Player[]) => {
|
||||
const visualPlayerDecks: PlayerVisualDeck[] = [];
|
||||
const currentVisualPlayerDeck: PlayerVisualDeck[] = [];
|
||||
let nonCurrentPlayerIndex = 1;
|
||||
playersData.forEach((player) => {
|
||||
const positionOffset = 14;
|
||||
const playerVisualDeck: PlayerVisualDeck = {
|
||||
player,
|
||||
visualDeck: [],
|
||||
};
|
||||
if (player.socketId === socket.id) {
|
||||
playerVisualDeck.visualDeck = createPlayerDeck(
|
||||
player.deck,
|
||||
new Vector3(0, 20, positionOffset)
|
||||
);
|
||||
currentVisualPlayerDeck.push(playerVisualDeck);
|
||||
} else {
|
||||
const playerOffset = positionOffset + nonCurrentPlayerIndex * -20;
|
||||
playerVisualDeck.visualDeck = createPlayerDeck(
|
||||
player.deck,
|
||||
new Vector3(0, 20, playerOffset)
|
||||
);
|
||||
visualPlayerDecks.push(playerVisualDeck);
|
||||
nonCurrentPlayerIndex++;
|
||||
}
|
||||
});
|
||||
setVisualPlayerDecks([...currentVisualPlayerDeck, ...visualPlayerDecks]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!playersData) return;
|
||||
updatePlayerCards(playersData);
|
||||
}, [playersData]);
|
||||
|
||||
if (!visualPlayerDecks) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{visualPlayerDecks.map((visualPlayerDeck, playerIndex) => (
|
||||
<>
|
||||
{visualPlayerDeck.visualDeck.map((column, columnIndex) => (
|
||||
<>
|
||||
{column.map((card, cardIndex) => (
|
||||
<PlayerCard
|
||||
key={columnIndex + cardIndex * 4}
|
||||
card={card}
|
||||
visualPlayerDeck={visualPlayerDeck}
|
||||
columnIndex={columnIndex}
|
||||
cardIndex={cardIndex}
|
||||
isCurrentPlayer={playerIndex === 0}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
))}
|
||||
<CardCache
|
||||
playerData={visualPlayerDeck.player}
|
||||
// current player is always at index 0
|
||||
position={new Vector3(9, 20, 6 - playerIndex * 12)}
|
||||
/>
|
||||
</>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PlayerDecks;
|
||||
// ich (0) --> 4
|
||||
// andere (1) --> -8
|
||||
|
|
@ -13,6 +13,8 @@ type SessionManagerProps = {
|
|||
showStartGameButton: boolean;
|
||||
};
|
||||
|
||||
type SessionResponse = "success" | "error:full" | "error:running";
|
||||
|
||||
export const SessionManager: FC<SessionManagerProps> = ({
|
||||
isConnected,
|
||||
clientsInRoom,
|
||||
|
|
@ -25,9 +27,11 @@ export const SessionManager: FC<SessionManagerProps> = ({
|
|||
|
||||
function joinSession(event: React.FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
socket.emit("join-session", sessionField);
|
||||
socket.emit("join-session", sessionField, (response: SessionResponse) => {
|
||||
if (response !== "success") return;
|
||||
setSession(sessionField);
|
||||
setSessionField("");
|
||||
});
|
||||
}
|
||||
|
||||
function leaveSession(sessionName: string) {
|
||||
|
|
@ -52,10 +56,10 @@ export const SessionManager: FC<SessionManagerProps> = ({
|
|||
>
|
||||
<div className="py-8 px-4 mx-auto max-w-screen-xl text-center lg:py-16 z-10 relative">
|
||||
<h1 className="mb-4 text-4xl font-extrabold tracking-tight leading-none md:text-5xl lg:text-6xl text-white">
|
||||
Skyjo
|
||||
Skylo
|
||||
</h1>
|
||||
<p className="mb-8 text-lg font-normal lg:text-xl sm:px-16 lg:px-48 text-gray-200">
|
||||
Play Skyjo online with your friends!
|
||||
Play Skylo online with your friends!
|
||||
</p>
|
||||
<div className="p-4">
|
||||
{!isActiveSession && (
|
||||
|
|
@ -64,7 +68,7 @@ export const SessionManager: FC<SessionManagerProps> = ({
|
|||
htmlFor="first_name"
|
||||
className="block mb-2 text-sm font-medium text-white"
|
||||
>
|
||||
Join Skyjo Session
|
||||
Join Skylo Session
|
||||
</label>
|
||||
<div className="flex space-x-1 items-center">
|
||||
<input
|
||||
|
|
|
|||
|
|
@ -1,198 +0,0 @@
|
|||
import { useRef, useEffect, FC } from "react";
|
||||
import {
|
||||
Scene,
|
||||
PerspectiveCamera,
|
||||
WebGLRenderer,
|
||||
Vector3,
|
||||
DirectionalLight,
|
||||
DirectionalLightHelper,
|
||||
AmbientLight,
|
||||
Object3D,
|
||||
Mesh,
|
||||
GridHelper,
|
||||
AxesHelper,
|
||||
Material,
|
||||
} from "three";
|
||||
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
||||
import { useGLTF } from "@react-three/drei";
|
||||
import { createCube } from "../objects/cube";
|
||||
import { createPlayerCards, createCard } from "../objects/cards";
|
||||
import { Game, Player } from "../types/gameTypes";
|
||||
import { socket } from "../socket";
|
||||
|
||||
type ThreeSceneProps = {
|
||||
gameData: Game | null;
|
||||
};
|
||||
|
||||
const ThreeScene: FC<ThreeSceneProps> = ({ gameData }) => {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
const cardsRef = useRef<Mesh[]>([]);
|
||||
const tableModel = useGLTF("/models/table.glb");
|
||||
const heightProportion = 1.25;
|
||||
|
||||
function extractCurrentPlayer(gameData: Game | null): Player | undefined {
|
||||
if (!gameData) return undefined;
|
||||
return gameData.players.find((player) => player.socketId === socket.id);
|
||||
}
|
||||
|
||||
function disposeMesh(mesh: THREE.Mesh) {
|
||||
if (mesh.material instanceof Material) {
|
||||
mesh.material.dispose();
|
||||
} else if (Array.isArray(mesh.material)) {
|
||||
for (const material of mesh.material) {
|
||||
material.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
mesh.geometry.dispose();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
const scene = new Scene();
|
||||
const camera = new PerspectiveCamera(
|
||||
75,
|
||||
window.innerWidth / (window.innerHeight / heightProportion),
|
||||
0.1,
|
||||
1000
|
||||
);
|
||||
|
||||
const renderer = new WebGLRenderer();
|
||||
|
||||
renderer.setSize(window.innerWidth, window.innerHeight / heightProportion);
|
||||
container && container.appendChild(renderer.domElement);
|
||||
|
||||
// Objects
|
||||
const cubeCenter = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeCenter.position.set(0, 20, 0);
|
||||
|
||||
const cubeTL = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeTL.position.set(-10, 20, -15);
|
||||
|
||||
const cubeTR = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeTR.position.set(10, 20, -15);
|
||||
|
||||
const cubeBL = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeBL.position.set(-10, 20, 15);
|
||||
|
||||
const cubeBR = createCube(new Vector3(1, 1, 1), 0x00ff00);
|
||||
cubeBR.position.set(10, 20, 15);
|
||||
|
||||
scene.add(cubeCenter, cubeBL, cubeBR, cubeTL, cubeTR);
|
||||
|
||||
// Cards
|
||||
/*const initialCards: Card[] = [];
|
||||
for (let i = 1; i < 13; i++) {
|
||||
initialCards.push({ id: i, name: `${i} Card`, value: i as CardValue });
|
||||
}
|
||||
|
||||
const playerCards = createPlayerCards(initialCards, new Vector3(0, 20, 0));
|
||||
|
||||
scene.add(...playerCards);*/
|
||||
|
||||
const currentPlayer = extractCurrentPlayer(gameData);
|
||||
if (currentPlayer && !cardsRef.current.length) {
|
||||
cardsRef.current = createPlayerCards(
|
||||
currentPlayer.cards,
|
||||
new Vector3(0, 20, 0)
|
||||
);
|
||||
scene.add(...cardsRef.current);
|
||||
}
|
||||
|
||||
// Camera
|
||||
camera.position.set(0, 45, 10);
|
||||
camera.lookAt(0, 0, 0);
|
||||
|
||||
// Orbit Controls
|
||||
const orbit = new OrbitControls(camera, renderer.domElement);
|
||||
orbit.update();
|
||||
|
||||
// Lights
|
||||
const directionalLight = new DirectionalLight(0xffffff, 0.8);
|
||||
directionalLight.position.set(0, 50, 20);
|
||||
scene.add(directionalLight);
|
||||
|
||||
directionalLight.castShadow = true;
|
||||
directionalLight.shadow.mapSize.width = 1024;
|
||||
directionalLight.shadow.mapSize.height = 1024;
|
||||
|
||||
const ambientLight = new AmbientLight(0xa3a3a3, 0.3);
|
||||
scene.add(ambientLight);
|
||||
|
||||
// Import models
|
||||
const table = tableModel.scene;
|
||||
scene.add(table);
|
||||
// table.rotateY(Math.PI / 2);
|
||||
table.scale.set(2, 2, 2);
|
||||
table.position.set(0, 1.8, 0);
|
||||
|
||||
table.traverse(function (node: Object3D) {
|
||||
if (node instanceof Mesh) {
|
||||
// node.castShadow = true;
|
||||
node.receiveShadow = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Helpers
|
||||
const gridHelper = new GridHelper(100, 100);
|
||||
scene.add(gridHelper);
|
||||
|
||||
const axesHelper = new AxesHelper(5);
|
||||
scene.add(axesHelper);
|
||||
|
||||
const directionalLightHelper = new DirectionalLightHelper(
|
||||
directionalLight,
|
||||
5
|
||||
);
|
||||
scene.add(directionalLightHelper);
|
||||
|
||||
// Animation
|
||||
const animate = () => {
|
||||
requestAnimationFrame(animate);
|
||||
// cube.rotation.x += 0.01;
|
||||
// cube.rotation.y += 0.01;
|
||||
const currentPlayer = extractCurrentPlayer(gameData);
|
||||
if (currentPlayer) {
|
||||
if (cardsRef.current.length === 0) {
|
||||
cardsRef.current = createPlayerCards(
|
||||
currentPlayer.cards,
|
||||
new Vector3(0, 20, 0)
|
||||
);
|
||||
scene.add(...cardsRef.current);
|
||||
} else {
|
||||
cardsRef.current.forEach((card, index) => {
|
||||
if (card.name !== currentPlayer.cards[index]?.name) {
|
||||
disposeMesh(card);
|
||||
scene.remove(card);
|
||||
cardsRef.current[index] = createCard(
|
||||
currentPlayer.cards[index],
|
||||
card.position
|
||||
);
|
||||
scene.add(cardsRef.current[index]);
|
||||
}
|
||||
});
|
||||
}
|
||||
//const cards = createPlayerCards(currentPlayer.cards);
|
||||
//scene.add(...cards);
|
||||
}
|
||||
|
||||
renderer.render(scene, camera);
|
||||
};
|
||||
|
||||
console.log("Animate");
|
||||
animate();
|
||||
|
||||
return () => {
|
||||
// Clean up on unmount
|
||||
renderer.dispose();
|
||||
// scene.dispose();
|
||||
// material.dispose();
|
||||
// geometry.dispose();
|
||||
container && container.removeChild(renderer.domElement);
|
||||
};
|
||||
}, [gameData]);
|
||||
|
||||
return <div ref={containerRef}></div>;
|
||||
};
|
||||
|
||||
export default ThreeScene;
|
||||
|
|
@ -6,9 +6,10 @@ import {
|
|||
Vector3,
|
||||
Mesh,
|
||||
Object3DEventMap,
|
||||
Object3D,
|
||||
} from "three";
|
||||
|
||||
import { Card } from "../types/gameTypes";
|
||||
import { Card, Deck, VisualColumn, VisualDeck } from "../types/gameTypes";
|
||||
|
||||
const textureLoader = new TextureLoader();
|
||||
const cardSize = 5;
|
||||
|
|
@ -18,7 +19,7 @@ const cardGeometry = new BoxGeometry(
|
|||
cardSize * 0.6
|
||||
);
|
||||
|
||||
const getCardTexture = (value: number | string) => {
|
||||
const getCardTexture = (value: number | null) => {
|
||||
let cardTexture;
|
||||
switch (value) {
|
||||
case -2:
|
||||
|
|
@ -66,7 +67,7 @@ const getCardTexture = (value: number | string) => {
|
|||
case 12:
|
||||
cardTexture = textureLoader.load("/textures/card-12.png");
|
||||
break;
|
||||
case "X":
|
||||
case null:
|
||||
cardTexture = textureLoader.load("/textures/card-back.png");
|
||||
break;
|
||||
default:
|
||||
|
|
@ -78,44 +79,38 @@ const getCardTexture = (value: number | string) => {
|
|||
};
|
||||
|
||||
export const createCard = (
|
||||
cardData: Card,
|
||||
card: Card,
|
||||
position: Vector3,
|
||||
faceUp: boolean = false
|
||||
) => {
|
||||
const cardMaterial = [
|
||||
new MeshBasicMaterial(),
|
||||
new MeshBasicMaterial(),
|
||||
new MeshBasicMaterial({ map: getCardTexture("X") }), // X = backside
|
||||
new MeshBasicMaterial({ map: getCardTexture(cardData.value) }),
|
||||
new MeshBasicMaterial({ map: getCardTexture(null) }), // X = backside
|
||||
new MeshBasicMaterial({ map: getCardTexture(card) }),
|
||||
new MeshBasicMaterial(),
|
||||
new MeshBasicMaterial(),
|
||||
];
|
||||
const card = new Mesh(cardGeometry, cardMaterial);
|
||||
card.name = cardData.name;
|
||||
card.position.copy(position);
|
||||
const visualCard = new Mesh(cardGeometry, cardMaterial);
|
||||
visualCard.name = card !== null ? card.toString() : "Facedown card";
|
||||
visualCard.position.copy(position);
|
||||
|
||||
if (faceUp) {
|
||||
card.rotation.x = Math.PI;
|
||||
console.log("faceUp");
|
||||
visualCard.rotation.x = Math.PI;
|
||||
}
|
||||
|
||||
return card;
|
||||
return visualCard;
|
||||
};
|
||||
|
||||
export const createPlayerCards = (
|
||||
cards: Card[],
|
||||
positionReference: Vector3
|
||||
) => {
|
||||
const playerCards: Mesh<
|
||||
BoxGeometry,
|
||||
MeshBasicMaterial[],
|
||||
Object3DEventMap
|
||||
>[] = [];
|
||||
cards.forEach((card, index) => {
|
||||
const cardPositionX = positionReference.x + (index % 4) * 4 - 6;
|
||||
export const createPlayerCards = (deck: Deck, positionReference: Vector3) => {
|
||||
const playerDeck: Object3D[][] = [];
|
||||
|
||||
let visualColumn: Object3D[] = [];
|
||||
deck.forEach((column, columnIndex) => {
|
||||
column.forEach((card, cardIndex) => {
|
||||
const cardPositionX = positionReference.x + columnIndex * 4 - 6;
|
||||
const cardPositionY = positionReference.y;
|
||||
const cardPositionZ =
|
||||
positionReference.z + (Math.ceil((index + 1) / 4) - 1) * 4 - 8;
|
||||
const cardPositionZ = positionReference.z + cardIndex * 4 - 8;
|
||||
|
||||
const cardPosition = new Vector3(
|
||||
cardPositionX,
|
||||
|
|
@ -123,9 +118,14 @@ export const createPlayerCards = (
|
|||
cardPositionZ
|
||||
);
|
||||
const playerCard = createCard(card, cardPosition);
|
||||
playerCards.push(playerCard);
|
||||
visualColumn.push(playerCard);
|
||||
if (cardIndex === 2) {
|
||||
playerDeck.push(visualColumn as VisualColumn);
|
||||
visualColumn = [];
|
||||
}
|
||||
});
|
||||
return playerCards;
|
||||
});
|
||||
return playerDeck as VisualDeck;
|
||||
};
|
||||
|
||||
export const createCardStaple = (
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ export type Player = {
|
|||
id: number;
|
||||
socketId: string;
|
||||
name: string;
|
||||
cards: Card[];
|
||||
knownCardPositions: boolean[];
|
||||
deck: Deck;
|
||||
knownCardPositions: KnownCardsColumn[];
|
||||
playersTurn: boolean;
|
||||
cardCache: Card | null;
|
||||
tookDispiledCard: boolean;
|
||||
|
|
@ -15,12 +15,21 @@ export type Player = {
|
|||
place: number;
|
||||
};
|
||||
|
||||
export type PlayerWithVisualCards = {
|
||||
export type PlayerVisualDeck = {
|
||||
player: Player;
|
||||
cards: Object3D[];
|
||||
visualDeck: VisualDeck;
|
||||
};
|
||||
|
||||
export type CardValue =
|
||||
export type VisualColumn = [Object3D, Object3D, Object3D];
|
||||
|
||||
export type VisualDeck = VisualColumn[];
|
||||
|
||||
export type Column = [Card, Card, Card];
|
||||
export type KnownCardsColumn = [boolean, boolean, boolean];
|
||||
|
||||
export type Deck = Column[];
|
||||
|
||||
export type Card =
|
||||
| -2
|
||||
| -1
|
||||
| 0
|
||||
|
|
@ -36,13 +45,7 @@ export type CardValue =
|
|||
| 10
|
||||
| 11
|
||||
| 12
|
||||
| "X";
|
||||
|
||||
export type Card = {
|
||||
id: number;
|
||||
name: string;
|
||||
value: CardValue;
|
||||
};
|
||||
| null;
|
||||
|
||||
export type CardStack = {
|
||||
cards: Card[];
|
||||
|
|
|
|||
Loading…
Reference in a new issue