mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
207 lines
6.9 KiB
JavaScript
207 lines
6.9 KiB
JavaScript
/**
|
|
*
|
|
* Run `yarn global add canvas` first
|
|
*/
|
|
|
|
const { createCanvas, loadImage } = require("canvas");
|
|
const fs = require("fs");
|
|
const path = require("path");
|
|
const { fileURLToPath } = require("url");
|
|
|
|
async function run() {
|
|
console.log("Running");
|
|
|
|
const fps = 14;
|
|
const dimensions = 192;
|
|
const beltBorder = 23.5;
|
|
const lineSize = 5;
|
|
|
|
const borderColor = "#91949e";
|
|
const fillColor = "#d2d4d9";
|
|
const arrowColor = "#c0c2c7";
|
|
|
|
// Generate arrow sprite
|
|
|
|
const arrowW = 60;
|
|
const arrowH = arrowW / 2;
|
|
/** @type {HTMLCanvasElement} */
|
|
const arrowSprite = createCanvas(arrowW, arrowH);
|
|
const arrowContext = arrowSprite.getContext("2d");
|
|
|
|
arrowContext.quality = "best";
|
|
arrowContext.fillStyle = arrowColor;
|
|
arrowContext.clearRect(0, 0, arrowW, arrowH);
|
|
arrowContext.beginPath();
|
|
arrowContext.moveTo(0, arrowH);
|
|
arrowContext.lineTo(arrowW / 2, 0);
|
|
arrowContext.lineTo(arrowW, arrowH);
|
|
arrowContext.closePath();
|
|
arrowContext.fill();
|
|
|
|
const promises = [];
|
|
|
|
// First, generate the forward belt
|
|
for (let i = 0; i < fps; ++i) {
|
|
/** @type {HTMLCanvasElement} */
|
|
const canvas = createCanvas(dimensions, dimensions);
|
|
const context = canvas.getContext("2d");
|
|
context.quality = "best";
|
|
|
|
const procentual = i / fps;
|
|
context.clearRect(0, 0, dimensions, dimensions);
|
|
|
|
context.fillStyle = fillColor;
|
|
context.strokeStyle = borderColor;
|
|
context.lineWidth = lineSize;
|
|
|
|
context.beginPath();
|
|
context.rect(beltBorder, -10, dimensions - 2 * beltBorder, dimensions + 20);
|
|
context.fill();
|
|
context.stroke();
|
|
|
|
const spacingBetweenArrows = (dimensions - 3 * arrowH) / 3;
|
|
const spacingTotal = spacingBetweenArrows + arrowH;
|
|
|
|
for (let k = 0; k < 5; ++k) {
|
|
let y = dimensions - arrowH - (k - 1) * spacingTotal - procentual * spacingTotal;
|
|
context.drawImage(arrowSprite, dimensions / 2 - arrowW / 2, y);
|
|
}
|
|
|
|
const out = fs.createWriteStream(path.join(__dirname, "built", "forward_" + i + ".png"));
|
|
const stream = canvas.createPNGStream();
|
|
stream.pipe(out);
|
|
promises.push(new Promise(resolve => stream.on("end", resolve)));
|
|
}
|
|
|
|
// Generate left and right side belt
|
|
for (let i = 0; i < fps; ++i) {
|
|
/** @type {HTMLCanvasElement} */
|
|
const canvas = createCanvas(dimensions, dimensions);
|
|
const context = canvas.getContext("2d");
|
|
context.quality = "best";
|
|
|
|
const procentual = i / fps;
|
|
const innerRadius = beltBorder;
|
|
context.clearRect(0, 0, dimensions, dimensions);
|
|
|
|
context.fillStyle = fillColor;
|
|
context.strokeStyle = borderColor;
|
|
context.lineWidth = lineSize;
|
|
|
|
context.beginPath();
|
|
context.moveTo(beltBorder, dimensions + 10);
|
|
context.lineTo(beltBorder, dimensions - innerRadius);
|
|
|
|
const steps = 256;
|
|
|
|
const outerRadius = dimensions - 2 * beltBorder;
|
|
|
|
const originX = dimensions - innerRadius;
|
|
const originY = dimensions - innerRadius;
|
|
|
|
const sqrt = x => Math.pow(Math.abs(x), 0.975) * Math.sign(x);
|
|
|
|
for (let k = 0; k <= steps; ++k) {
|
|
const pct = k / steps;
|
|
const angleRad = Math.PI + pct * Math.PI * 0.5;
|
|
const offX = originX + sqrt(Math.cos(angleRad)) * outerRadius;
|
|
const offY = originY + sqrt(Math.sin(angleRad)) * outerRadius;
|
|
|
|
context.lineTo(offX, offY);
|
|
}
|
|
|
|
context.lineTo(dimensions + 10, beltBorder);
|
|
context.lineTo(dimensions + 10, dimensions - beltBorder);
|
|
context.lineTo(dimensions, dimensions - beltBorder);
|
|
|
|
for (let k = 0; k <= steps; ++k) {
|
|
const pct = 1 - k / steps;
|
|
const angleRad = Math.PI + pct * Math.PI * 0.5;
|
|
const offX = dimensions + Math.cos(angleRad) * innerRadius;
|
|
const offY = dimensions + Math.sin(angleRad) * innerRadius;
|
|
|
|
context.lineTo(offX, offY);
|
|
}
|
|
|
|
context.lineTo(dimensions - beltBorder, dimensions + 10);
|
|
|
|
context.closePath();
|
|
context.fill();
|
|
context.stroke();
|
|
|
|
// Arrows
|
|
const rotationalRadius = dimensions / 2 - arrowH / 2 + 0.5;
|
|
|
|
const circumfence = (rotationalRadius * Math.PI * 2) / 4;
|
|
console.log("Circumfence:", circumfence, "px");
|
|
|
|
const remainingSpace = circumfence - 3 * arrowH + arrowH;
|
|
console.log("Remainig:", remainingSpace);
|
|
const spacing = remainingSpace / 3 + arrowH;
|
|
|
|
console.log("Spacing: ", spacing);
|
|
const angleSpacing = ((spacing / circumfence) * Math.PI) / 2;
|
|
|
|
for (let i = 0; i < 5; ++i) {
|
|
let angleRad = Math.PI + procentual * angleSpacing + (i - 1) * angleSpacing;
|
|
const offX = dimensions - arrowH / 2 + Math.cos(angleRad * 0.995) * rotationalRadius;
|
|
const offY = dimensions - arrowH / 2 + Math.sin(angleRad * 0.995) * rotationalRadius;
|
|
|
|
angleRad = Math.max(Math.PI, Math.min(1.5 * Math.PI, angleRad));
|
|
|
|
context.save();
|
|
context.translate(offX, offY);
|
|
context.rotate(angleRad + Math.PI);
|
|
context.drawImage(arrowSprite, -arrowW / 2, -arrowH / 2);
|
|
context.restore();
|
|
}
|
|
|
|
/** @type {HTMLCanvasElement} */
|
|
const flippedCanvas = createCanvas(dimensions, dimensions);
|
|
const flippedContext = flippedCanvas.getContext("2d");
|
|
flippedContext.quality = "best";
|
|
flippedContext.clearRect(0, 0, dimensions, dimensions);
|
|
flippedContext.scale(-1, 1);
|
|
flippedContext.drawImage(canvas, -dimensions, 0, dimensions, dimensions);
|
|
|
|
const outRight = fs.createWriteStream(path.join(__dirname, "built", "right_" + i + ".png"));
|
|
const streamRight = canvas.createPNGStream();
|
|
streamRight.pipe(outRight);
|
|
|
|
const outLeft = fs.createWriteStream(path.join(__dirname, "built", "left_" + i + ".png"));
|
|
const streamLeft = flippedCanvas.createPNGStream();
|
|
streamLeft.pipe(outLeft);
|
|
|
|
promises.push(new Promise(resolve => streamRight.on("end", resolve)));
|
|
promises.push(new Promise(resolve => streamLeft.on("end", resolve)));
|
|
}
|
|
|
|
console.log("Waiting for completion");
|
|
await Promise.all(promises);
|
|
|
|
// Also wait a bit more
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
|
|
console.log("Copying files to all locations");
|
|
|
|
// Copy other files
|
|
fs.copyFileSync(
|
|
path.join(__dirname, "built", "forward_0.png"),
|
|
path.join(__dirname, "..", "buildings", "belt_top.png")
|
|
);
|
|
|
|
fs.copyFileSync(
|
|
path.join(__dirname, "built", "right_0.png"),
|
|
path.join(__dirname, "..", "buildings", "belt_right.png")
|
|
);
|
|
|
|
fs.copyFileSync(
|
|
path.join(__dirname, "built", "left_0.png"),
|
|
path.join(__dirname, "..", "buildings", "belt_left.png")
|
|
);
|
|
|
|
console.log("Done!");
|
|
}
|
|
|
|
run();
|