commit bd35804bc4410221b013007be76dd7229e2df669 Author: Emma Date: Fri Jul 7 17:40:59 2023 -0600 all the things diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ddf7963 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,25 @@ +{ + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#af666c", + "activityBar.background": "#af666c", + "activityBar.foreground": "#e7e7e7", + "activityBar.inactiveForeground": "#e7e7e799", + "activityBarBadge.background": "#2f542c", + "activityBarBadge.foreground": "#e7e7e7", + "commandCenter.border": "#e7e7e799", + "sash.hoverBorder": "#af666c", + "statusBar.background": "#944e53", + "statusBar.foreground": "#e7e7e7", + "statusBarItem.hoverBackground": "#af666c", + "statusBarItem.remoteBackground": "#944e53", + "statusBarItem.remoteForeground": "#e7e7e7", + "titleBar.activeBackground": "#944e53", + "titleBar.activeForeground": "#e7e7e7", + "titleBar.inactiveBackground": "#944e5399", + "titleBar.inactiveForeground": "#e7e7e799" + }, + "peacock.remoteColor": "#de088c", + "deno.enable": true, + "deno.unstable": true, + "peacock.color": "#944e53" +} \ No newline at end of file diff --git a/attackDefs.ts b/attackDefs.ts new file mode 100644 index 0000000..0a5449e --- /dev/null +++ b/attackDefs.ts @@ -0,0 +1,14 @@ +export const attackRanges = { + airToAir: { + min: 0, + max: 2 + }, + airToGround: { + min: 0, + max: 2 + }, + groundToAir: { + min: 0, + max: 2 + } +} \ No newline at end of file diff --git a/bg.jpg b/bg.jpg new file mode 100644 index 0000000..5c66891 Binary files /dev/null and b/bg.jpg differ diff --git a/camelToSpace.ts b/camelToSpace.ts new file mode 100644 index 0000000..7dd709b --- /dev/null +++ b/camelToSpace.ts @@ -0,0 +1 @@ +export const camelToSpace = (value: string) => value.replace(/[A-Z0-9]/g, e => ` ${e.toLowerCase()}`); \ No newline at end of file diff --git a/card-images/series1-1.png b/card-images/series1-1.png new file mode 100644 index 0000000..8c21c2f Binary files /dev/null and b/card-images/series1-1.png differ diff --git a/card-images/series1-10.png b/card-images/series1-10.png new file mode 100644 index 0000000..b409f42 Binary files /dev/null and b/card-images/series1-10.png differ diff --git a/card-images/series1-11.png b/card-images/series1-11.png new file mode 100644 index 0000000..818e7a1 Binary files /dev/null and b/card-images/series1-11.png differ diff --git a/card-images/series1-12.png b/card-images/series1-12.png new file mode 100644 index 0000000..d9bd706 Binary files /dev/null and b/card-images/series1-12.png differ diff --git a/card-images/series1-13.png b/card-images/series1-13.png new file mode 100644 index 0000000..6dd9754 Binary files /dev/null and b/card-images/series1-13.png differ diff --git a/card-images/series1-14.png b/card-images/series1-14.png new file mode 100644 index 0000000..13083dc Binary files /dev/null and b/card-images/series1-14.png differ diff --git a/card-images/series1-15.png b/card-images/series1-15.png new file mode 100644 index 0000000..dc2f31d Binary files /dev/null and b/card-images/series1-15.png differ diff --git a/card-images/series1-16.png b/card-images/series1-16.png new file mode 100644 index 0000000..1c26c60 Binary files /dev/null and b/card-images/series1-16.png differ diff --git a/card-images/series1-17.png b/card-images/series1-17.png new file mode 100644 index 0000000..c80078e Binary files /dev/null and b/card-images/series1-17.png differ diff --git a/card-images/series1-18.png b/card-images/series1-18.png new file mode 100644 index 0000000..4fe3a4e Binary files /dev/null and b/card-images/series1-18.png differ diff --git a/card-images/series1-19.png b/card-images/series1-19.png new file mode 100644 index 0000000..988b0f6 Binary files /dev/null and b/card-images/series1-19.png differ diff --git a/card-images/series1-2.png b/card-images/series1-2.png new file mode 100644 index 0000000..7dd4f6b Binary files /dev/null and b/card-images/series1-2.png differ diff --git a/card-images/series1-20.png b/card-images/series1-20.png new file mode 100644 index 0000000..51a9b17 Binary files /dev/null and b/card-images/series1-20.png differ diff --git a/card-images/series1-21.png b/card-images/series1-21.png new file mode 100644 index 0000000..2ddbb9e Binary files /dev/null and b/card-images/series1-21.png differ diff --git a/card-images/series1-22.png b/card-images/series1-22.png new file mode 100644 index 0000000..a8516c5 Binary files /dev/null and b/card-images/series1-22.png differ diff --git a/card-images/series1-23.png b/card-images/series1-23.png new file mode 100644 index 0000000..3865be7 Binary files /dev/null and b/card-images/series1-23.png differ diff --git a/card-images/series1-24.png b/card-images/series1-24.png new file mode 100644 index 0000000..454e1fa Binary files /dev/null and b/card-images/series1-24.png differ diff --git a/card-images/series1-25.png b/card-images/series1-25.png new file mode 100644 index 0000000..f9f19fd Binary files /dev/null and b/card-images/series1-25.png differ diff --git a/card-images/series1-26.png b/card-images/series1-26.png new file mode 100644 index 0000000..a82c5c7 Binary files /dev/null and b/card-images/series1-26.png differ diff --git a/card-images/series1-27.png b/card-images/series1-27.png new file mode 100644 index 0000000..bb415e0 Binary files /dev/null and b/card-images/series1-27.png differ diff --git a/card-images/series1-28.png b/card-images/series1-28.png new file mode 100644 index 0000000..bfa0e9c Binary files /dev/null and b/card-images/series1-28.png differ diff --git a/card-images/series1-29.png b/card-images/series1-29.png new file mode 100644 index 0000000..adc2c77 Binary files /dev/null and b/card-images/series1-29.png differ diff --git a/card-images/series1-3.png b/card-images/series1-3.png new file mode 100644 index 0000000..a791c9a Binary files /dev/null and b/card-images/series1-3.png differ diff --git a/card-images/series1-30.png b/card-images/series1-30.png new file mode 100644 index 0000000..b7af588 Binary files /dev/null and b/card-images/series1-30.png differ diff --git a/card-images/series1-31.png b/card-images/series1-31.png new file mode 100644 index 0000000..38dcf67 Binary files /dev/null and b/card-images/series1-31.png differ diff --git a/card-images/series1-32.png b/card-images/series1-32.png new file mode 100644 index 0000000..7cd9cad Binary files /dev/null and b/card-images/series1-32.png differ diff --git a/card-images/series1-33.png b/card-images/series1-33.png new file mode 100644 index 0000000..014bca3 Binary files /dev/null and b/card-images/series1-33.png differ diff --git a/card-images/series1-34.png b/card-images/series1-34.png new file mode 100644 index 0000000..39dd1f2 Binary files /dev/null and b/card-images/series1-34.png differ diff --git a/card-images/series1-35.png b/card-images/series1-35.png new file mode 100644 index 0000000..b3a5cdd Binary files /dev/null and b/card-images/series1-35.png differ diff --git a/card-images/series1-36.png b/card-images/series1-36.png new file mode 100644 index 0000000..097db07 Binary files /dev/null and b/card-images/series1-36.png differ diff --git a/card-images/series1-37.png b/card-images/series1-37.png new file mode 100644 index 0000000..3d20fc1 Binary files /dev/null and b/card-images/series1-37.png differ diff --git a/card-images/series1-38.png b/card-images/series1-38.png new file mode 100644 index 0000000..2481310 Binary files /dev/null and b/card-images/series1-38.png differ diff --git a/card-images/series1-39.png b/card-images/series1-39.png new file mode 100644 index 0000000..3b80070 Binary files /dev/null and b/card-images/series1-39.png differ diff --git a/card-images/series1-4.png b/card-images/series1-4.png new file mode 100644 index 0000000..c6876c9 Binary files /dev/null and b/card-images/series1-4.png differ diff --git a/card-images/series1-40.png b/card-images/series1-40.png new file mode 100644 index 0000000..2fb10a9 Binary files /dev/null and b/card-images/series1-40.png differ diff --git a/card-images/series1-41.png b/card-images/series1-41.png new file mode 100644 index 0000000..e256198 Binary files /dev/null and b/card-images/series1-41.png differ diff --git a/card-images/series1-42.png b/card-images/series1-42.png new file mode 100644 index 0000000..4572622 Binary files /dev/null and b/card-images/series1-42.png differ diff --git a/card-images/series1-43.png b/card-images/series1-43.png new file mode 100644 index 0000000..e1ad8c5 Binary files /dev/null and b/card-images/series1-43.png differ diff --git a/card-images/series1-44.png b/card-images/series1-44.png new file mode 100644 index 0000000..dc74ffb Binary files /dev/null and b/card-images/series1-44.png differ diff --git a/card-images/series1-45.png b/card-images/series1-45.png new file mode 100644 index 0000000..2fa8ce5 Binary files /dev/null and b/card-images/series1-45.png differ diff --git a/card-images/series1-46.png b/card-images/series1-46.png new file mode 100644 index 0000000..35308e9 Binary files /dev/null and b/card-images/series1-46.png differ diff --git a/card-images/series1-47.png b/card-images/series1-47.png new file mode 100644 index 0000000..93be5ff Binary files /dev/null and b/card-images/series1-47.png differ diff --git a/card-images/series1-48.png b/card-images/series1-48.png new file mode 100644 index 0000000..eb8695f Binary files /dev/null and b/card-images/series1-48.png differ diff --git a/card-images/series1-49.png b/card-images/series1-49.png new file mode 100644 index 0000000..fb06c80 Binary files /dev/null and b/card-images/series1-49.png differ diff --git a/card-images/series1-5.png b/card-images/series1-5.png new file mode 100644 index 0000000..79ce343 Binary files /dev/null and b/card-images/series1-5.png differ diff --git a/card-images/series1-50.png b/card-images/series1-50.png new file mode 100644 index 0000000..0577ea8 Binary files /dev/null and b/card-images/series1-50.png differ diff --git a/card-images/series1-51.png b/card-images/series1-51.png new file mode 100644 index 0000000..b6de3ca Binary files /dev/null and b/card-images/series1-51.png differ diff --git a/card-images/series1-52.png b/card-images/series1-52.png new file mode 100644 index 0000000..f5f810a Binary files /dev/null and b/card-images/series1-52.png differ diff --git a/card-images/series1-53.png b/card-images/series1-53.png new file mode 100644 index 0000000..5022637 Binary files /dev/null and b/card-images/series1-53.png differ diff --git a/card-images/series1-54.png b/card-images/series1-54.png new file mode 100644 index 0000000..b741b41 Binary files /dev/null and b/card-images/series1-54.png differ diff --git a/card-images/series1-55.png b/card-images/series1-55.png new file mode 100644 index 0000000..cdb7fbb Binary files /dev/null and b/card-images/series1-55.png differ diff --git a/card-images/series1-56.png b/card-images/series1-56.png new file mode 100644 index 0000000..0f56fdd Binary files /dev/null and b/card-images/series1-56.png differ diff --git a/card-images/series1-57.png b/card-images/series1-57.png new file mode 100644 index 0000000..e418b86 Binary files /dev/null and b/card-images/series1-57.png differ diff --git a/card-images/series1-58.png b/card-images/series1-58.png new file mode 100644 index 0000000..def10e9 Binary files /dev/null and b/card-images/series1-58.png differ diff --git a/card-images/series1-59.png b/card-images/series1-59.png new file mode 100644 index 0000000..94148db Binary files /dev/null and b/card-images/series1-59.png differ diff --git a/card-images/series1-6.png b/card-images/series1-6.png new file mode 100644 index 0000000..c439ba3 Binary files /dev/null and b/card-images/series1-6.png differ diff --git a/card-images/series1-60.png b/card-images/series1-60.png new file mode 100644 index 0000000..e0a4edf Binary files /dev/null and b/card-images/series1-60.png differ diff --git a/card-images/series1-7.png b/card-images/series1-7.png new file mode 100644 index 0000000..b33cf11 Binary files /dev/null and b/card-images/series1-7.png differ diff --git a/card-images/series1-8.png b/card-images/series1-8.png new file mode 100644 index 0000000..2c21f63 Binary files /dev/null and b/card-images/series1-8.png differ diff --git a/card-images/series1-9.png b/card-images/series1-9.png new file mode 100644 index 0000000..4e21caa Binary files /dev/null and b/card-images/series1-9.png differ diff --git a/cardGen/consts.ts b/cardGen/consts.ts new file mode 100644 index 0000000..b622273 --- /dev/null +++ b/cardGen/consts.ts @@ -0,0 +1 @@ +export const textSmall = '24px' \ No newline at end of file diff --git a/cardGen/rows.ts b/cardGen/rows.ts new file mode 100644 index 0000000..f8ec527 --- /dev/null +++ b/cardGen/rows.ts @@ -0,0 +1,62 @@ +import { CanvasRenderingContext2D } from "https://deno.land/x/skia_canvas@0.4.1/mod.ts"; +import { styleTypeAccessor, TextStyle } from "./textStyle.ts"; +import { wordWrap } from "./wordWrap.ts"; + +type line = { value: string, style: TextStyle, type: styleTypeAccessor, newLine?: boolean, combine?: boolean } + +export const flexRow = (ctx: CanvasRenderingContext2D, sections: string[], maxWidth: number) => { + const totalWidth = sections.map(s => ctx.measureText(s).width).reduce((a, b) => a + b, 0); + const gap = (maxWidth - totalWidth) / (sections.length - 1); + + ctx.save() + for (const section of sections) { + ctx.fillText(section, 0, 0); + ctx.translate(ctx.measureText(section).width + gap, 0); + } + ctx.restore(); +} + +export const inlineRow = (ctx: CanvasRenderingContext2D, sections: line[], maxWidth: number) => { + const lines: line[] = []; + for (const [i, section] of sections.entries()) { + if (!section.newLine) { + const last = lines[i - 1]; + if (last) { + ctx.font = last.style[last.type]; + const lastWidth = ctx.measureText(last.value).width; + ctx.font = section.style[section.type]; + lines.push(...wordWrap(ctx, section.value, maxWidth, maxWidth - lastWidth).map((e, i): line => ({ + ...section, + value: e, + combine: i === 0 + }))); + continue; + } + } + ctx.font = section.style[section.type]; + lines.push(...wordWrap(ctx, section.value, maxWidth).map((e): line => ({ + ...section, + value: e + }))); + } + + return lines; +} + +export const drawRow = (ctx: CanvasRenderingContext2D, lines: line[]) => { + for (const [i, line] of lines.entries()) { + const last = lines[i - 1]; + if (line.combine && last) { + ctx.save(); + ctx.font = last.style[last.type]; + ctx.translate(ctx.measureText(last.value).width, 0); + ctx.font = line.style[line.type]; + ctx.fillText(line.value, 0, 0); + ctx.restore(); + } else { + ctx.translate(0, line.style.lineHeight); + ctx.font = line.style[line.type]; + ctx.fillText(line.value, 0, 0); + } + } +} \ No newline at end of file diff --git a/cardGen/textStyle.ts b/cardGen/textStyle.ts new file mode 100644 index 0000000..e9e63a8 --- /dev/null +++ b/cardGen/textStyle.ts @@ -0,0 +1,22 @@ +export type styleTypeAccessor = 'default' | 'bold' | 'italic' | 'boldItalic'; + +export class TextStyle { + fontSize: number; + lineHeight: number; + constructor(fontSize: number, lineHeight?: number) { + this.fontSize = fontSize; + this.lineHeight = lineHeight || fontSize; + } + get default() { + return `${this.fontSize}px Chakra Petch` + } + get bold() { + return `bold ${this.fontSize}px Chakra Petch` + } + get italic() { + return `italic ${this.fontSize}px Chakra Petch` + } + get boldItalic() { + return `italic bold ${this.fontSize}px Chakra Petch` + } +} diff --git a/cardGen/wordWrap.ts b/cardGen/wordWrap.ts new file mode 100644 index 0000000..74293ea --- /dev/null +++ b/cardGen/wordWrap.ts @@ -0,0 +1,24 @@ +import { CanvasRenderingContext2D } from "https://deno.land/x/skia_canvas@0.4.1/mod.ts"; + +export const wordWrap = (ctx: CanvasRenderingContext2D, text: string, maxWidth: number, lineWidth?: number) => { + const words = text.split(' '); + let testLine = ''; + const lines: string[] = []; + + for (const word of words) { + const previous = testLine; + testLine += ` ${word}`; + testLine = testLine.replace(/^\s/, ''); + const { width } = ctx.measureText(testLine); + + const calcedWidth = lineWidth && lines.length === 0 ? lineWidth : maxWidth; + + if (width > calcedWidth) { + lines.push(previous); + testLine = word; + } + } + if (testLine) lines.push(testLine); + + return lines; +} \ No newline at end of file diff --git a/fonts/ChakraPetch-Bold.ttf b/fonts/ChakraPetch-Bold.ttf new file mode 100644 index 0000000..7b63c6b Binary files /dev/null and b/fonts/ChakraPetch-Bold.ttf differ diff --git a/fonts/ChakraPetch-BoldItalic.ttf b/fonts/ChakraPetch-BoldItalic.ttf new file mode 100644 index 0000000..0bdf8a3 Binary files /dev/null and b/fonts/ChakraPetch-BoldItalic.ttf differ diff --git a/fonts/ChakraPetch-Italic.ttf b/fonts/ChakraPetch-Italic.ttf new file mode 100644 index 0000000..dfd35ba Binary files /dev/null and b/fonts/ChakraPetch-Italic.ttf differ diff --git a/fonts/ChakraPetch-Light.ttf b/fonts/ChakraPetch-Light.ttf new file mode 100644 index 0000000..ac3be41 Binary files /dev/null and b/fonts/ChakraPetch-Light.ttf differ diff --git a/fonts/ChakraPetch-LightItalic.ttf b/fonts/ChakraPetch-LightItalic.ttf new file mode 100644 index 0000000..3b24705 Binary files /dev/null and b/fonts/ChakraPetch-LightItalic.ttf differ diff --git a/fonts/ChakraPetch-Medium.ttf b/fonts/ChakraPetch-Medium.ttf new file mode 100644 index 0000000..05ded64 Binary files /dev/null and b/fonts/ChakraPetch-Medium.ttf differ diff --git a/fonts/ChakraPetch-MediumItalic.ttf b/fonts/ChakraPetch-MediumItalic.ttf new file mode 100644 index 0000000..f840323 Binary files /dev/null and b/fonts/ChakraPetch-MediumItalic.ttf differ diff --git a/fonts/ChakraPetch-Regular.ttf b/fonts/ChakraPetch-Regular.ttf new file mode 100644 index 0000000..245df02 Binary files /dev/null and b/fonts/ChakraPetch-Regular.ttf differ diff --git a/fonts/ChakraPetch-SemiBold.ttf b/fonts/ChakraPetch-SemiBold.ttf new file mode 100644 index 0000000..20181b5 Binary files /dev/null and b/fonts/ChakraPetch-SemiBold.ttf differ diff --git a/fonts/ChakraPetch-SemiBoldItalic.ttf b/fonts/ChakraPetch-SemiBoldItalic.ttf new file mode 100644 index 0000000..fa994fe Binary files /dev/null and b/fonts/ChakraPetch-SemiBoldItalic.ttf differ diff --git a/fonts/Rajdhani-Bold.ttf b/fonts/Rajdhani-Bold.ttf new file mode 100644 index 0000000..4259153 Binary files /dev/null and b/fonts/Rajdhani-Bold.ttf differ diff --git a/fonts/Rajdhani-Light.ttf b/fonts/Rajdhani-Light.ttf new file mode 100644 index 0000000..2d6b269 Binary files /dev/null and b/fonts/Rajdhani-Light.ttf differ diff --git a/fonts/Rajdhani-Medium.ttf b/fonts/Rajdhani-Medium.ttf new file mode 100644 index 0000000..2e82d0a Binary files /dev/null and b/fonts/Rajdhani-Medium.ttf differ diff --git a/fonts/Rajdhani-Regular.ttf b/fonts/Rajdhani-Regular.ttf new file mode 100644 index 0000000..5618bc3 Binary files /dev/null and b/fonts/Rajdhani-Regular.ttf differ diff --git a/fonts/Rajdhani-SemiBold.ttf b/fonts/Rajdhani-SemiBold.ttf new file mode 100644 index 0000000..8738ec5 Binary files /dev/null and b/fonts/Rajdhani-SemiBold.ttf differ diff --git a/generateCardImages.ts b/generateCardImages.ts new file mode 100644 index 0000000..b9f93df --- /dev/null +++ b/generateCardImages.ts @@ -0,0 +1,176 @@ +import { createCanvas, Fonts, Image } from "https://deno.land/x/skia_canvas@0.4.1/mod.ts"; +import { drawRow, flexRow, inlineRow } from "./cardGen/rows.ts"; +import { TextStyle } from "./cardGen/textStyle.ts"; +import { wordWrap } from "./cardGen/wordWrap.ts"; +import { card } from './types.ts'; +import { camelToSpace } from './camelToSpace.ts'; + +const bg = Image.loadSync('./bg.jpg'); + +Fonts.registerDir('./fonts'); + +// Fonts.setAlias('Petch', 'Chakra Petch') + +const xsText = new TextStyle(32, 36); +const mdText = new TextStyle(40, 46); +const smText = new TextStyle(34, 40); +const lgText = new TextStyle(60, 66) + +const width = Math.floor(2.74 * 300); +const height = Math.floor(3.74 * 300); + +const canvas = createCanvas(width, height); +const ctx = canvas.getContext('2d'); + +const cutAreaWidth = 750; +const cutAreaHeight = 1050; +const _cutArea = { + wStart: (canvas.width - cutAreaWidth) / 2, + wEnd: canvas.width - ((canvas.width - cutAreaWidth) / 2), + hStart: (canvas.height - cutAreaHeight) / 2, + hEnd: canvas.height - ((canvas.height - cutAreaHeight) / 2), +} +const safeAreaWidth = 690; +const safeAreaHeight = 990; +const safeArea = { + wStart: (canvas.width - safeAreaWidth) / 2, + wEnd: canvas.width - ((canvas.width - safeAreaWidth) / 2), + hStart: (canvas.height - safeAreaHeight) / 2, + hEnd: canvas.height - ((canvas.height - safeAreaHeight) / 2), +} + +const cards: card[] = JSON.parse(Deno.readTextFileSync('./series1.json')); +// const card = cards[12]; +// Safe Area +// ctx.strokeStyle = 'green' +// ctx.beginPath() +// ctx.roundRect(safeArea.wStart, safeArea.hStart, safeAreaWidth, safeAreaHeight, 24) +// ctx.stroke() + +// Cut Area +// ctx.strokeStyle = 'red' +// ctx.beginPath() +// ctx.roundRect(cutArea.wStart, cutArea.hStart, cutAreaWidth, cutAreaHeight, 40) +// ctx.stroke() + +for (const [i, card] of cards.entries()) { + ctx.drawImage(bg, 0, 0) + ctx.fillStyle = 'rgba(255, 255, 255, 0.7)' + ctx.fillRect(0, 0, canvas.width, canvas.height); + + + ctx.save(); + ctx.textBaseline = "top" + ctx.fillStyle = 'black' + ctx.translate(safeArea.wStart, safeArea.hStart) + ctx.font = lgText.bold; + ctx.fillText(card.type.toLocaleUpperCase(), 0, 0) + ctx.translate(0, lgText.lineHeight + 40); + + const blurbs = { + bad: `Bad luck! You must take one of the following penalties`, + good: `Select either one maneuver or one attack to make. If you can't complete any action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.` + } + const blurb = card.attacks.length || card.maneuvers.length ? blurbs.good : blurbs.bad; + ctx.font = xsText.italic + const blurbLines = wordWrap(ctx, blurb, safeAreaWidth); + for (const line of blurbLines) { + ctx.fillText(line, 0, 0); + ctx.translate(0, smText.lineHeight); + } + + ctx.font = mdText.default + if (card.attacks.length) { + ctx.translate(0, -20) + const attackLines = inlineRow( + ctx, + [ + { + value: 'Attacks: ', + style: mdText, + type: 'bold', + }, + { + value: card.attacks.map(a => camelToSpace(a)).join(', '), + style: mdText, + type: 'default' + } + ], + safeAreaWidth + ); + drawRow(ctx, attackLines); + } + if (card.maneuvers.length) { + ctx.translate(0, 20) + const maneuverLines = inlineRow( + ctx, + [ + { + value: 'Maneuvers: ', + style: mdText, + type: 'bold', + }, + { + value: card.maneuvers.map(m => camelToSpace(m.name)).join(', '), + style: mdText, + type: 'default' + } + ], + safeAreaWidth + ); + drawRow(ctx, maneuverLines); + } + + if (card.penalties.length) { + ctx.translate(0, 80); + ctx.strokeStyle = 'purple'; + ctx.beginPath(); + ctx.moveTo(0, 0); + ctx.lineTo(safeAreaWidth, 0); + ctx.stroke(); + ctx.translate(0, -20); + const penaltyLines = inlineRow( + ctx, + [ + { + value: card.penalties.length === 1 ? 'Penalty: ' : 'Penalties: ', + style: mdText, + type: 'bold', + }, + { + value: card.penalties.join(', '), + style: mdText, + type: 'default' + } + ], + safeAreaWidth + ); + drawRow(ctx, penaltyLines); + } + + + ctx.restore(); + ctx.fillStyle = 'grey' + ctx.font = xsText.default; + ctx.save(); + ctx.translate(safeArea.wStart, safeArea.hEnd); + ctx.strokeStyle = 'black'; + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.moveTo(0, -xsText.lineHeight); + ctx.lineTo(safeAreaWidth, -xsText.lineHeight); + ctx.stroke(); + ctx.textAlign = 'center'; + ctx.fillText('Nightfall: Blood Red Skies', safeAreaWidth / 2, -xsText.lineHeight - 12); + ctx.textAlign = 'left' + flexRow(ctx, ['Series 1', `${i + 1}/60`, `© ${new Date().getFullYear()} Cyborg Grizzly Games`], safeAreaWidth); + ctx.restore(); + + try { + canvas.save(`./card-images/series1-${i + 1}.png`, "png") + } catch (error) { + console.log(error); + console.log(i); + } + // canvas.save(`./testImg.png`, "png") +} diff --git a/generateHtml.ts b/generateHtml.ts new file mode 100644 index 0000000..48ba1ad --- /dev/null +++ b/generateHtml.ts @@ -0,0 +1,94 @@ +import { camelToSpace } from "./camelToSpace.ts"; +import { card } from "./types.ts"; + +const series = 1; + +const template = (cards: string[]) => ` + + + + + + + Blood Red Skies Cards Series ${series} + + + + + + +
+ ${cards.join('\n')} +
+ + +` + +const decoder = new TextDecoder(); +const cards: card[] = JSON.parse(decoder.decode(Deno.readFileSync(`./series${series}.json`))); + +const html = template(cards.map((c, i) => ` +
+
+

${c.type}

+ + ${c.attacks.length || c.maneuvers.length ? + `

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

` : + `

Bad luck! You must take one of the following penalties

` + } + + ${c.maneuvers.length > 0 ? `

Maneuvers: ${c.maneuvers.map(a => camelToSpace(a.name)).join(', ')}

` : ''} + ${c.attacks.length > 0 ? `

Attacks: ${c.attacks.map(a => camelToSpace(a)).join(', ')}

` : ''} + ${c.penalties.length > 0 ? `

Penalties: ${c.penalties.join(', ')}

` : ''} +
+ +
+

Series ${series}

+

${i + 1}/${cards.length}

+

© ${new Date().getFullYear()} Cyborg Grizzly Games

+
+
+`)) + +const encoder = new TextEncoder(); +Deno.writeFile(`./series${series}.html`, encoder.encode(html)); diff --git a/index.html b/index.html new file mode 100644 index 0000000..b5a879e --- /dev/null +++ b/index.html @@ -0,0 +1,15 @@ + + + + + + + Blood Red Skies Cards + + + +
+ +
+ + \ No newline at end of file diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..2c95011 --- /dev/null +++ b/index.ts @@ -0,0 +1,67 @@ +import { attackRanges } from "./attackDefs.ts"; +import { move, moves } from "./moveDefs.ts"; +import { penaltyDefs } from "./penaltyDefs.ts"; +import { card } from "./types.ts"; + +const series = Deno.args.find(a => a.includes('series'))?.split('=')[1]; +console.log(`Generating cards for series ${series}`); + +const cardCount = 60; + +const cards: card[] = []; + +while (cards.length < cardCount) { + const maneuvers: move[] = []; + const maneuverCount = Math.floor(Math.random() * 3); + while (maneuvers.length < maneuverCount) { + const move = moves[Math.floor(Math.random() * moves.length)]; + if (!maneuvers.includes(move)) maneuvers.push(move); + } + + const attacks: string[] = []; + + for (const [name, attack] of Object.entries(attackRanges)) { + const rand = Math.random() * 10; + if (rand < attack.max) attacks.push(name); + } + + const penalties = penaltyDefs.map(value => ({ value, sort: Math.random() })) + .sort((a, b) => a.sort - b.sort) + .map(({ value }) => value).splice(0, Math.min(3, Math.floor(Math.random() * (penaltyDefs.length + 1)))) + .sort((a,b) => { + if (a < b) { + return -1; + } + if (a > b) { + return 1; + } + return 0; + }); + + const card: card = { + maneuvers, + attacks, + penalties, + type: 'action' + }; + + if (card.penalties.length === 0 && card.attacks.includes('groundToAir')) card.penalties.push('Land Battle'); + + // TODO: optimize this. Cards should be stored in a map with the key being the stringification of a normalized concatenation of all properties + for (const existing of cards) { + const everyAttack = existing.attacks.every(a => card.attacks.includes(a)) && card.attacks.every(a => existing.attacks.includes(a)) + const everyManeuver = existing.maneuvers.every(a => card.maneuvers.find(e => e.name === a.name)) && card.maneuvers.every(a => existing.maneuvers.find(e => e.name === a.name)); + const everyPenalty = existing.penalties.every(a => card.penalties.includes(a)) && card.penalties.every(a => existing.penalties.includes(a)) + + if (everyAttack && everyManeuver && everyPenalty) { + card.needsEffect = true; + break; + } + } + + (card.maneuvers.length || card.attacks.length || card.penalties.length) && cards.push(card); +} + +const encoder = new TextEncoder(); +Deno.writeFile(`./series${series}.json`, encoder.encode(JSON.stringify(cards, null, 2))); +console.log('Done'); diff --git a/moveDefs.ts b/moveDefs.ts new file mode 100644 index 0000000..ae1d931 --- /dev/null +++ b/moveDefs.ts @@ -0,0 +1,46 @@ +export interface move { + complexity: 'simple' | 'complex'; + length?: number; + facing?: number; + horizontalOffset?: number; + evasiveness?: number; + name: string +} + +export const moves: move[] = [ + { + name: 'immelmann', + complexity: 'complex', + length: 10 + }, + { + name: 'bankedTurn', + complexity: 'simple', + length: 6 + }, + { + name: 'barrelRoll', + complexity: 'complex', + length: 8 + }, + { + name: 'straight', + complexity: 'simple', + length: 4 + }, + { + name: 'tightBank', + complexity: 'complex', + length: 4 + }, + { + name: 'turn', + complexity: 'simple', + length: 4 + }, + { + name: 'sBend', + complexity: 'simple', + length: 4 + }, +] \ No newline at end of file diff --git a/penaltyDefs.ts b/penaltyDefs.ts new file mode 100644 index 0000000..526abe0 --- /dev/null +++ b/penaltyDefs.ts @@ -0,0 +1,5 @@ +export const penaltyDefs = [ + 'Stall', + 'Damage', + 'Ground Battle' +] \ No newline at end of file diff --git a/series1.html b/series1.html new file mode 100644 index 0000000..984527a --- /dev/null +++ b/series1.html @@ -0,0 +1,1198 @@ + + + + + + + + Blood Red Skies Cards Series 1 + + + + + + +
+ +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: barrel roll

+

Attacks: ground to air

+

Penalties: Land Battle

+
+ +
+

Series 1

+

1/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: barrel roll

+ + +
+ +
+

Series 1

+

2/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: straight

+

Attacks: air to air

+ +
+ +
+

Series 1

+

3/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Stall

+
+ +
+

Series 1

+

4/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Damage, Land Battle

+
+ +
+

Series 1

+

5/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: straight

+ +

Penalties: Land Battle, Stall

+
+ +
+

Series 1

+

6/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: banked turn

+ +

Penalties: Land Battle, Stall

+
+ +
+

Series 1

+

7/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: turn

+

Attacks: air to ground

+

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

8/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: tight bank

+ + +
+ +
+

Series 1

+

9/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: tight bank, straight

+ +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

10/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: tight bank

+

Attacks: air to air, air to ground

+

Penalties: Damage, Stall

+
+ +
+

Series 1

+

11/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Damage, Stall

+
+ +
+

Series 1

+

12/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann, tight bank

+ +

Penalties: Stall

+
+ +
+

Series 1

+

13/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: banked turn, tight bank

+ +

Penalties: Land Battle, Stall

+
+ +
+

Series 1

+

14/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: straight, tight bank

+ +

Penalties: Damage, Land Battle

+
+ +
+

Series 1

+

15/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

16/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: barrel roll

+ +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

17/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

18/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: s bend, barrel roll

+ +

Penalties: Land Battle

+
+ +
+

Series 1

+

19/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: barrel roll

+ + +
+ +
+

Series 1

+

20/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann

+

Attacks: air to ground, ground to air

+

Penalties: Land Battle

+
+ +
+

Series 1

+

21/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

22/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann, barrel roll

+ +

Penalties: Land Battle

+
+ +
+

Series 1

+

23/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann, tight bank

+

Attacks: air to ground

+

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

24/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: straight, barrel roll

+

Attacks: air to air

+ +
+ +
+

Series 1

+

25/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: straight, turn

+

Attacks: air to ground, ground to air

+

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

26/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

27/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ + +

Attacks: air to air, ground to air

+

Penalties: Land Battle

+
+ +
+

Series 1

+

28/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: barrel roll, banked turn

+

Attacks: air to air

+

Penalties: Damage

+
+ +
+

Series 1

+

29/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann

+

Attacks: ground to air

+

Penalties: Land Battle

+
+ +
+

Series 1

+

30/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ + +

Attacks: air to ground

+

Penalties: Damage, Stall

+
+ +
+

Series 1

+

31/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann, straight

+ +

Penalties: Stall

+
+ +
+

Series 1

+

32/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann

+ +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

33/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann

+

Attacks: ground to air

+

Penalties: Land Battle

+
+ +
+

Series 1

+

34/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann

+

Attacks: air to air

+

Penalties: Stall

+
+ +
+

Series 1

+

35/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ + +

Attacks: air to air

+

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

36/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ + +

Attacks: air to air

+

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

37/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann, tight bank

+

Attacks: air to air

+

Penalties: Damage, Stall

+
+ +
+

Series 1

+

38/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: tight bank

+ +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

39/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: straight, immelmann

+

Attacks: ground to air

+

Penalties: Land Battle

+
+ +
+

Series 1

+

40/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann

+

Attacks: air to ground

+

Penalties: Damage, Stall

+
+ +
+

Series 1

+

41/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: turn

+

Attacks: air to ground

+

Penalties: Damage, Stall

+
+ +
+

Series 1

+

42/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: banked turn, s bend

+ +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

43/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: barrel roll

+ +

Penalties: Stall

+
+ +
+

Series 1

+

44/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ + +

Attacks: ground to air

+

Penalties: Land Battle

+
+ +
+

Series 1

+

45/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ + +

Attacks: air to ground

+ +
+ +
+

Series 1

+

46/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: s bend

+ + +
+ +
+

Series 1

+

47/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: tight bank, banked turn

+ +

Penalties: Damage, Land Battle

+
+ +
+

Series 1

+

48/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: barrel roll, tight bank

+ +

Penalties: Damage, Land Battle

+
+ +
+

Series 1

+

49/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: tight bank, barrel roll

+ +

Penalties: Land Battle

+
+ +
+

Series 1

+

50/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Land Battle, Stall

+
+ +
+

Series 1

+

51/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Land Battle

+
+ +
+

Series 1

+

52/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Stall

+
+ +
+

Series 1

+

53/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: s bend, banked turn

+

Attacks: air to air

+ +
+ +
+

Series 1

+

54/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ + +

Attacks: air to air

+ +
+ +
+

Series 1

+

55/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: barrel roll

+

Attacks: air to air

+ +
+ +
+

Series 1

+

56/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Bad luck! You must take one of the following penalties

+ + + +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

57/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: immelmann, barrel roll

+

Attacks: ground to air

+

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

58/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: s bend, immelmann

+

Attacks: air to ground

+

Penalties: Damage, Land Battle

+
+ +
+

Series 1

+

59/60

+

© 2022 Cyborg Grizzly Games

+
+
+ + +
+
+

action

+ +

Select either one maneuver or one attack to make. If you can't complete one action from this card, you must take one penalty listed. If there are no penalties listed, discard this card.

+ +

Maneuvers: s bend, tight bank

+ +

Penalties: Damage, Land Battle, Stall

+
+ +
+

Series 1

+

60/60

+

© 2022 Cyborg Grizzly Games

+
+
+ +
+ + diff --git a/series1.json b/series1.json new file mode 100644 index 0000000..7af5360 --- /dev/null +++ b/series1.json @@ -0,0 +1,934 @@ +[ + { + "maneuvers": [ + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [ + "groundToAir" + ], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "straight", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [ + "airToAir" + ], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "straight", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "bankedTurn", + "complexity": "simple", + "length": 6 + } + ], + "attacks": [], + "penalties": [ + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "turn", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [ + "airToGround" + ], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + }, + { + "name": "straight", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [ + "airToAir", + "airToGround" + ], + "penalties": [ + "Damage", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Damage", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + }, + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "bankedTurn", + "complexity": "simple", + "length": 6 + }, + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "straight", + "complexity": "simple", + "length": 4 + }, + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action", + "needsEffect": true + }, + { + "maneuvers": [ + { + "name": "sBend", + "complexity": "simple", + "length": 4 + }, + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [], + "penalties": [], + "type": "action", + "needsEffect": true + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + } + ], + "attacks": [ + "airToGround", + "groundToAir" + ], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action", + "needsEffect": true + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + }, + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + }, + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [ + "airToGround" + ], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "straight", + "complexity": "simple", + "length": 4 + }, + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [ + "airToAir" + ], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "straight", + "complexity": "simple", + "length": 4 + }, + { + "name": "turn", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [ + "airToGround", + "groundToAir" + ], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action", + "needsEffect": true + }, + { + "maneuvers": [], + "attacks": [ + "airToAir", + "groundToAir" + ], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + }, + { + "name": "bankedTurn", + "complexity": "simple", + "length": 6 + } + ], + "attacks": [ + "airToAir" + ], + "penalties": [ + "Damage" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + } + ], + "attacks": [ + "groundToAir" + ], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [ + "airToGround" + ], + "penalties": [ + "Damage", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + }, + { + "name": "straight", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + } + ], + "attacks": [ + "groundToAir" + ], + "penalties": [ + "Land Battle" + ], + "type": "action", + "needsEffect": true + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + } + ], + "attacks": [ + "airToAir" + ], + "penalties": [ + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [ + "airToAir" + ], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [ + "airToAir" + ], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action", + "needsEffect": true + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + }, + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [ + "airToAir" + ], + "penalties": [ + "Damage", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "straight", + "complexity": "simple", + "length": 4 + }, + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + } + ], + "attacks": [ + "groundToAir" + ], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + } + ], + "attacks": [ + "airToGround" + ], + "penalties": [ + "Damage", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "turn", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [ + "airToGround" + ], + "penalties": [ + "Damage", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "bankedTurn", + "complexity": "simple", + "length": 6 + }, + { + "name": "sBend", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [], + "penalties": [ + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [ + "groundToAir" + ], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [ + "airToGround" + ], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "sBend", + "complexity": "simple", + "length": 4 + } + ], + "attacks": [], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + }, + { + "name": "bankedTurn", + "complexity": "simple", + "length": 6 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + }, + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + }, + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Stall" + ], + "type": "action", + "needsEffect": true + }, + { + "maneuvers": [ + { + "name": "sBend", + "complexity": "simple", + "length": 4 + }, + { + "name": "bankedTurn", + "complexity": "simple", + "length": 6 + } + ], + "attacks": [ + "airToAir" + ], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [ + "airToAir" + ], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [ + "airToAir" + ], + "penalties": [], + "type": "action" + }, + { + "maneuvers": [], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action", + "needsEffect": true + }, + { + "maneuvers": [ + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + }, + { + "name": "barrelRoll", + "complexity": "complex", + "length": 8 + } + ], + "attacks": [ + "groundToAir" + ], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "sBend", + "complexity": "simple", + "length": 4 + }, + { + "name": "immelmann", + "complexity": "complex", + "length": 10 + } + ], + "attacks": [ + "airToGround" + ], + "penalties": [ + "Damage", + "Land Battle" + ], + "type": "action" + }, + { + "maneuvers": [ + { + "name": "sBend", + "complexity": "simple", + "length": 4 + }, + { + "name": "tightBank", + "complexity": "complex", + "length": 4 + } + ], + "attacks": [], + "penalties": [ + "Damage", + "Land Battle", + "Stall" + ], + "type": "action" + } +] \ No newline at end of file diff --git a/testImg.png b/testImg.png new file mode 100644 index 0000000..9a84d57 Binary files /dev/null and b/testImg.png differ diff --git a/types.ts b/types.ts new file mode 100644 index 0000000..e8959e8 --- /dev/null +++ b/types.ts @@ -0,0 +1,9 @@ +import { move } from "./moveDefs.ts"; + +export interface card { + maneuvers: move[]; + attacks: string[]; + penalties: string[]; + type: 'action' | 'win condition' | 'wild card' | 'sudden death'; + needsEffect?: boolean; +} \ No newline at end of file