From 3adf3bf76d621a7cd2faaa62a9a71ec9395d5fd5 Mon Sep 17 00:00:00 2001 From: Dylan Pizzo Date: Tue, 7 Jan 2025 08:10:47 -0800 Subject: [PATCH] add vp symbols --- src/client/App.tsx | 8 +-- src/dominiontext.ts | 139 +++++++++----------------------------------- src/draw.ts | 8 +++ src/sampleData.ts | 93 ++++++++++++++++------------- 4 files changed, 94 insertions(+), 154 deletions(-) diff --git a/src/client/App.tsx b/src/client/App.tsx index ee0bc08..3a52d31 100644 --- a/src/client/App.tsx +++ b/src/client/App.tsx @@ -1,13 +1,13 @@ import { useState } from "react"; -import { sampleCard1, sampleCard2, sampleCard3 } from "../sampleData.ts"; +import { sampleCards } from "../sampleData.ts"; import { Card } from "./Card.tsx"; export const App = () => { const [count, setCount] = useState(0); return
- - - + {sampleCards.map((sampleCard) => { + return + })}
; }; diff --git a/src/dominiontext.ts b/src/dominiontext.ts index 3fa05f2..b1ad252 100644 --- a/src/dominiontext.ts +++ b/src/dominiontext.ts @@ -5,9 +5,12 @@ export type Piece = | { type: "text"; text: string; isBold?: boolean; isItalic?: boolean } | { type: "space" } | { type: "break" } - | { type: "coin"; text: string } - | { type: "debt"; text: string } - | { type: "potion"; text: string }; + | { + type: "symbol"; + symbol: "coin" | "debt" | "potion" | "vp" | "vp-token"; + text: string; + textColor: string; + }; type PromiseOr = T | Promise; @@ -124,14 +127,14 @@ const breakPiece = pieceDef({ render() {}, }); -const coinPiece = pieceDef({ - type: "coin", - measure(context, _piece) { +const symbolPiece = pieceDef({ + type: "symbol", + measure(context, piece) { context.save(); const metrics = context.measureText(" "); const height = metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; - const coinImage = getImage("coin"); + const coinImage = getImage(piece.symbol); context.restore(); return { type: "content", @@ -146,7 +149,7 @@ const coinPiece = pieceDef({ const height = measure.ascent + measure.descent; // context.fillRect(x, y - measure.ascent, measure.width, height); context.drawImage( - getImage("coin"), + getImage(piece.symbol), x, y - measure.ascent, measure.width, @@ -158,103 +161,14 @@ const coinPiece = pieceDef({ fontInfo.size = parseInt(fontInfo.size.toString()) * 1.2; const font = stringifyFont(fontInfo); context.font = font; - context.fillStyle = "black"; + context.fillStyle = piece.textColor; context.textAlign = "center"; context.fillText(piece.text, x + measure.width / 2, y); context.restore(); }, }); -const debtPiece = pieceDef({ - type: "debt", - measure(context, _piece) { - context.save(); - const metrics = context.measureText(" "); - const height = - metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; - const coinImage = getImage("debt"); - context.restore(); - return { - type: "content", - width: coinImage.width * (height / coinImage.height), - ascent: metrics.fontBoundingBoxAscent, - descent: metrics.fontBoundingBoxDescent, - }; - }, - render(context, piece, x, y, measure) { - context.save(); - // context.fillStyle = "yellow"; - const height = measure.ascent + measure.descent; - // context.fillRect(x, y - measure.ascent, measure.width, height); - context.drawImage( - getImage("debt"), - x, - y - measure.ascent, - measure.width, - height - ); - const fontInfo = parseFont(context.font); - fontInfo.family = ["DominionSpecial"]; - fontInfo.weight = "bold"; - fontInfo.size = parseInt(fontInfo.size.toString()) * 1.2; - const font = stringifyFont(fontInfo); - context.font = font; - context.fillStyle = "white"; - context.textAlign = "center"; - context.fillText(piece.text, x + measure.width / 2, y); - context.restore(); - }, -}); - -const potionPiece = pieceDef({ - type: "potion", - measure(context, _piece) { - context.save(); - const metrics = context.measureText(" "); - const height = - metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent; - const coinImage = getImage("potion"); - context.restore(); - return { - type: "content", - width: coinImage.width * (height / coinImage.height), - ascent: metrics.fontBoundingBoxAscent, - descent: metrics.fontBoundingBoxDescent, - }; - }, - render(context, piece, x, y, measure) { - context.save(); - // context.fillStyle = "yellow"; - const height = measure.ascent + measure.descent; - // context.fillRect(x, y - measure.ascent, measure.width, height); - context.drawImage( - getImage("potion"), - x, - y - measure.ascent, - measure.width, - height - ); - const fontInfo = parseFont(context.font); - fontInfo.family = ["DominionSpecial"]; - fontInfo.weight = "bold"; - fontInfo.size = parseInt(fontInfo.size.toString()) * 1.2; - const font = stringifyFont(fontInfo); - context.font = font; - context.fillStyle = "white"; - context.textAlign = "center"; - context.fillText(piece.text, x + measure.width / 2, y); - context.restore(); - }, -}); - -const pieceDefs = [ - textPiece, - spacePiece, - breakPiece, - coinPiece, - debtPiece, - potionPiece, -]; +const pieceDefs = [textPiece, spacePiece, breakPiece, symbolPiece]; const tools: PieceTools = {} as any; @@ -406,23 +320,28 @@ export const renderDominionText = async ( export const parse = (text: string): Piece[] => { const pieces: Piece[] = []; + const symbolMap = { + "$": { symbol: "coin", textColor: "black" }, + "@": { symbol: "debt", textColor: "white" }, + "^": { symbol: "potion", textColor: "white" }, + "%": { symbol: "vp", textColor: "white" }, + "#": { symbol: "vp-token", textColor: "black" }, + } as const; for (let i = 0; i < text.length; i++) { const char = text[i]; if (char === " ") { pieces.push({ type: "space" }); } else if (char === "\n") { pieces.push({ type: "break" }); - } else if (char === "$") { - const end = text.slice(i).match(/\$\d*/)![0].length; - pieces.push({ type: "coin", text: text.slice(i + 1, i + end) }); - i += end - 1; - } else if (char === "@") { - const end = text.slice(i).match(/@\d*/)![0].length; - pieces.push({ type: "debt", text: text.slice(i + 1, i + end) }); - i += end - 1; - } else if (char === "^") { - const end = text.slice(i).match(/\^\d*/)![0].length; - pieces.push({ type: "potion", text: text.slice(i + 1, i + end) }); + } else if (char && char in symbolMap) { + const c = char as keyof typeof symbolMap; + const end = text.slice(i).match(new RegExp(`\\${c}\\w*`))![0] + .length; + pieces.push({ + type: "symbol", + ...symbolMap[c], + text: text.slice(i + 1, i + end), + }); i += end - 1; } else if (char === "+") { const match = text.slice(i).match(/\+\d* \w+/); diff --git a/src/draw.ts b/src/draw.ts index d2aed09..d337d9b 100644 --- a/src/draw.ts +++ b/src/draw.ts @@ -59,6 +59,14 @@ const imageList = [ key: "potion", src: "/static/assets/Potion.png", }, + { + key: "vp", + src: "/static/assets/VP.png", + }, + { + key: "vp-token", + src: "/static/assets/VP-Token.png", + }, ]; export const loadImages = async () => { diff --git a/src/sampleData.ts b/src/sampleData.ts index e569f95..5db3286 100644 --- a/src/sampleData.ts +++ b/src/sampleData.ts @@ -3,45 +3,58 @@ import { TYPE_ACTION, TYPE_REACTION, TYPE_TREASURE, + TYPE_VICTORY, } from "./types.ts"; -export const sampleCard1: DominionCard = { - orientation: "card", - title: "Title", - description: - "+1 Action\n\nReveal the top card of your deck. If it's an Action card, +1 Action.", - types: [TYPE_ACTION, TYPE_REACTION], - image: "https://wiki.dominionstrategy.com/images/7/76/AdventurerArt.jpg", - artist: "Dall-E", - author: "John Doe", - version: "", - cost: "@8", - preview: "", -}; - -export const sampleCard2: DominionCard = { - orientation: "card", - title: "Market", - description: "+1 Card\n+1 Action\n+1 Buy\n+$1", - types: [TYPE_ACTION], - image: "", - artist: "Leonardo DaVinci", - author: "Jane Smith", - version: "", - cost: "$4", - preview: "", -}; - -export const sampleCard3: DominionCard = { - orientation: "card", - title: "Flask", - description: - "+2 Cards\n\nAt the start of your Clean-up phase, you may put a card from your hand onto your deck.", - types: [TYPE_TREASURE], - image: "", - artist: "", - author: "", - version: "", - cost: "$6", - preview: "", -}; +export const sampleCards: DominionCard[] = [ + { + orientation: "card", + title: "Title", + description: + "+1 Action\n\nReveal the top card of your deck. If it's an Action card, +1 Action. If it has ^ in its cost, +1 Card.", + types: [TYPE_ACTION, TYPE_REACTION], + image: "https://wiki.dominionstrategy.com/images/7/76/AdventurerArt.jpg", + artist: "Dall-E", + author: "John Doe", + version: "", + cost: "@8", + preview: "", + }, + { + orientation: "card", + title: "Market", + description: "+1 Card\n+1 Action\n+1 Buy\n+$1", + types: [TYPE_ACTION], + image: "", + artist: "Leonardo DaVinci", + author: "Jane Smith", + version: "", + cost: "$4", + preview: "", + }, + { + orientation: "card", + title: "Flask", + description: + "+2 Cards\n\nAt the start of your Clean-up phase, you may put a card from your hand onto your deck.", + types: [TYPE_TREASURE], + image: "", + artist: "", + author: "", + version: "", + cost: "$6", + preview: "", + }, + { + orientation: "card", + title: "Flask", + description: "+1 #\n\n-\n\n2 %", + types: [TYPE_VICTORY], + image: "", + artist: "", + author: "", + version: "", + cost: "$6", + preview: "", + }, +];