🚀 gif creator

This commit is contained in:
platane
2020-07-19 12:36:10 +02:00
parent 1799d05bbf
commit 59e24fcb37
6 changed files with 130 additions and 41 deletions

1
packages/gif-creator/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
out.gif

View File

@@ -0,0 +1,42 @@
import { createGif } from "..";
import { generateGrid } from "@snk/compute/generateGrid";
import { computeBestRun } from "@snk/compute";
const drawOptions = {
sizeBorderRadius: 2,
sizeCell: 16,
sizeDot: 12,
colorBorder: "#1b1f230a",
colorDots: { 1: "#9be9a8", 2: "#40c463", 3: "#30a14e", 4: "#216e39" },
colorEmpty: "#ebedf0",
colorSnake: "purple",
};
const gameOptions = { maxSnakeLength: 5 };
const gifOptions = { delay: 200 };
it("should generate gif", async () => {
const grid = generateGrid(14, 7, { colors: [1, 2, 3, 4], emptyP: 3 });
const snake = [
{ x: 4, y: -1 },
{ x: 3, y: -1 },
{ x: 2, y: -1 },
{ x: 1, y: -1 },
{ x: 0, y: -1 },
];
const commands = computeBestRun(grid, snake, gameOptions).slice(0, 9);
const gif = await createGif(
grid,
snake,
commands,
drawOptions,
gameOptions,
gifOptions
);
expect(gif).toBeDefined();
});

View File

@@ -14,7 +14,9 @@ const drawOptions = {
const gameOptions = { maxSnakeLength: 5 };
const grid = generateGrid(14, 7, { colors: [1, 2, 3, 4], emptyP: 3 });
const gifOptions = { delay: 100 };
const grid = generateGrid(42, 7, { colors: [1, 2, 3, 4], emptyP: 3 });
const snake = [
{ x: 4, y: -1 },
@@ -26,4 +28,8 @@ const snake = [
const commands = computeBestRun(grid, snake, gameOptions);
createGif(grid, snake, commands, drawOptions, gameOptions);
createGif(grid, snake, commands, drawOptions, gameOptions, gifOptions).then(
(buffer) => {
process.stdout.write(buffer);
}
);

View File

@@ -6,16 +6,17 @@ import { Point } from "@snk/compute/point";
import { copySnake } from "@snk/compute/snake";
import { drawWorld } from "@snk/draw/drawWorld";
import { step } from "@snk/compute/step";
import * as tmp from "tmp";
// @ts-ignore
import * as mkdirp from "mkdirp";
import * as execa from "execa";
export const createGif = (
export const createGif = async (
grid0: Grid,
snake0: Point[],
commands: Point[],
drawOptions: Parameters<typeof drawWorld>[4],
gameOptions: Parameters<typeof step>[4]
gameOptions: Parameters<typeof step>[4],
gifOptions: { delay: number }
) => {
const grid = copyGrid(grid0);
const snake = copySnake(snake0);
@@ -24,14 +25,17 @@ export const createGif = (
const width = drawOptions.sizeCell * (grid.width + 4);
const height = drawOptions.sizeCell * (grid.height + 4) + 100;
const dir = path.join(__dirname, "tmp", Math.random().toString(36).slice(2));
mkdirp.sync(dir);
const { name: dir, removeCallback: cleanUp } = tmp.dirSync({
unsafeCleanup: true,
});
const canvas = createCanvas(width, height);
const ctx = canvas.getContext("2d")!;
const writeImage = (i: number) => {
ctx.clearRect(0, 0, 99999, 99999);
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, 99999, 99999);
drawWorld(ctx, grid, snake, stack, drawOptions);
const buffer = canvas.toBuffer("image/png", {
@@ -39,17 +43,39 @@ export const createGif = (
filters: canvas.PNG_FILTER_NONE,
});
const filename = path.join(dir, `${i.toString().padStart(4, "0")}.png`);
const fileName = path.join(dir, `${i.toString().padStart(4, "0")}.png`);
console.log(filename);
fs.writeFileSync(filename, buffer);
fs.writeFileSync(fileName, buffer);
};
writeImage(0);
try {
writeImage(0);
for (let i = 0; i < commands.length; i++) {
step(grid, snake, stack, commands[i], gameOptions);
writeImage(i + 1);
for (let i = 0; i < commands.length; i++) {
step(grid, snake, stack, commands[i], gameOptions);
writeImage(i + 1);
}
const outFileName = path.join(dir, "out.gif");
await execa(
"gm",
[
"convert",
["-loop", "0"],
["-delay", gifOptions.delay.toString()],
["-dispose", "2"],
// ["-layers", "OptimizeFrame"],
["-compress", "LZW"],
["-strip"],
path.join(dir, "*.png"),
outFileName,
].flat()
);
return fs.readFileSync(outFileName);
} finally {
cleanUp();
}
};

View File

@@ -5,13 +5,15 @@
"@snk/compute": "1.0.0",
"@snk/draw": "1.0.0",
"canvas": "2.6.1",
"mkdirp": "1.0.4"
"execa": "4.0.3",
"tmp": "0.2.1"
},
"devDependencies": {
"@types/mkdirp": "1.0.1",
"@types/execa": "2.0.0",
"@types/tmp": "0.2.0",
"@zeit/ncc": "0.22.3"
},
"scripts": {
"dev": "ncc run __tests__/dev.ts"
"dev": "ncc run __tests__/dev.ts --quiet | tail -n +2 > out.gif "
}
}