holding cards, kinda

This commit is contained in:
2025-08-27 23:00:01 -04:00
parent 686529507e
commit d69336027a
6 changed files with 43 additions and 20 deletions

View File

@@ -1,7 +1,7 @@
import { Component, Suspense } from "solid-js"; import { Component, Suspense } from "solid-js";
import type { Card } from "@games/shared/cards"; import type { Card } from "@games/shared/cards";
import { Clickable, Stylable } from "./toolbox"; import { Clickable, Sizable, Stylable } from "./toolbox";
const cardToSvgFilename = (card: Card) => { const cardToSvgFilename = (card: Card) => {
if (card.kind == "joker") { if (card.kind == "joker") {
@@ -25,7 +25,8 @@ export default ((props) => {
draggable={false} draggable={false}
class={props.class} class={props.class}
style={props.style} style={props.style}
width="100px" width={props.width ?? "100px"}
height={props.height}
src={ src={
props.face == "down" props.face == "down"
? "/views/back.svg" ? "/views/back.svg"
@@ -43,5 +44,6 @@ export default ((props) => {
| { card?: Card; face: "down" } | { card?: Card; face: "down" }
) & ) &
Stylable & Stylable &
Clickable Clickable &
Sizable
>; >;

View File

@@ -4,18 +4,26 @@ import Card from "./Card";
export default (props: { handCount: number }) => { export default (props: { handCount: number }) => {
return ( return (
<div class="flex">
<For each={Array(props.handCount)}> <For each={Array(props.handCount)}>
{() => ( {(_, i) => {
const midOffset = i() + 0.5 - props.handCount / 2;
return (
<Card <Card
face="down" face="down"
width="40px"
style={{ style={{
"margin-left": "-15px", "margin-left": "-10px",
transform: "translate(0, 40px)", "margin-right": "-10px",
transform: `rotate(${
midOffset * 0.2
}rad) translate(0px, ${
2 ** Math.abs(midOffset) * 2
}px)`,
"box-shadow": "-4px 4px 4px rgba(0, 0, 0, 0.7)",
}} }}
/> />
)} );
}}
</For> </For>
</div>
); );
}; };

View File

@@ -49,13 +49,22 @@ export default () => {
Quit Quit
</button> </button>
<For each={Object.entries(view().playerHandCounts)}> <For each={Object.entries(view().playerHandCounts)}>
{([playerKey, handCount]) => ( {([playerKey, handCount], i) => (
<Portal <Portal
mount={document.getElementById(`player-${playerKey}`)!} mount={document.getElementById(`player-${playerKey}`)!}
ref={(ref) => {
const midOffset =
i() +
0.5 -
Object.values(view().playerHandCounts).length /
2;
ref.style = `position: absolute; display: flex; justify-content: center; top: 65%; transform: translate(${Math.abs(
midOffset * 0
)}px, 0px) rotate(${midOffset * 1}rad)`;
}}
> >
<div class="absolute center">
<FannedHand handCount={handCount} /> <FannedHand handCount={handCount} />
</div>
</Portal> </Portal>
)} )}
</For> </For>

View File

@@ -65,7 +65,7 @@ export default (props: { tableKey: string }) => {
view, view,
}} }}
> >
<div class="flex justify-around p-t-10"> <div class="flex justify-around p-t-14">
<For each={players().filter((p) => p != me())}> <For each={players().filter((p) => p != me())}>
{(player, i) => { {(player, i) => {
const verticalOffset = () => { const verticalOffset = () => {

View File

@@ -14,3 +14,8 @@ export type Clickable = {
> >
| undefined; | undefined;
}; };
export type Sizable = {
width?: string;
height?: string;
};

View File

@@ -10,7 +10,6 @@ import dayjs from "dayjs";
import db from "./db"; import db from "./db";
import { liveTable, WsOut, WsIn } from "./table"; import { liveTable, WsOut, WsIn } from "./table";
import { Human } from "@prisma/client"; import { Human } from "@prisma/client";
import _ from "lodash";
import { combine } from "kefir"; import { combine } from "kefir";
const api = new Elysia({ prefix: "/api" }) const api = new Elysia({ prefix: "/api" })
@@ -89,9 +88,9 @@ const api = new Elysia({ prefix: "/api" })
send({ players }) send({ players })
); );
table.outputs.playersReady.onValue((readys) => table.outputs.playersReady
send({ playersReady: readys }) .skipDuplicates()
); .onValue((readys) => send({ playersReady: readys }));
combine( combine(
[table.outputs.gameState], [table.outputs.gameState],