mirror of
				https://github.com/tobspr/shapez.io.git
				synced 2025-06-13 13:04:03 +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();
 |