Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix avatars #58

Merged
merged 1 commit into from
Oct 15, 2024
Merged
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
2 changes: 1 addition & 1 deletion apps/web/src/app/games/[id]/components/DownloadModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function DownloadModal() {
if (isLoading)
return (
<Modal closeButton={false} className="w-96 h-52 animate-grow-in">
<div className="flex text-nowrap text-sm flex-col items-center gap-1 text-white text-center">
<div className="flex text-sm flex-col items-center gap-1 text-white text-center">
{percentage ? (
<>
Downloading assets
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/games/[id]/components/PlayerActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default function PlayerActions() {
actions.map((action) => (
<button
key={action}
className={`capitalize focus:outline-[#b87d5b] z-20 relative nes-btn is-warning disabled:hover:cursor-not-allowed w-full py-2 sm:py-4 text-[10px] sm:text-base text-white flex hover:brightness-90 ${
className={`capitalize text-center focus:outline-[#b87d5b] z-20 relative nes-btn is-warning disabled:hover:cursor-not-allowed w-full py-2 sm:py-4 text-[10px] sm:text-base text-white flex hover:brightness-90 ${
isActionQueued && queuedAction === action ? "cursor-pointer" : ""
}`}
onClick={() => handlePlayerAction(action)}
Expand Down
11 changes: 6 additions & 5 deletions apps/web/src/app/games/[id]/components/Pot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@ export default function Pot({ players }: { players: (UIPlayer | null)[] }) {
const [betting, setBetting] = useState(false);
const pot = useSelector(selectPot$());
const gameStatus = useSelector(selectGameStatus$());
const raisedSeats = mockPlayers.reduce<number[]>((acc, curr, i) => {
const raisedSeats = players.reduce<number[]>((acc, curr, i) => {
if (
curr.roundAction?.action === BettingActions.CALL ||
curr.roundAction?.action === BettingActions.RAISE
curr &&
(curr.roundAction?.action === BettingActions.CALL ||
curr.roundAction?.action === BettingActions.RAISE)
) {
acc.push(i + 1);
}
return acc;
}, []);

const winnerSeats = mockPlayers?.reduce<number[]>((acc, curr, i) => {
if (curr.winAmount && curr.winAmount > 0) {
const winnerSeats = players?.reduce<number[]>((acc, curr, i) => {
if (curr?.winAmount && curr.winAmount > 0) {
acc.push(i + 1);
}
return acc;
Expand Down
18 changes: 13 additions & 5 deletions apps/web/src/app/games/[id]/components/PrivateCards.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { GameStatus } from "@jeton/ts-sdk";
import { useSelector } from "@legendapp/state/react";
import dealCardSound from "@src/assets/audio/effects/card-place.mp3";
import { useAudio } from "@src/hooks/useAudio";
import { CARDS_MAP } from "@src/lib/constants/cards";
import { mockPrivateCards } from "@src/lib/constants/mocks";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { selectGameStatus$ } from "../state/selectors/gameSelectors";
import Card from "./Card";

export default function PrivateCards({
playersPrivateCards,
}: {
playersPrivateCards: Record<number /* seat number start from */, number[]> | null;
}) {
const [receivedCards, setReceivedCards] = useState(true);
const gameStatus = useSelector(selectGameStatus$());
const [receivedCards, setReceivedCards] = useState(false);
const [revealedCards, setRevealedCards] = useState(false);
const [dealCards, setDealCards] = useState<number[]>([]);
const dealCardEffect = useAudio(dealCardSound, "effect");
Expand Down Expand Up @@ -38,10 +42,14 @@ export default function PrivateCards({
}, [seats, dealCardEffect]);

useEffect(() => {
setTimeout(() => {
setRevealedCards(true);
}, 3000);
}, []);
if (gameStatus === GameStatus.ShowDown) {
setReceivedCards(true);

setTimeout(() => {
setRevealedCards(true);
}, 600);
}
});

return (
<>
Expand Down
47 changes: 27 additions & 20 deletions apps/web/src/app/games/[id]/components/Seat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import Avatar9 from "@src/assets/images/avatars/avatar-9.png";
import Avatar10 from "@src/assets/images/avatars/avatar-10.png";
import WinnerStuff from "@src/assets/images/champagne-pixel-animated.gif";
import Chip from "@src/assets/images/chips/chip.png";
import { mockPlayers } from "@src/lib/constants/mocks";
import Image from "next/image";
import Image, { type StaticImageData } from "next/image";
import { useEffect, useMemo, useRef, useState } from "react";
import {
selectAwaitingBetFrom$,
Expand All @@ -25,6 +24,7 @@ import {
import type { UIPlayer } from "../state/state";
import DealerBadge from "./DealerBadge";

// Define the avatars array as a constant
const avatars = [
Avatar1,
Avatar2,
Expand All @@ -38,18 +38,19 @@ const avatars = [
Avatar10,
];

function assignUniqueAvatars(players: (UIPlayer | null)[]): Record<string, string> {
// Function to assign unique avatars to players
function assignUniqueAvatars(players: (UIPlayer | null)[]): Record<string, StaticImageData> {
const availableAvatars = [...avatars];
const assignedAvatars: Record<string, string> = {};
const assignedAvatars: Record<string, StaticImageData> = {};

players.forEach((player) => {
if (!player) return;
if (!assignedAvatars[player.id]) {
const avatarIndex = hashPlayerIDToAvatar(player.id, availableAvatars.length);

const assignedAvatar = String(availableAvatars[avatarIndex]);
const assignedAvatar = availableAvatars[avatarIndex];

assignedAvatars[player.id] = assignedAvatar;
assignedAvatars[player.id] = assignedAvatar ?? Avatar1;

availableAvatars.splice(avatarIndex, 1);
}
Expand All @@ -58,6 +59,7 @@ function assignUniqueAvatars(players: (UIPlayer | null)[]): Record<string, strin
return assignedAvatars;
}

// Function to hash player IDs and assign avatar
function hashPlayerIDToAvatar(id: string, avatarCount: number): number {
let hash = 0;
for (let i = 0; i < id.length; i++) {
Expand All @@ -75,54 +77,58 @@ export default function Seat({
}) {
const mounted = useRef(false);

// Selectors from the state
const players = useSelector(selectGamePlayers$());
const shufflingPlayer = useSelector(selectShufflingPlayer$());
const awaitingBetFrom = useSelector(selectAwaitingBetFrom$());
const isPlayerTurn = awaitingBetFrom?.id === player.id;
const dealer = useSelector(selectDealer$());
const gameStatus = useSelector(selectGameStatus$());
const [lastAction, setLastAction] = useState("");

const [lastAction, setLastAction] = useState<string>("");
const isWinner = player.winAmount && player.winAmount > 0;

// Use `useMemo` to assign avatars
const assignedAvatars = useMemo(() => (players ? assignUniqueAvatars(players) : {}), [players]);

const playerAvatar = assignedAvatars[player.id];
const playerAvatar = assignedAvatars[player.id] ?? Avatar1;

const isMainPlayerCards = useMemo(() => {
return seatNumber === 1;
}, [seatNumber]);

useEffect(() => {
if (mounted.current) return;

mounted.current = true;
}, []);

// Reset last action based on game status
useEffect(() => {
console.log("status: ", gameStatus);

if (
gameStatus === GameStatus.DrawRiver ||
gameStatus === GameStatus.DrawFlop ||
gameStatus === GameStatus.DrawTurn
gameStatus === GameStatus.DrawTurn ||
isPlayerTurn
) {
setLastAction("");
}
}, [gameStatus]);
}, [gameStatus, isPlayerTurn]);

// Update last action for the player
useEffect(() => {
if (player.roundAction) {
const { action, amount } = player.roundAction;
setLastAction(`${action} ${amount}`);
}
});
}, [player.roundAction]);

return (
<div
className={`seat-position items-center flex z-30 shrink-0 md:w-28 xl:w-36 w-6 grow-0 duration-1000 ${
className={`seat-position items-center flex z-30 shrink-0 md:w-28 xl:w-36 w-6 grow-0 duration-1000 ${
shufflingPlayer?.id === player.id
? "seat-dealer scale-110"
: `seat-${seatNumber} ${2 > Math.random() ? "z-[501]" : ""} ${
player.status === PlayerStatus.sittingOut ? "opacity-80" : ""
}`
: `seat-${seatNumber} ${player.status === PlayerStatus.sittingOut ? "opacity-80" : ""}`
}`}
style={{ animationDelay: `${seatNumber * 100 + 100}ms` }}
>
Expand All @@ -133,7 +139,7 @@ export default function Seat({
>
<Image
draggable={false}
src={playerAvatar ?? ""}
src={playerAvatar} // playerAvatar is always a valid image
alt="avatar"
className={`aspect-square object-contain bg-black/70 h-full animate-grow-in grow-0 rounded-full shrink-0 border-2 md:border-8 ${
shufflingPlayer?.id === player.id ? "scale-125 animate-bounce delay-1000" : ""
Expand All @@ -147,7 +153,7 @@ export default function Seat({
}}
/>
<div className="bg-black/70 shrink-0 flex-col sm:border border-amber-300 rounded-sm line-clamp-1 relative flex justify-center text-[6px] text-white text-center shadow-2xl md:text-sm px-1 divide-y divide-white/50">
<span>{seatNumber === 1 ? "me" : player.id.slice(2, 8)} </span>
<span>{seatNumber === 1 ? "me" : player.id.slice(2, 8)}</span>
<span className="flex items-center justify-center">
<Image src={Chip} alt="chip" className="w-6 sm:block hidden" />
{player.balance}
Expand All @@ -160,7 +166,7 @@ export default function Seat({
className={`absolute top-0 -right-5 sm:-right-14 animate-grow-in ${
isWinner ? "animate-tada" : ""
}`}
alt="chicken winner"
alt="winner badge"
src={WinnerStuff}
/>
)}
Expand All @@ -183,6 +189,7 @@ export default function Seat({
</div>
</>
)}

{dealer?.id === player.id && <DealerBadge />}
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/app/games/[id]/components/ShufflingCards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const ShufflingCards = () => {
{angles.map((angle, index) => (
<div
key={angle}
className={`w-24 h-32 mx-2 rounded-lg bg-[url("/images/card-back.png")] bg-no-repeat bg-contain justify-center absolute animate-cardLoop`}
className={`md:w-16 md:h-24 2xl:w-24 2xl:h-32 mx-2 rounded-lg bg-[url("/images/card-back.png")] bg-no-repeat bg-contain justify-center absolute animate-cardLoop`}
style={{
transformOrigin: "20% 80%",
zIndex: positions[index]?.zIndex,
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
.chips,
.cards {
position: absolute;
will-change: transform;
}

@media (min-width: 768px) {
Expand Down
4 changes: 2 additions & 2 deletions apps/web/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ module.exports = {
"100%": { transform: "scale3d(1, 1, 1)" },
},
cardAnimation: {
"0%, 100%": { transform: "rotate(0deg)" },
"0%, 100%": { transform: "rotate(0deg) rotateY(0deg)" },
"30%": { transform: "rotate(360deg)" },
"50%": { transform: "rotateY(180deg)" },
"70%": { transform: "rotate(360deg)" },
"70%": { transform: "rotate(360deg) " },
},
deal: {
"0%": {
Expand Down
2 changes: 1 addition & 1 deletion packages/tailwindcss-config/base-tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ const config = {
"slide-in": "slideIn 1s ease-out",
"grow-in": "growIn 0.5s ease-out",
"flip-y": "flip 1s",
fading: "fading 2s infinite",
fading: "fading 1.5s",
headShake: "headShake 1s ease-in-out .5s",
},
},
Expand Down