basic drawing

This commit is contained in:
2025-08-03 14:43:29 -04:00
parent e4f6e1899d
commit 0124b69440
9 changed files with 200 additions and 38 deletions

BIN
assets/sources/Card_back_01.svg LFS Normal file

Binary file not shown.

1
assets/views/back.svg Symbolic link
View File

@@ -0,0 +1 @@
../sources/Card_back_01.svg

View File

@@ -28,6 +28,10 @@ body::before {
width: 100%;
}
.w-full {
width: 100%;
}
.center {
display: flex;
justify-content: center;

View File

@@ -1,4 +1,4 @@
import { Component, createResource, Suspense } from "solid-js";
import { Component, createResource, JSX, Suspense } from "solid-js";
import { Card } from "../types/cards";
const cardToSvgFilename = (card: Card) => {
@@ -7,24 +7,43 @@ const cardToSvgFilename = (card: Card) => {
}
const value =
{ ace: 1, jack: 11, queen: 12, king: 13 }[card.rank] ??
(card.rank as number);
{ ace: 1, jack: 11, queen: 12, king: 13 }[
card.rank as "ace" | "jack" | "queen" | "king" // fuck you typescript
] ?? (card.rank as number);
return `${card.suit.toUpperCase()}-${value}${
value >= 11 ? "-" + (card.rank as string).toUpperCase() : ""
}`;
};
export default ((props) => {
const [svgPath] = createResource(
() =>
import(
`~/../assets/views/cards/${cardToSvgFilename(props.card)}.svg`
const [svgPath] = createResource(() =>
props.face == "down"
? // @ts-ignore
import("~/../assets/views/back.svg")
: import(
`~/../assets/views/cards/${cardToSvgFilename(
props.card
)}.svg`
)
);
return (
<Suspense>
<img src={svgPath()?.default} />
<img
draggable={false}
class={props.class}
style={{
"border-radius": "5px",
...props.style,
}}
width="100px"
src={svgPath()?.default}
/>
</Suspense>
);
}) satisfies Component<{ card: Card }>;
}) satisfies Component<{
class?: string;
style?: JSX.CSSProperties;
card: Card;
face?: "up" | "down";
}>;

View File

@@ -1,15 +1,40 @@
import { JSX } from "solid-js";
import { createContext, JSX } from "solid-js";
import Card from "./Card";
import Hand from "./Hand";
import Pile from "./Pile";
import { newDeck, shuffle, Hand as THand } from "../types/cards";
import { createStore, produce } from "solid-js/store";
const GameContext = createContext();
export default () => {
const [gameState, setGameState] = createStore({
pile: shuffle(newDeck()),
hand: [] as THand,
});
return (
<GameContext.Provider value={{ gameState, setGameState }}>
<div
class="full center column"
onClick={() => {}}
class="full column"
style={{ "row-gap": "20px", "font-size": "32px" }}
>
games
<Card card={{ kind: "joker", color: "red" }} />
coming soon
<div class="full center">
<Pile
pile={gameState.pile}
style={{ cursor: "pointer" }}
onClick={() =>
setGameState(
produce((state) => {
state.hand.push(state.pile.pop()!);
})
)
}
/>
</div>
<Hand hand={gameState.hand} />
</div>
</GameContext.Provider>
);
};

View File

@@ -0,0 +1,24 @@
import { Component, For } from "solid-js";
import Card from "./Card";
import { Hand } from "../types/cards";
export default ((props) => {
return (
<div
style={{
border: "2px dashed white",
"border-radius": "12px",
margin: "10px",
"margin-bottom": "25px",
padding: "10px",
height: "200px",
overflow: "scroll",
"scrollbar-width": "none",
display: "flex",
gap: "5px",
}}
>
<For each={props.hand}>{(card) => <Card card={card} />}</For>
</div>
);
}) satisfies Component<{ hand: Hand }>;

View File

@@ -0,0 +1,44 @@
import { Component, For, JSX } from "solid-js";
import Card from "./Card";
import { Pile } from "../types/cards";
export default ((props) => {
return (
<div
class="center"
style={{ width: "200px", height: "400px", ...props.style }}
onClick={props.onClick}
>
<For each={props.pile}>
{(card, i) => (
<Card
card={card}
face="down"
style={{
position: "absolute",
transform: `translate(${i() * 0.8}px, ${
-i() * 0.4
}px)`,
"z-index": 100 - i(),
border: `0.1px solid rgb(${
60 - i() + Math.random() * 10
}, ${60 - i() + Math.random() * 10}, ${
60 - i() + Math.random() * 10
});`,
}}
/>
)}
</For>
</div>
);
}) satisfies Component<{
pile: Pile;
style?: JSX.CSSProperties;
onClick?:
| JSX.EventHandlerUnion<
HTMLDivElement,
MouseEvent,
JSX.EventHandler<HTMLDivElement, MouseEvent>
>
| undefined;
}>;

View File

@@ -1,6 +1,23 @@
export type Suit = "heart" | "diamond" | "spade" | "club";
const suits = ["heart", "diamond", "spade", "club"] as const;
export type Suit = (typeof suits)[number];
const ranks = [
2,
3,
4,
5,
6,
7,
8,
9,
10,
"jack",
"queen",
"king",
"ace",
] as const;
export type Rank = (typeof ranks)[number];
type Rank = number | "jack" | "queen" | "king" | "ace";
export type Card =
| {
kind: "normal";
@@ -13,3 +30,28 @@ export type Pile = Card[];
export type Stack = Card[];
export type Hand = Card[];
export type Board = Card[];
export const newDeck = (withJokers = false): Pile =>
suits
.map((suit) =>
ranks.map((rank) => ({ kind: "normal", suit, rank } as Card))
)
.flat()
.concat(
withJokers
? [
{ kind: "joker", color: "red" },
{ kind: "joker", color: "black" },
]
: []
);
export const shuffle = (cards: Card[]) => {
let i = cards.length;
while (i > 0) {
const j = Math.floor(Math.random() * i);
i--;
[cards[i], cards[j]] = [cards[j], cards[i]];
}
return cards;
};