import { Canvas, createCanvas, loadImage, SKRSContext2D } from "@napi-rs/canvas"; import { GenerateBattlerOptions, Colour, Opponents, PlayerActions, } from "./types"; export const validColours = Object.entries(Colour).map((x) => x[0]); export const validOpponents = Object.entries(Opponents).map((x) => x[0]); export const validPlayerActions = Object.entries(PlayerActions).map((x) => x[1]); export async function generateBattler( opts: GenerateBattlerOptions & { direction?: "right" | "left" }, ): Promise { // Image dimensions const canvas = createCanvas(1280, 1280); const context = canvas.getContext("2d"); if (!validColours.includes(opts.colour)) opts.colour = Colour.Black; // Load + draw the necessary images // [Glow] try { if (opts.glow && opts.glow !== "None") { const glow = await loadImage(`./assets/glows/${opts.glow}.png`); context.drawImage(glow, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Back] try { if (opts.back && opts.back !== "None") { const back = await loadImage(`./assets/backs/${opts.back}.png`) context.drawImage(back, 0, 0, canvas.width, canvas.height) } } catch (err) { } // [Base] const base = await loadImage(`./assets/bases/${opts.colour || "Black"}.png`); context.drawImage(base, 0, 0, canvas.width, canvas.height); // [Upper Bottom] try { if (opts.upperBottom && opts.upperBottom !== "None") { const face = await loadImage(`./assets/upperBottom/${opts.face}.png`); context.drawImage(face, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Bottom] try { if (opts.bottom && opts.bottom !== "None") { const bottom = await loadImage(`./assets/bottoms/${opts.bottom}.png`); context.drawImage(bottom, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Top] try { if (opts.top && opts.top !== "None") { const top = await loadImage(`./assets/tops/${opts.top}.png`); context.drawImage(top, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Face] try { if (opts.face && opts.face !== "None") { const face = await loadImage(`./assets/faces/${opts.face}.png`); context.drawImage(face, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Hair] try { if (opts.hair && opts.hair !== "None") { const face = await loadImage(`./assets/hair/${opts.hair}.png`); context.drawImage(face, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Hat] try { if (opts.hat && opts.hat !== "None") { const hat = await loadImage(`./assets/hats/${opts.hat}.png`); context.drawImage(hat, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Eyes] try { if (opts.eye && opts.eye !== "None") { const eye = await loadImage(`./assets/eyes/${opts.eye}.png`); context.drawImage(eye, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Upper Top] try { if (opts.upperTop && opts.upperTop !== "None") { const eye = await loadImage(`./assets/upperTop/${opts.upperTop}.png`); context.drawImage(eye, 0, 0, canvas.width, canvas.height); } } catch (err) { } // [Neck] try { if (opts.neck && opts.neck !== "None") { const neck = await loadImage(`./assets/necks/${opts.neck}.png`) context.drawImage(neck, 0, 0, canvas.width, canvas.height) } } catch (err) { } // [Buddy] try { if (opts.buddy && opts.buddy !== "None") { const buddy = await loadImage(`./assets/buddies/${opts.buddy}.png`) context.drawImage(buddy, 0, 0, canvas.width, canvas.height) } } catch (err) { } if (opts.direction && opts.direction == "left") { let flipped = createCanvas(1280, 1280); let flippedCtx = flipped.getContext("2d"); flippedCtx.scale(-1, 1); flippedCtx.drawImage(canvas, -canvas.width, 0, canvas.width, canvas.height); return flipped; } return canvas; } export function drawText(pos: [number, number], text: string, colour: string, outline: { colour: string, width: number }, ctx: SKRSContext2D) { ctx.strokeStyle = outline.colour; ctx.lineWidth = outline.width; ctx.fillStyle = colour; ctx.strokeText(text, pos[0], pos[1]) ctx.fillText(text, pos[0], pos[1]) } export const applyText = (canvas: Canvas, text: string, width: number) => { const context = canvas.getContext('2d'); // Declare a base size of the font let fontSize = 175; do { // Assign the font to the context and decrement it so it can be measured again context.font = `${fontSize -= 10}px Lilita One`; // Compare pixel width of the text to the canvas minus the approximate avatar size } while (context.measureText(text).width > width); // Return the result to use in the actual canvas return context.font; };