177 lines
4.9 KiB
TypeScript
177 lines
4.9 KiB
TypeScript
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")
|
|
}
|