add some cards and fix some coloring
This commit is contained in:
parent
7a752a92cb
commit
4d318d20ee
207
src/cards.ts
207
src/cards.ts
@ -1,8 +1,29 @@
|
||||
import { DominionCard, TYPE_TREASURE, TYPE_VICTORY } from "./types.ts";
|
||||
import {
|
||||
DominionCard,
|
||||
TYPE_ACTION,
|
||||
TYPE_DURATION,
|
||||
TYPE_NIGHT,
|
||||
TYPE_TREASURE,
|
||||
TYPE_VICTORY,
|
||||
} from "./types.ts";
|
||||
|
||||
const expansionIcon = "";
|
||||
const author = "Dylan";
|
||||
|
||||
const sampleCard = {
|
||||
orientation: "card",
|
||||
title: "Sample",
|
||||
description: "",
|
||||
types: [TYPE_ACTION],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "0.1",
|
||||
cost: "$",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
};
|
||||
|
||||
export const cards: DominionCard[] = [
|
||||
{
|
||||
orientation: "card",
|
||||
@ -21,14 +42,194 @@ export const cards: DominionCard[] = [
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Promising Land",
|
||||
description: "Worth 1% per 3 cards you have that cost $4 or $5.",
|
||||
description: "Worth 1% per 4 cards you have that cost $4 or $5.",
|
||||
types: [TYPE_VICTORY],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "",
|
||||
version: "0.1",
|
||||
cost: "$4",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Steelworker",
|
||||
description:
|
||||
"If it's your Action phase, +3 Cards.\n\nIf it's your Buy phase, +1 Buy, and +$1.",
|
||||
types: [TYPE_ACTION, TYPE_TREASURE],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "0.2",
|
||||
cost: "$5",
|
||||
preview: "$?",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Shovel",
|
||||
description:
|
||||
"Play a Treasure card from your hand. Then trash it from play to gain a Treasure card costing up to $3 more than it.",
|
||||
types: [TYPE_TREASURE],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "0.1",
|
||||
cost: "$6",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "High Council",
|
||||
description:
|
||||
"+2 Cards\n+1 Action\n+1 Buy\n\nEach player (including you) may choose one: +1 Card, or trash a card from their hand.",
|
||||
types: [TYPE_ACTION],
|
||||
image: "",
|
||||
artist: "",
|
||||
author: "Lou + Dylan",
|
||||
version: "0.1",
|
||||
cost: "$7",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Productive Village",
|
||||
description:
|
||||
"If it's your Action phase, +3 Actions.\n\nIf it's your Buy phase, +$1 per unused Action you have (Action, not Action card). +$1 if you have no Actions.",
|
||||
types: [TYPE_ACTION, TYPE_TREASURE],
|
||||
image: "",
|
||||
artist: "",
|
||||
author: "Dylan",
|
||||
version: "0.1",
|
||||
cost: "$3",
|
||||
preview: "$?",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Secret Society",
|
||||
description:
|
||||
"+1 Action\n\nIf you have at least 3 copies of Secret Society in play, trash all of them to gain any number of cards costing at least $2, whose total combined cost is at most $50.\n\n-\n\nOn your turn, this costs $3 plus $2 per Secret Society you've gained this game.",
|
||||
types: [TYPE_ACTION],
|
||||
image: "",
|
||||
artist: "",
|
||||
author: "Dylan",
|
||||
version: "0.1",
|
||||
cost: "$?",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Eclipse",
|
||||
description:
|
||||
"+1 Card\n\nIf you have no Actions, +1 Action. If you have no Buys, +1 Buy. Return to your Action phase.",
|
||||
types: [TYPE_NIGHT],
|
||||
image: "",
|
||||
artist: "",
|
||||
author: "Dylan",
|
||||
version: "0.1",
|
||||
cost: "$5",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Moonlit Scheme",
|
||||
description: "You may play an Action card from your hand.",
|
||||
types: [TYPE_NIGHT],
|
||||
image: "",
|
||||
artist: "",
|
||||
author: "Dylan",
|
||||
version: "0.1",
|
||||
cost: "$2",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Beaver",
|
||||
description:
|
||||
"Pay $1. If you did, gain a card costing up to the amount of $ you have.",
|
||||
types: [TYPE_NIGHT],
|
||||
image: "",
|
||||
artist: "",
|
||||
author: "Dylan",
|
||||
version: "0.1",
|
||||
cost: "$3",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Silk",
|
||||
description: "Choose one: +$2, or gain a Silver.",
|
||||
types: [TYPE_TREASURE],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "0.1",
|
||||
cost: "$4",
|
||||
preview: "$?",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Foundry",
|
||||
description:
|
||||
"Choose one: +1 Card, +1 Action and +$1; or trash a card from your hand to gain a card that costs up to $2 more than it.",
|
||||
types: [TYPE_ACTION],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "0.1",
|
||||
cost: "$5",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Vendor",
|
||||
description:
|
||||
"Choose three different options: +1 Card, +1 Action, +1 Buy, +$1, trash a card from your hand.",
|
||||
types: [TYPE_ACTION],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "0.2",
|
||||
cost: "$5",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Chateau",
|
||||
description:
|
||||
"1%\n\n-\n\nWhen you gain this, choose one: gain an Estate; or +1 Card, +1 Action, +1 Buy, +$1, and if it's your Buy phase, return to your Action phase.",
|
||||
types: [TYPE_VICTORY],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "0.1",
|
||||
cost: "$3",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
{
|
||||
orientation: "card",
|
||||
title: "Retainer",
|
||||
description:
|
||||
"Set aside a card from your hand (under this).\n\nAt any time during any of your turns, you may take +1 Action, and add the set aside card to your hand, discarding this from play.\n\nAt the start of each of your Buy phases, if the card is still set aside, +@1.",
|
||||
types: [TYPE_ACTION, TYPE_DURATION],
|
||||
image: "",
|
||||
artist: "",
|
||||
author,
|
||||
version: "0.2",
|
||||
cost: "$2",
|
||||
preview: "",
|
||||
expansionIcon,
|
||||
},
|
||||
];
|
||||
|
5
src/colorhelper.ts
Normal file
5
src/colorhelper.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import parseColor1 from "npm:parse-color";
|
||||
|
||||
export const parseColor = (c: string): { rgb: [number, number, number] } => {
|
||||
return parseColor1(c);
|
||||
};
|
@ -391,7 +391,7 @@ export const parse = (
|
||||
pieces.push({ type: "break" });
|
||||
} else if (char in symbolMap) {
|
||||
const c = char as keyof typeof symbolMap;
|
||||
const end = text.slice(i).match(new RegExp(`\\${c}\\w*`))![0]
|
||||
const end = text.slice(i).match(new RegExp(`\\${c}[^ \n.,;]*`))![0]
|
||||
.length;
|
||||
const isBig =
|
||||
isDescription &&
|
||||
|
97
src/draw.ts
97
src/draw.ts
@ -1,3 +1,4 @@
|
||||
import { parseColor } from "./colorhelper.ts";
|
||||
import {
|
||||
measureDominionText,
|
||||
parse,
|
||||
@ -39,6 +40,10 @@ const imageList = [
|
||||
key: "card-color-2",
|
||||
src: "/static/assets/CardColorTwo.png",
|
||||
},
|
||||
{
|
||||
key: "card-color-2-night",
|
||||
src: "/static/assets/CardColorTwoNight.png",
|
||||
},
|
||||
{
|
||||
key: "card-brown",
|
||||
src: "/static/assets/CardBrown.png",
|
||||
@ -151,25 +156,74 @@ export const drawCard = (
|
||||
}
|
||||
};
|
||||
|
||||
const _rgbCache: Record<string, { r: number; g: number; b: number }> = {};
|
||||
const getColorRgb = (c: string): { r: number; g: number; b: number } => {
|
||||
const { rgb } = parseColor(c);
|
||||
const [r, g, b] = rgb;
|
||||
return { r, g, b };
|
||||
// if (c in _rgbCache) {
|
||||
// return _rgbCache[c]!;
|
||||
// }
|
||||
// const canvas = document.createElement("canvas");
|
||||
// canvas.width = 10;
|
||||
// canvas.height = 10;
|
||||
// const context = canvas.getContext("2d")!;
|
||||
// context.fillRect(0, 0, 10, 10);
|
||||
// const data = context.getImageData(5, 5, 1, 1).data;
|
||||
// console.log(data);
|
||||
// const [r, g, b] = data;
|
||||
// const rgb = { r: r!, g: g!, b: b! };
|
||||
// _rgbCache[c] = rgb;
|
||||
// return rgb;
|
||||
};
|
||||
|
||||
const getTextColorForBackground = (c: string): string => {
|
||||
// return "black";
|
||||
const { r, g, b } = getColorRgb(c);
|
||||
const avg = (r + g + b) / 3 / 255;
|
||||
console.log([r, g, b], avg);
|
||||
return avg > 0.5 ? "black" : "white";
|
||||
};
|
||||
|
||||
const getColors = (
|
||||
types: DominionCardType[]
|
||||
): { primary: string; secondary: string | null } => {
|
||||
): {
|
||||
primary: string;
|
||||
secondary: string | null;
|
||||
description: string | null;
|
||||
descriptionText: string;
|
||||
titleText: string;
|
||||
} => {
|
||||
const descriptionType =
|
||||
types.find((t) => t.color?.onConflictDescriptionOnly) ?? null;
|
||||
const byPriority = [...types]
|
||||
.filter((type) => type.color)
|
||||
.filter((type) => type.color && type !== descriptionType)
|
||||
.sort((a, b) => b.color!.priority - a.color!.priority);
|
||||
const priority1 = byPriority[0]!;
|
||||
let primary = priority1.color?.value ?? "white";
|
||||
let secondary = byPriority[1]?.color?.value ?? null;
|
||||
let primaryType: DominionCardType | null = priority1 ?? null;
|
||||
let secondaryType = byPriority[1] ?? null;
|
||||
if (priority1 === TYPE_ACTION) {
|
||||
const overriders = byPriority.filter((t) => t.color!.overridesAction);
|
||||
if (overriders.length) {
|
||||
primary = overriders[0]!.color!.value;
|
||||
primaryType = overriders[0] ?? null;
|
||||
}
|
||||
if (primary === secondary) {
|
||||
secondary = byPriority[2]?.color?.value ?? null;
|
||||
if (primaryType === secondaryType) {
|
||||
secondaryType = byPriority[2] ?? null;
|
||||
}
|
||||
}
|
||||
return { primary, secondary };
|
||||
primaryType = primaryType ?? descriptionType;
|
||||
const primary = primaryType?.color?.value ?? "white";
|
||||
const secondary = secondaryType?.color?.value ?? null;
|
||||
const description = descriptionType?.color?.value ?? null;
|
||||
const descriptionText = getTextColorForBackground(description ?? primary);
|
||||
const titleText = getTextColorForBackground(primary);
|
||||
return {
|
||||
primary,
|
||||
secondary,
|
||||
description,
|
||||
descriptionText,
|
||||
titleText,
|
||||
};
|
||||
};
|
||||
|
||||
const drawStandardCard = async (
|
||||
@ -213,6 +267,17 @@ const drawStandardCard = async (
|
||||
0,
|
||||
0
|
||||
);
|
||||
} else if (colors.description) {
|
||||
context.drawImage(
|
||||
colorImage(getImage("card-color-1"), colors.description),
|
||||
0,
|
||||
0
|
||||
);
|
||||
context.drawImage(
|
||||
colorImage(getImage("card-color-2-night"), colors.primary),
|
||||
0,
|
||||
0
|
||||
);
|
||||
} else {
|
||||
context.drawImage(
|
||||
colorImage(getImage("card-color-1"), colors.primary),
|
||||
@ -224,6 +289,7 @@ const drawStandardCard = async (
|
||||
context.drawImage(getImage("card-gray"), 0, 0);
|
||||
context.drawImage(colorImage(getImage("card-brown"), "#ff9911"), 0, 0);
|
||||
// Draw the name
|
||||
context.fillStyle = colors.titleText;
|
||||
size = 78;
|
||||
context.font = `${size}pt DominionTitle`;
|
||||
while (
|
||||
@ -234,7 +300,16 @@ const drawStandardCard = async (
|
||||
}
|
||||
await renderDominionText(context, parse(card.title), w / 2, 220);
|
||||
// Draw the description
|
||||
context.font = "60pt DominionText";
|
||||
context.fillStyle = colors.descriptionText;
|
||||
size = 60;
|
||||
context.font = `${size}pt DominionText`;
|
||||
while (
|
||||
(await measureDominionText(context, parse(card.description), 1000))
|
||||
.height > 650
|
||||
) {
|
||||
size -= 1;
|
||||
context.font = `${size}pt DominionText`;
|
||||
}
|
||||
await renderDominionText(
|
||||
context,
|
||||
parse(card.description, { isDescription: true }),
|
||||
@ -243,6 +318,7 @@ const drawStandardCard = async (
|
||||
1000
|
||||
);
|
||||
// Draw the types
|
||||
context.fillStyle = colors.titleText;
|
||||
size = 65;
|
||||
context.font = `${size}pt DominionTitle`;
|
||||
while (
|
||||
@ -264,6 +340,7 @@ const drawStandardCard = async (
|
||||
800
|
||||
);
|
||||
// Draw the cost
|
||||
context.fillStyle = colors.titleText;
|
||||
context.font = "90pt DominionText";
|
||||
const costMeasure = await measureDominionText(context, parse(card.cost));
|
||||
await renderDominionText(
|
||||
@ -273,6 +350,7 @@ const drawStandardCard = async (
|
||||
1940
|
||||
);
|
||||
// Draw the preview
|
||||
context.fillStyle = colors.titleText;
|
||||
if (card.preview) {
|
||||
context.font = "90pt DominionText";
|
||||
await renderDominionText(context, parse(card.preview), 200, 210);
|
||||
@ -293,6 +371,7 @@ const drawStandardCard = async (
|
||||
2035
|
||||
);
|
||||
// Draw the artist credit
|
||||
context.fillStyle = "white";
|
||||
const artistMeasure = await measureDominionText(
|
||||
context,
|
||||
parse(card.artist)
|
||||
|
@ -142,7 +142,7 @@ export const TYPE_NIGHT: DominionBasicCardType = {
|
||||
typeType: "basic",
|
||||
name: "Night",
|
||||
color: {
|
||||
value: "black",
|
||||
value: "#485058",
|
||||
priority: 6,
|
||||
onConflictDescriptionOnly: true,
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user