mirror of
https://github.com/syuilo/ai.git
synced 2024-11-22 05:08:00 +00:00
Refactor
This commit is contained in:
parent
4c378ebf7a
commit
a257c1b622
177
src/modules/maze/gen-maze.ts
Normal file
177
src/modules/maze/gen-maze.ts
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
import * as gen from 'random-seed';
|
||||||
|
import { CellType } from './maze';
|
||||||
|
|
||||||
|
const cellVariants = {
|
||||||
|
empty: {
|
||||||
|
digg: { left: 'left', right: 'right', top: 'top', bottom: 'bottom' },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
digg: { left: null, right: 'leftRight', top: 'leftTop', bottom: 'leftBottom' },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
digg: { left: 'leftRight', right: null, top: 'rightTop', bottom: 'rightBottom' },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
top: {
|
||||||
|
digg: { left: 'leftTop', right: 'rightTop', top: null, bottom: 'topBottom' },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
bottom: {
|
||||||
|
digg: { left: 'leftBottom', right: 'rightBottom', top: 'topBottom', bottom: null },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
leftTop: {
|
||||||
|
digg: { left: null, right: 'leftRightTop', top: null, bottom: 'leftTopBottom' },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
leftBottom: {
|
||||||
|
digg: { left: null, right: 'leftRightBottom', top: 'leftTopBottom', bottom: null },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
rightTop: {
|
||||||
|
digg: { left: 'leftRightTop', right: null, top: null, bottom: 'rightTopBottom' },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
rightBottom: {
|
||||||
|
digg: { left: 'leftRightBottom', right: null, top: 'rightTopBottom', bottom: null },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
leftRightTop: {
|
||||||
|
digg: { left: null, right: null, top: null, bottom: null },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
leftRightBottom: {
|
||||||
|
digg: { left: null, right: null, top: null, bottom: null },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
leftTopBottom: {
|
||||||
|
digg: { left: null, right: null, top: null, bottom: null },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
rightTopBottom: {
|
||||||
|
digg: { left: null, right: null, top: null, bottom: null },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
leftRight: {
|
||||||
|
digg: { left: null, right: null, top: 'leftRightTop', bottom: 'leftRightBottom' },
|
||||||
|
cross: { left: false, right: false, top: true, bottom: true },
|
||||||
|
},
|
||||||
|
topBottom: {
|
||||||
|
digg: { left: 'leftTopBottom', right: 'rightTopBottom', top: null, bottom: null },
|
||||||
|
cross: { left: true, right: true, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
cross: {
|
||||||
|
digg: { left: 'cross', right: 'cross', top: 'cross', bottom: 'cross' },
|
||||||
|
cross: { left: false, right: false, top: false, bottom: false },
|
||||||
|
},
|
||||||
|
} as { [k in CellType]: {
|
||||||
|
digg: { left: CellType | null; right: CellType | null; top: CellType | null; bottom: CellType | null; };
|
||||||
|
cross: { left: boolean; right: boolean; top: boolean; bottom: boolean; };
|
||||||
|
} };
|
||||||
|
|
||||||
|
type Dir = 'left' | 'right' | 'top' | 'bottom';
|
||||||
|
|
||||||
|
export function genMaze(seed) {
|
||||||
|
const rand = gen.create(seed);
|
||||||
|
|
||||||
|
const mazeSize = 11 + rand(21);
|
||||||
|
|
||||||
|
// maze (filled by 'empty')
|
||||||
|
const maze: CellType[][] = new Array(mazeSize);
|
||||||
|
for (let i = 0; i < mazeSize; i++) {
|
||||||
|
maze[i] = new Array(mazeSize).fill('empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
const origin = {
|
||||||
|
x: rand(mazeSize),
|
||||||
|
y: rand(mazeSize),
|
||||||
|
};
|
||||||
|
|
||||||
|
function checkDiggable(x: number, y: number, dir: Dir) {
|
||||||
|
if (cellVariants[maze[x][y]].digg[dir] === null) return false;
|
||||||
|
|
||||||
|
const newPos =
|
||||||
|
dir === 'top' ? { x: x, y: y - 1 } :
|
||||||
|
dir === 'bottom' ? { x: x, y: y + 1 } :
|
||||||
|
dir === 'left' ? { x: x - 1, y: y } :
|
||||||
|
dir === 'right' ? { x: x + 1, y: y } :
|
||||||
|
{ x, y };
|
||||||
|
|
||||||
|
if (newPos.x < 0 || newPos.y < 0 || newPos.x >= mazeSize || newPos.y >= mazeSize) return false;
|
||||||
|
|
||||||
|
const cell = maze[newPos.x][newPos.y];
|
||||||
|
if (cell === 'empty') return true;
|
||||||
|
if (cellVariants[cell].cross[dir] && checkDiggable(newPos.x, newPos.y, dir)) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function diggFrom(x: number, y: number) {
|
||||||
|
const isUpDiggable = checkDiggable(x, y, 'top');
|
||||||
|
const isRightDiggable = checkDiggable(x, y, 'right');
|
||||||
|
const isDownDiggable = checkDiggable(x, y, 'bottom');
|
||||||
|
const isLeftDiggable = checkDiggable(x, y, 'left');
|
||||||
|
|
||||||
|
if (!isUpDiggable && !isRightDiggable && !isDownDiggable && !isLeftDiggable) return;
|
||||||
|
|
||||||
|
const dirs: Dir[] = [];
|
||||||
|
if (isUpDiggable) dirs.push('top');
|
||||||
|
if (isRightDiggable) dirs.push('right');
|
||||||
|
if (isDownDiggable) dirs.push('bottom');
|
||||||
|
if (isLeftDiggable) dirs.push('left');
|
||||||
|
|
||||||
|
const dir = dirs[rand(dirs.length)];
|
||||||
|
|
||||||
|
maze[x][y] = cellVariants[maze[x][y]].digg[dir];
|
||||||
|
|
||||||
|
if (dir === 'top') {
|
||||||
|
maze[x][y - 1] = maze[x][y - 1] === 'empty' ? 'bottom' : 'cross';
|
||||||
|
diggFrom(x, y - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dir === 'right') {
|
||||||
|
maze[x + 1][y] = maze[x + 1][y] === 'empty' ? 'left' : 'cross';
|
||||||
|
diggFrom(x + 1, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dir === 'bottom') {
|
||||||
|
maze[x][y + 1] = maze[x][y + 1] === 'empty' ? 'top' : 'cross';
|
||||||
|
diggFrom(x, y + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dir === 'left') {
|
||||||
|
maze[x - 1][y] = maze[x - 1][y] === 'empty' ? 'right' : 'cross';
|
||||||
|
diggFrom(x - 1, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
diggFrom(origin.x, origin.y);
|
||||||
|
|
||||||
|
let hasEmptyCell = true;
|
||||||
|
while (hasEmptyCell) {
|
||||||
|
const nonEmptyCells = [];
|
||||||
|
|
||||||
|
for (let y = 0; y < mazeSize; y++) {
|
||||||
|
for (let x = 0; x < mazeSize; x++) {
|
||||||
|
const cell = maze[x][y];
|
||||||
|
if (cell !== 'empty' && cell !== 'cross') nonEmptyCells.push([x, y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const pos = nonEmptyCells[rand(nonEmptyCells.length)];
|
||||||
|
|
||||||
|
diggFrom(pos[0], pos[1]);
|
||||||
|
|
||||||
|
hasEmptyCell = false;
|
||||||
|
for (let y = 0; y < mazeSize; y++) {
|
||||||
|
for (let x = 0; x < mazeSize; x++) {
|
||||||
|
if (maze[x][y] === 'empty') hasEmptyCell = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maze;
|
||||||
|
}
|
|
@ -2,147 +2,13 @@
|
||||||
* Random avatar generator
|
* Random avatar generator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const p = require('pureimage');
|
|
||||||
import * as gen from 'random-seed';
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import autobind from 'autobind-decorator';
|
import autobind from 'autobind-decorator';
|
||||||
import Module from '../../module';
|
import Module from '../../module';
|
||||||
import serifs from '../../serifs';
|
import serifs from '../../serifs';
|
||||||
import * as tmp from 'tmp';
|
import * as tmp from 'tmp';
|
||||||
|
import { genMaze } from './gen-maze';
|
||||||
type CellType = 'empty' | 'left' | 'right' | 'top' | 'bottom' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom' | 'leftRightTop' | 'leftRightBottom' | 'leftTopBottom' | 'rightTopBottom' | 'leftRight' | 'topBottom' | 'cross';
|
import { renderMaze } from './render-maze';
|
||||||
|
|
||||||
type Dir = 'left' | 'right' | 'top' | 'bottom';
|
|
||||||
|
|
||||||
const cellVariants = {
|
|
||||||
empty: {
|
|
||||||
digg: { left: 'left', right: 'right', top: 'top', bottom: 'bottom' },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
left: {
|
|
||||||
digg: { left: null, right: 'leftRight', top: 'leftTop', bottom: 'leftBottom' },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
right: {
|
|
||||||
digg: { left: 'leftRight', right: null, top: 'rightTop', bottom: 'rightBottom' },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
top: {
|
|
||||||
digg: { left: 'leftTop', right: 'rightTop', top: null, bottom: 'topBottom' },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
bottom: {
|
|
||||||
digg: { left: 'leftBottom', right: 'rightBottom', top: 'topBottom', bottom: null },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
leftTop: {
|
|
||||||
digg: { left: null, right: 'leftRightTop', top: null, bottom: 'leftTopBottom' },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
leftBottom: {
|
|
||||||
digg: { left: null, right: 'leftRightBottom', top: 'leftTopBottom', bottom: null },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
rightTop: {
|
|
||||||
digg: { left: 'leftRightTop', right: null, top: null, bottom: 'rightTopBottom' },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
rightBottom: {
|
|
||||||
digg: { left: 'leftRightBottom', right: null, top: 'rightTopBottom', bottom: null },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
leftRightTop: {
|
|
||||||
digg: { left: null, right: null, top: null, bottom: null },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
leftRightBottom: {
|
|
||||||
digg: { left: null, right: null, top: null, bottom: null },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
leftTopBottom: {
|
|
||||||
digg: { left: null, right: null, top: null, bottom: null },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
rightTopBottom: {
|
|
||||||
digg: { left: null, right: null, top: null, bottom: null },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
leftRight: {
|
|
||||||
digg: { left: null, right: null, top: 'leftRightTop', bottom: 'leftRightBottom' },
|
|
||||||
cross: { left: false, right: false, top: true, bottom: true },
|
|
||||||
},
|
|
||||||
topBottom: {
|
|
||||||
digg: { left: 'leftTopBottom', right: 'rightTopBottom', top: null, bottom: null },
|
|
||||||
cross: { left: true, right: true, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
cross: {
|
|
||||||
digg: { left: 'cross', right: 'cross', top: 'cross', bottom: 'cross' },
|
|
||||||
cross: { left: false, right: false, top: false, bottom: false },
|
|
||||||
},
|
|
||||||
} as { [k in CellType]: {
|
|
||||||
digg: { left: CellType | null; right: CellType | null; top: CellType | null; bottom: CellType | null; };
|
|
||||||
cross: { left: boolean; right: boolean; top: boolean; bottom: boolean; };
|
|
||||||
} };
|
|
||||||
|
|
||||||
const imageSize = 2048; // px
|
|
||||||
const margin = 192;
|
|
||||||
const mazeAreaSize = imageSize - (margin * 2);
|
|
||||||
|
|
||||||
const themes = [{
|
|
||||||
bg1: '#C1D9CE',
|
|
||||||
bg2: '#F2EDD5',
|
|
||||||
wall: '#0F8AA6',
|
|
||||||
road: '#C1D9CE',
|
|
||||||
marker: '#84BFBF',
|
|
||||||
}, {
|
|
||||||
bg1: '#17275B',
|
|
||||||
bg2: '#1F2E67',
|
|
||||||
wall: '#17275B',
|
|
||||||
road: '#6A77A4',
|
|
||||||
marker: '#E6E5E3',
|
|
||||||
}, {
|
|
||||||
bg1: '#BFD962',
|
|
||||||
bg2: '#EAF2AC',
|
|
||||||
wall: '#1E4006',
|
|
||||||
road: '#BFD962',
|
|
||||||
marker: '#74A608',
|
|
||||||
}, {
|
|
||||||
bg1: '#C0CCB8',
|
|
||||||
bg2: '#FFE2C0',
|
|
||||||
wall: '#664A3C',
|
|
||||||
road: '#FFCB99',
|
|
||||||
marker: '#E78F72',
|
|
||||||
}, {
|
|
||||||
bg1: '#101010',
|
|
||||||
bg2: '#151515',
|
|
||||||
wall: '#909090',
|
|
||||||
road: '#202020',
|
|
||||||
marker: '#606060',
|
|
||||||
}, {
|
|
||||||
bg1: '#e0e0e0',
|
|
||||||
bg2: '#f2f2f2',
|
|
||||||
wall: '#a0a0a0',
|
|
||||||
road: '#e0e0e0',
|
|
||||||
marker: '#707070',
|
|
||||||
}, {
|
|
||||||
bg1: '#7DE395',
|
|
||||||
bg2: '#D0F3CF',
|
|
||||||
wall: '#349D9E',
|
|
||||||
road: '#7DE395',
|
|
||||||
marker: '#56C495',
|
|
||||||
}, {
|
|
||||||
bg1: '#C9EEEA',
|
|
||||||
bg2: '#DBF4F1',
|
|
||||||
wall: '#4BC6B9',
|
|
||||||
road: '#C9EEEA',
|
|
||||||
marker: '#19A89D',
|
|
||||||
}, {
|
|
||||||
bg1: '#1e231b',
|
|
||||||
bg2: '#27331e',
|
|
||||||
wall: '#67b231',
|
|
||||||
road: '#385622',
|
|
||||||
marker: '#78d337',
|
|
||||||
}];
|
|
||||||
|
|
||||||
export default class extends Module {
|
export default class extends Module {
|
||||||
public readonly name = 'maze';
|
public readonly name = 'maze';
|
||||||
|
@ -168,11 +34,11 @@ export default class extends Module {
|
||||||
const seed = date;
|
const seed = date;
|
||||||
|
|
||||||
this.log('Maze generating...');
|
this.log('Maze generating...');
|
||||||
const maze = this.genMize(seed);
|
const maze = genMaze(seed);
|
||||||
|
|
||||||
this.log('Maze rendering...');
|
this.log('Maze rendering...');
|
||||||
const [temp] = await this.createTemp();
|
const [temp] = await this.createTemp();
|
||||||
await this.renderMaze(seed, maze, fs.createWriteStream(temp));
|
await renderMaze(seed, maze, fs.createWriteStream(temp));
|
||||||
|
|
||||||
this.log('Image uploading...');
|
this.log('Image uploading...');
|
||||||
const file = await this.ai.upload(fs.createReadStream(temp));
|
const file = await this.ai.upload(fs.createReadStream(temp));
|
||||||
|
@ -193,316 +59,4 @@ export default class extends Module {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@autobind
|
|
||||||
private genMize(seed) {
|
|
||||||
const rand = gen.create(seed);
|
|
||||||
|
|
||||||
const mazeSize = 11 + rand(21);
|
|
||||||
|
|
||||||
// maze (filled by 'empty')
|
|
||||||
const maze: CellType[][] = new Array(mazeSize);
|
|
||||||
for (let i = 0; i < mazeSize; i++) {
|
|
||||||
maze[i] = new Array(mazeSize).fill('empty');
|
|
||||||
}
|
|
||||||
|
|
||||||
const origin = {
|
|
||||||
x: rand(mazeSize),
|
|
||||||
y: rand(mazeSize),
|
|
||||||
};
|
|
||||||
|
|
||||||
function checkDiggable(x: number, y: number, dir: Dir) {
|
|
||||||
if (cellVariants[maze[x][y]].digg[dir] === null) return false;
|
|
||||||
|
|
||||||
const newPos =
|
|
||||||
dir === 'top' ? { x: x, y: y - 1 } :
|
|
||||||
dir === 'bottom' ? { x: x, y: y + 1 } :
|
|
||||||
dir === 'left' ? { x: x - 1, y: y } :
|
|
||||||
dir === 'right' ? { x: x + 1, y: y } :
|
|
||||||
{ x, y };
|
|
||||||
|
|
||||||
if (newPos.x < 0 || newPos.y < 0 || newPos.x >= mazeSize || newPos.y >= mazeSize) return false;
|
|
||||||
|
|
||||||
const cell = maze[newPos.x][newPos.y];
|
|
||||||
if (cell === 'empty') return true;
|
|
||||||
if (cellVariants[cell].cross[dir] && checkDiggable(newPos.x, newPos.y, dir)) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function diggFrom(x: number, y: number) {
|
|
||||||
const isUpDiggable = checkDiggable(x, y, 'top');
|
|
||||||
const isRightDiggable = checkDiggable(x, y, 'right');
|
|
||||||
const isDownDiggable = checkDiggable(x, y, 'bottom');
|
|
||||||
const isLeftDiggable = checkDiggable(x, y, 'left');
|
|
||||||
|
|
||||||
if (!isUpDiggable && !isRightDiggable && !isDownDiggable && !isLeftDiggable) return;
|
|
||||||
|
|
||||||
const dirs: Dir[] = [];
|
|
||||||
if (isUpDiggable) dirs.push('top');
|
|
||||||
if (isRightDiggable) dirs.push('right');
|
|
||||||
if (isDownDiggable) dirs.push('bottom');
|
|
||||||
if (isLeftDiggable) dirs.push('left');
|
|
||||||
|
|
||||||
const dir = dirs[rand(dirs.length)];
|
|
||||||
|
|
||||||
maze[x][y] = cellVariants[maze[x][y]].digg[dir];
|
|
||||||
|
|
||||||
if (dir === 'top') {
|
|
||||||
maze[x][y - 1] = maze[x][y - 1] === 'empty' ? 'bottom' : 'cross';
|
|
||||||
diggFrom(x, y - 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dir === 'right') {
|
|
||||||
maze[x + 1][y] = maze[x + 1][y] === 'empty' ? 'left' : 'cross';
|
|
||||||
diggFrom(x + 1, y);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dir === 'bottom') {
|
|
||||||
maze[x][y + 1] = maze[x][y + 1] === 'empty' ? 'top' : 'cross';
|
|
||||||
diggFrom(x, y + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dir === 'left') {
|
|
||||||
maze[x - 1][y] = maze[x - 1][y] === 'empty' ? 'right' : 'cross';
|
|
||||||
diggFrom(x - 1, y);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diggFrom(origin.x, origin.y);
|
|
||||||
|
|
||||||
let hasEmptyCell = true;
|
|
||||||
while (hasEmptyCell) {
|
|
||||||
const nonEmptyCells = [];
|
|
||||||
|
|
||||||
for (let y = 0; y < mazeSize; y++) {
|
|
||||||
for (let x = 0; x < mazeSize; x++) {
|
|
||||||
const cell = maze[x][y];
|
|
||||||
if (cell !== 'empty' && cell !== 'cross') nonEmptyCells.push([x, y]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const pos = nonEmptyCells[rand(nonEmptyCells.length)];
|
|
||||||
|
|
||||||
diggFrom(pos[0], pos[1]);
|
|
||||||
|
|
||||||
hasEmptyCell = false;
|
|
||||||
for (let y = 0; y < mazeSize; y++) {
|
|
||||||
for (let x = 0; x < mazeSize; x++) {
|
|
||||||
if (maze[x][y] === 'empty') hasEmptyCell = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return maze;
|
|
||||||
}
|
|
||||||
|
|
||||||
@autobind
|
|
||||||
private renderMaze(seed, maze: CellType[][], stream: fs.WriteStream): Promise<void> {
|
|
||||||
const rand = gen.create(seed);
|
|
||||||
const mazeSize = maze.length;
|
|
||||||
|
|
||||||
const colors = themes[rand(themes.length)];
|
|
||||||
|
|
||||||
const canvas = p.make(imageSize, imageSize);
|
|
||||||
const ctx = canvas.getContext('2d');
|
|
||||||
|
|
||||||
ctx.fillStyle = colors.bg1;
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(0, 0, imageSize, imageSize);
|
|
||||||
|
|
||||||
ctx.fillStyle = colors.bg2;
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(margin / 2, margin / 2, imageSize - ((margin / 2) * 2), imageSize - ((margin / 2) * 2));
|
|
||||||
|
|
||||||
// Draw
|
|
||||||
function drawCell(ctx, x, y, size, left, right, top, bottom, mark) {
|
|
||||||
const wallThickness = size / 8;
|
|
||||||
const wallMargin = size / 4;
|
|
||||||
const markerMargin = size / 3;
|
|
||||||
|
|
||||||
ctx.fillStyle = colors.road;
|
|
||||||
if (left) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x, y + wallMargin, size - wallMargin, size - (wallMargin * 2));
|
|
||||||
}
|
|
||||||
if (right) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x + wallMargin, y + wallMargin, size - wallMargin, size - (wallMargin * 2));
|
|
||||||
}
|
|
||||||
if (top) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x + wallMargin, y, size - (wallMargin * 2), size - wallMargin);
|
|
||||||
}
|
|
||||||
if (bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x + wallMargin, y + wallMargin, size - (wallMargin * 2), size - wallMargin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mark) {
|
|
||||||
ctx.fillStyle = colors.marker;
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x + markerMargin, y + markerMargin, size - (markerMargin * 2), size - (markerMargin * 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
const wallLeftTopX = x + wallMargin - (wallThickness / 2);
|
|
||||||
const wallLeftTopY = y + wallMargin - (wallThickness / 2);
|
|
||||||
const wallRightTopX = x + size - wallMargin - (wallThickness / 2);
|
|
||||||
const wallRightTopY = y + wallMargin - (wallThickness / 2);
|
|
||||||
const wallLeftBottomX = x + wallMargin - (wallThickness / 2);
|
|
||||||
const wallLeftBottomY = y + size - wallMargin - (wallThickness / 2);
|
|
||||||
const wallRightBottomX = x + size - wallMargin - (wallThickness / 2);
|
|
||||||
const wallRightBottomY = y + size - wallMargin - (wallThickness / 2);
|
|
||||||
|
|
||||||
ctx.fillStyle = colors.wall;
|
|
||||||
if (left && right && top && bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
if (rand(2) === 0) {
|
|
||||||
ctx.fillRect(x + wallMargin - (wallThickness / 2), y, wallThickness, size);
|
|
||||||
ctx.fillRect(x + size - wallMargin - (wallThickness / 2), y, wallThickness, size);
|
|
||||||
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
|
||||||
ctx.fillRect(x + size - wallMargin, y + wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
|
||||||
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
|
||||||
ctx.fillRect(x + size - wallMargin, y + size - wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
|
||||||
} else {
|
|
||||||
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size, wallThickness);
|
|
||||||
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), size, wallThickness);
|
|
||||||
ctx.fillRect(wallLeftTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallRightTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallLeftTopX, wallLeftBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallRightTopX, wallRightBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!left && right && !top && bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (right && bottom) {
|
|
||||||
ctx.fillRect(wallRightBottomX, wallRightBottomY, wallMargin + (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(wallRightBottomX, wallRightBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left && !right && !top && bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size - wallMargin + (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(wallRightTopX, y + wallMargin - (wallThickness / 2), wallThickness, size - wallMargin + (wallThickness / 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left && bottom) {
|
|
||||||
ctx.fillRect(x, wallLeftBottomY, wallMargin - (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!left && right && top && !bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(wallLeftBottomX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (right && top) {
|
|
||||||
ctx.fillRect(wallRightTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallRightTopX, wallRightTopY, size - wallMargin - (wallThickness * 2), wallThickness);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left && !right && top && !bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x, wallLeftBottomY, size - wallMargin - (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(wallRightTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left && top) {
|
|
||||||
ctx.fillRect(wallLeftTopX, y, wallThickness, wallMargin + (wallThickness / 2));
|
|
||||||
ctx.fillRect(x, wallLeftTopY, wallMargin - (wallThickness / 2), wallThickness);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!left && right && !top && !bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin - (wallThickness * 2));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (left && !right && !top && !bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(x, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
|
||||||
ctx.fillRect(wallRightTopX, wallRightTopY, wallThickness, size - wallMargin - (wallThickness * 2));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!left && !right && !top && bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallRightTopX, wallRightTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin - (wallThickness * 2), wallThickness);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!left && !right && top && !bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(wallLeftTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallRightTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
|
||||||
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin - (wallThickness * 2), wallThickness);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (top && bottom) {
|
|
||||||
if (!left) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x + wallMargin - (wallThickness / 2), y, wallThickness, size);
|
|
||||||
}
|
|
||||||
if (!right) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x + size - wallMargin - (wallThickness / 2), y, wallThickness, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (left && right) {
|
|
||||||
if (!top) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size, wallThickness);
|
|
||||||
}
|
|
||||||
if (!bottom) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), size, wallThickness);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const cellSize = mazeAreaSize / mazeSize;
|
|
||||||
|
|
||||||
for (let x = 0; x < mazeSize; x++) {
|
|
||||||
for (let y = 0; y < mazeSize; y++) {
|
|
||||||
const actualX = margin + (cellSize * x);
|
|
||||||
const actualY = margin + (cellSize * y);
|
|
||||||
|
|
||||||
const cell = maze[x][y];
|
|
||||||
|
|
||||||
const mark = (x === 0 && y === 0) || (x === mazeSize - 1 && y === mazeSize - 1);
|
|
||||||
|
|
||||||
if (cell === 'left') drawCell(ctx, actualX, actualY, cellSize, true, false, false, false, mark);
|
|
||||||
if (cell === 'right') drawCell(ctx, actualX, actualY, cellSize, false, true, false, false, mark);
|
|
||||||
if (cell === 'top') drawCell(ctx, actualX, actualY, cellSize, false, false, true, false, mark);
|
|
||||||
if (cell === 'bottom') drawCell(ctx, actualX, actualY, cellSize, false, false, false, true, mark);
|
|
||||||
if (cell === 'leftTop') drawCell(ctx, actualX, actualY, cellSize, true, false, true, false, mark);
|
|
||||||
if (cell === 'leftBottom') drawCell(ctx, actualX, actualY, cellSize, true, false, false, true, mark);
|
|
||||||
if (cell === 'rightTop') drawCell(ctx, actualX, actualY, cellSize, false, true, true, false, mark);
|
|
||||||
if (cell === 'rightBottom') drawCell(ctx, actualX, actualY, cellSize, false, true, false, true, mark);
|
|
||||||
if (cell === 'leftRightTop') drawCell(ctx, actualX, actualY, cellSize, true, true, true, false, mark);
|
|
||||||
if (cell === 'leftRightBottom') drawCell(ctx, actualX, actualY, cellSize, true, true, false, true, mark);
|
|
||||||
if (cell === 'leftTopBottom') drawCell(ctx, actualX, actualY, cellSize, true, false, true, true, mark);
|
|
||||||
if (cell === 'rightTopBottom') drawCell(ctx, actualX, actualY, cellSize, false, true, true, true, mark);
|
|
||||||
if (cell === 'leftRight') drawCell(ctx, actualX, actualY, cellSize, true, true, false, false, mark);
|
|
||||||
if (cell === 'topBottom') drawCell(ctx, actualX, actualY, cellSize, false, false, true, true, mark);
|
|
||||||
if (cell === 'cross') drawCell(ctx, actualX, actualY, cellSize, true, true, true, true, mark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return p.encodePNGToStream(canvas, stream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
1
src/modules/maze/maze.ts
Normal file
1
src/modules/maze/maze.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export type CellType = 'empty' | 'left' | 'right' | 'top' | 'bottom' | 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom' | 'leftRightTop' | 'leftRightBottom' | 'leftTopBottom' | 'rightTopBottom' | 'leftRight' | 'topBottom' | 'cross';
|
217
src/modules/maze/render-maze.ts
Normal file
217
src/modules/maze/render-maze.ts
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as gen from 'random-seed';
|
||||||
|
const p = require('pureimage');
|
||||||
|
|
||||||
|
import { CellType } from './maze';
|
||||||
|
import { themes } from './themes';
|
||||||
|
|
||||||
|
const imageSize = 2048; // px
|
||||||
|
const margin = 192;
|
||||||
|
const mazeAreaSize = imageSize - (margin * 2);
|
||||||
|
|
||||||
|
export function renderMaze(seed, maze: CellType[][], stream: fs.WriteStream): Promise<void> {
|
||||||
|
const rand = gen.create(seed);
|
||||||
|
const mazeSize = maze.length;
|
||||||
|
|
||||||
|
const colors = themes[rand(themes.length)];
|
||||||
|
|
||||||
|
const canvas = p.make(imageSize, imageSize);
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
ctx.fillStyle = colors.bg1;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(0, 0, imageSize, imageSize);
|
||||||
|
|
||||||
|
ctx.fillStyle = colors.bg2;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(margin / 2, margin / 2, imageSize - ((margin / 2) * 2), imageSize - ((margin / 2) * 2));
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
function drawCell(ctx, x, y, size, left, right, top, bottom, mark) {
|
||||||
|
const wallThickness = size / 8;
|
||||||
|
const wallMargin = size / 4;
|
||||||
|
const markerMargin = size / 3;
|
||||||
|
|
||||||
|
ctx.fillStyle = colors.road;
|
||||||
|
if (left) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x, y + wallMargin, size - wallMargin, size - (wallMargin * 2));
|
||||||
|
}
|
||||||
|
if (right) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x + wallMargin, y + wallMargin, size - wallMargin, size - (wallMargin * 2));
|
||||||
|
}
|
||||||
|
if (top) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x + wallMargin, y, size - (wallMargin * 2), size - wallMargin);
|
||||||
|
}
|
||||||
|
if (bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x + wallMargin, y + wallMargin, size - (wallMargin * 2), size - wallMargin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mark) {
|
||||||
|
ctx.fillStyle = colors.marker;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x + markerMargin, y + markerMargin, size - (markerMargin * 2), size - (markerMargin * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
const wallLeftTopX = x + wallMargin - (wallThickness / 2);
|
||||||
|
const wallLeftTopY = y + wallMargin - (wallThickness / 2);
|
||||||
|
const wallRightTopX = x + size - wallMargin - (wallThickness / 2);
|
||||||
|
const wallRightTopY = y + wallMargin - (wallThickness / 2);
|
||||||
|
const wallLeftBottomX = x + wallMargin - (wallThickness / 2);
|
||||||
|
const wallLeftBottomY = y + size - wallMargin - (wallThickness / 2);
|
||||||
|
const wallRightBottomX = x + size - wallMargin - (wallThickness / 2);
|
||||||
|
const wallRightBottomY = y + size - wallMargin - (wallThickness / 2);
|
||||||
|
|
||||||
|
ctx.fillStyle = colors.wall;
|
||||||
|
if (left && right && top && bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
if (rand(2) === 0) {
|
||||||
|
ctx.fillRect(x + wallMargin - (wallThickness / 2), y, wallThickness, size);
|
||||||
|
ctx.fillRect(x + size - wallMargin - (wallThickness / 2), y, wallThickness, size);
|
||||||
|
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
||||||
|
ctx.fillRect(x + size - wallMargin, y + wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
||||||
|
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
||||||
|
ctx.fillRect(x + size - wallMargin, y + size - wallMargin - (wallThickness / 2), wallMargin, wallThickness);
|
||||||
|
} else {
|
||||||
|
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size, wallThickness);
|
||||||
|
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), size, wallThickness);
|
||||||
|
ctx.fillRect(wallLeftTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallRightTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallLeftTopX, wallLeftBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallRightTopX, wallRightBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!left && right && !top && bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (right && bottom) {
|
||||||
|
ctx.fillRect(wallRightBottomX, wallRightBottomY, wallMargin + (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(wallRightBottomX, wallRightBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left && !right && !top && bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size - wallMargin + (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(wallRightTopX, y + wallMargin - (wallThickness / 2), wallThickness, size - wallMargin + (wallThickness / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left && bottom) {
|
||||||
|
ctx.fillRect(x, wallLeftBottomY, wallMargin - (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, wallThickness, wallMargin + (wallThickness / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!left && right && top && !bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(wallLeftBottomX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (right && top) {
|
||||||
|
ctx.fillRect(wallRightTopX, y, wallThickness, wallMargin - (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallRightTopX, wallRightTopY, size - wallMargin - (wallThickness * 2), wallThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left && !right && top && !bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x, wallLeftBottomY, size - wallMargin - (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(wallRightTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left && top) {
|
||||||
|
ctx.fillRect(wallLeftTopX, y, wallThickness, wallMargin + (wallThickness / 2));
|
||||||
|
ctx.fillRect(x, wallLeftTopY, wallMargin - (wallThickness / 2), wallThickness);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!left && right && !top && !bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin - (wallThickness * 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left && !right && !top && !bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x, wallLeftTopY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(x, wallLeftBottomY, size - wallMargin + (wallThickness / 2), wallThickness);
|
||||||
|
ctx.fillRect(wallRightTopX, wallRightTopY, wallThickness, size - wallMargin - (wallThickness * 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!left && !right && !top && bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(wallLeftTopX, wallLeftTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallRightTopX, wallRightTopY, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallLeftTopX, wallLeftTopY, size - wallMargin - (wallThickness * 2), wallThickness);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!left && !right && top && !bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(wallLeftTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallRightTopX, y, wallThickness, size - wallMargin + (wallThickness / 2));
|
||||||
|
ctx.fillRect(wallLeftBottomX, wallLeftBottomY, size - wallMargin - (wallThickness * 2), wallThickness);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top && bottom) {
|
||||||
|
if (!left) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x + wallMargin - (wallThickness / 2), y, wallThickness, size);
|
||||||
|
}
|
||||||
|
if (!right) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x + size - wallMargin - (wallThickness / 2), y, wallThickness, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (left && right) {
|
||||||
|
if (!top) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x, y + wallMargin - (wallThickness / 2), size, wallThickness);
|
||||||
|
}
|
||||||
|
if (!bottom) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.fillRect(x, y + size - wallMargin - (wallThickness / 2), size, wallThickness);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cellSize = mazeAreaSize / mazeSize;
|
||||||
|
|
||||||
|
for (let x = 0; x < mazeSize; x++) {
|
||||||
|
for (let y = 0; y < mazeSize; y++) {
|
||||||
|
const actualX = margin + (cellSize * x);
|
||||||
|
const actualY = margin + (cellSize * y);
|
||||||
|
|
||||||
|
const cell = maze[x][y];
|
||||||
|
|
||||||
|
const mark = (x === 0 && y === 0) || (x === mazeSize - 1 && y === mazeSize - 1);
|
||||||
|
|
||||||
|
if (cell === 'left') drawCell(ctx, actualX, actualY, cellSize, true, false, false, false, mark);
|
||||||
|
if (cell === 'right') drawCell(ctx, actualX, actualY, cellSize, false, true, false, false, mark);
|
||||||
|
if (cell === 'top') drawCell(ctx, actualX, actualY, cellSize, false, false, true, false, mark);
|
||||||
|
if (cell === 'bottom') drawCell(ctx, actualX, actualY, cellSize, false, false, false, true, mark);
|
||||||
|
if (cell === 'leftTop') drawCell(ctx, actualX, actualY, cellSize, true, false, true, false, mark);
|
||||||
|
if (cell === 'leftBottom') drawCell(ctx, actualX, actualY, cellSize, true, false, false, true, mark);
|
||||||
|
if (cell === 'rightTop') drawCell(ctx, actualX, actualY, cellSize, false, true, true, false, mark);
|
||||||
|
if (cell === 'rightBottom') drawCell(ctx, actualX, actualY, cellSize, false, true, false, true, mark);
|
||||||
|
if (cell === 'leftRightTop') drawCell(ctx, actualX, actualY, cellSize, true, true, true, false, mark);
|
||||||
|
if (cell === 'leftRightBottom') drawCell(ctx, actualX, actualY, cellSize, true, true, false, true, mark);
|
||||||
|
if (cell === 'leftTopBottom') drawCell(ctx, actualX, actualY, cellSize, true, false, true, true, mark);
|
||||||
|
if (cell === 'rightTopBottom') drawCell(ctx, actualX, actualY, cellSize, false, true, true, true, mark);
|
||||||
|
if (cell === 'leftRight') drawCell(ctx, actualX, actualY, cellSize, true, true, false, false, mark);
|
||||||
|
if (cell === 'topBottom') drawCell(ctx, actualX, actualY, cellSize, false, false, true, true, mark);
|
||||||
|
if (cell === 'cross') drawCell(ctx, actualX, actualY, cellSize, true, true, true, true, mark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.encodePNGToStream(canvas, stream);
|
||||||
|
}
|
55
src/modules/maze/themes.ts
Normal file
55
src/modules/maze/themes.ts
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
export const themes = [{
|
||||||
|
bg1: '#C1D9CE',
|
||||||
|
bg2: '#F2EDD5',
|
||||||
|
wall: '#0F8AA6',
|
||||||
|
road: '#C1D9CE',
|
||||||
|
marker: '#84BFBF',
|
||||||
|
}, {
|
||||||
|
bg1: '#17275B',
|
||||||
|
bg2: '#1F2E67',
|
||||||
|
wall: '#17275B',
|
||||||
|
road: '#6A77A4',
|
||||||
|
marker: '#E6E5E3',
|
||||||
|
}, {
|
||||||
|
bg1: '#BFD962',
|
||||||
|
bg2: '#EAF2AC',
|
||||||
|
wall: '#1E4006',
|
||||||
|
road: '#BFD962',
|
||||||
|
marker: '#74A608',
|
||||||
|
}, {
|
||||||
|
bg1: '#C0CCB8',
|
||||||
|
bg2: '#FFE2C0',
|
||||||
|
wall: '#664A3C',
|
||||||
|
road: '#FFCB99',
|
||||||
|
marker: '#E78F72',
|
||||||
|
}, {
|
||||||
|
bg1: '#101010',
|
||||||
|
bg2: '#151515',
|
||||||
|
wall: '#909090',
|
||||||
|
road: '#202020',
|
||||||
|
marker: '#606060',
|
||||||
|
}, {
|
||||||
|
bg1: '#e0e0e0',
|
||||||
|
bg2: '#f2f2f2',
|
||||||
|
wall: '#a0a0a0',
|
||||||
|
road: '#e0e0e0',
|
||||||
|
marker: '#707070',
|
||||||
|
}, {
|
||||||
|
bg1: '#7DE395',
|
||||||
|
bg2: '#D0F3CF',
|
||||||
|
wall: '#349D9E',
|
||||||
|
road: '#7DE395',
|
||||||
|
marker: '#56C495',
|
||||||
|
}, {
|
||||||
|
bg1: '#C9EEEA',
|
||||||
|
bg2: '#DBF4F1',
|
||||||
|
wall: '#4BC6B9',
|
||||||
|
road: '#C9EEEA',
|
||||||
|
marker: '#19A89D',
|
||||||
|
}, {
|
||||||
|
bg1: '#1e231b',
|
||||||
|
bg2: '#27331e',
|
||||||
|
wall: '#67b231',
|
||||||
|
road: '#385622',
|
||||||
|
marker: '#78d337',
|
||||||
|
}];
|
Loading…
Reference in a new issue