|
|
@ -60,8 +60,8 @@ const RENDERER_FPS = 30
|
|
|
|
function setup() {
|
|
|
|
function setup() {
|
|
|
|
console.log('Setting up circuits art...')
|
|
|
|
console.log('Setting up circuits art...')
|
|
|
|
|
|
|
|
|
|
|
|
$canvas.width = $canvas.clientWidth
|
|
|
|
$canvas.width = $canvas.clientWidth * window.devicePixelRatio
|
|
|
|
$canvas.height = $canvas.clientHeight
|
|
|
|
$canvas.height = $canvas.clientHeight * window.devicePixelRatio
|
|
|
|
|
|
|
|
|
|
|
|
const g = $canvas.getContext('2d')!
|
|
|
|
const g = $canvas.getContext('2d')!
|
|
|
|
const state: State = {
|
|
|
|
const state: State = {
|
|
|
@ -75,14 +75,19 @@ function setup() {
|
|
|
|
const handle = window.setInterval(() => {
|
|
|
|
const handle = window.setInterval(() => {
|
|
|
|
const time = new Date().getTime() - startTime.getTime()
|
|
|
|
const time = new Date().getTime() - startTime.getTime()
|
|
|
|
|
|
|
|
|
|
|
|
update(state, g.canvas.width, g.canvas.height, time)
|
|
|
|
update(
|
|
|
|
|
|
|
|
state,
|
|
|
|
|
|
|
|
g.canvas.width / window.devicePixelRatio,
|
|
|
|
|
|
|
|
g.canvas.height / window.devicePixelRatio,
|
|
|
|
|
|
|
|
time
|
|
|
|
|
|
|
|
)
|
|
|
|
render(g, state, time)
|
|
|
|
render(g, state, time)
|
|
|
|
}, 1000 / RENDERER_FPS)
|
|
|
|
}, 1000 / RENDERER_FPS)
|
|
|
|
|
|
|
|
|
|
|
|
renderer = { timer: handle }
|
|
|
|
renderer = { timer: handle }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function update(state: State, width: number, height: number, time: number) {
|
|
|
|
function update(state: State, width: number, _height: number, _time: number) {
|
|
|
|
const w = (width / CELL_SIZE) | 0
|
|
|
|
const w = (width / CELL_SIZE) | 0
|
|
|
|
// const h = (height / CELL_SIZE) | 0
|
|
|
|
// const h = (height / CELL_SIZE) | 0
|
|
|
|
|
|
|
|
|
|
|
@ -166,14 +171,20 @@ const RENDER_CELL: Record<WireCell, (g: CanvasRenderingContext2D) => void> = {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function render(g: CanvasRenderingContext2D, state: State, time: number) {
|
|
|
|
function render(g: CanvasRenderingContext2D, state: State, _time: number) {
|
|
|
|
|
|
|
|
const WIDTH = g.canvas.width / window.devicePixelRatio
|
|
|
|
|
|
|
|
const HEIGHT = g.canvas.height / window.devicePixelRatio
|
|
|
|
|
|
|
|
|
|
|
|
g.clearRect(0, 0, g.canvas.width, g.canvas.height)
|
|
|
|
g.clearRect(0, 0, g.canvas.width, g.canvas.height)
|
|
|
|
|
|
|
|
|
|
|
|
g.resetTransform()
|
|
|
|
g.resetTransform()
|
|
|
|
|
|
|
|
g.scale(window.devicePixelRatio, window.devicePixelRatio)
|
|
|
|
g.scale(CELL_SIZE, CELL_SIZE)
|
|
|
|
g.scale(CELL_SIZE, CELL_SIZE)
|
|
|
|
|
|
|
|
|
|
|
|
g.lineWidth = 3 / CELL_SIZE
|
|
|
|
g.lineWidth = 3 / CELL_SIZE
|
|
|
|
|
|
|
|
|
|
|
|
const w = (g.canvas.width / CELL_SIZE) | 0
|
|
|
|
const w = (WIDTH / CELL_SIZE) | 0
|
|
|
|
const h = (g.canvas.height / CELL_SIZE) | 0
|
|
|
|
const h = (HEIGHT / CELL_SIZE) | 0
|
|
|
|
for (let y = 0; y <= h + 1; y++) {
|
|
|
|
for (let y = 0; y <= h + 1; y++) {
|
|
|
|
for (let x = 0; x <= w + 1; x++) {
|
|
|
|
for (let x = 0; x <= w + 1; x++) {
|
|
|
|
if (!state.grid.has([x, y])) continue
|
|
|
|
if (!state.grid.has([x, y])) continue
|
|
|
@ -235,18 +246,6 @@ function randomChoice<T>(choices: T[]): T {
|
|
|
|
return choices[randomInt(0, choices.length - 1)]
|
|
|
|
return choices[randomInt(0, choices.length - 1)]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function randomWeightedChoice<T>(choices: [T, number][]) {
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3 + 4 + 5 + 6
|
|
|
|
|
|
|
|
randomWeightedChoice([
|
|
|
|
|
|
|
|
['a', 3],
|
|
|
|
|
|
|
|
['b', 4],
|
|
|
|
|
|
|
|
['c', 5],
|
|
|
|
|
|
|
|
['d', 6],
|
|
|
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const DIR_TO_VEC: Record<WireDirection, Point2> = {
|
|
|
|
const DIR_TO_VEC: Record<WireDirection, Point2> = {
|
|
|
|
['down']: [0, 1],
|
|
|
|
['down']: [0, 1],
|
|
|
|
['down-left']: [-1, 1],
|
|
|
|
['down-left']: [-1, 1],
|
|
|
@ -277,14 +276,14 @@ const DIR_AVAILABLE_PREDICATE: Record<WireDirection, (pos: Point2, grid: Grid<Wi
|
|
|
|
function pruneDirections(
|
|
|
|
function pruneDirections(
|
|
|
|
grid: Grid<WireCell>,
|
|
|
|
grid: Grid<WireCell>,
|
|
|
|
position: Point2,
|
|
|
|
position: Point2,
|
|
|
|
directions: WireDirection[],
|
|
|
|
directions: WireDirection[]
|
|
|
|
): WireDirection[] {
|
|
|
|
): WireDirection[] {
|
|
|
|
return directions.filter(dir => DIR_AVAILABLE_PREDICATE[dir](position, grid))
|
|
|
|
return directions.filter(dir => DIR_AVAILABLE_PREDICATE[dir](position, grid))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function generateWire(
|
|
|
|
function generateWire(
|
|
|
|
grid: Grid<WireCell>,
|
|
|
|
grid: Grid<WireCell>,
|
|
|
|
startingPoint: Point2,
|
|
|
|
startingPoint: Point2
|
|
|
|
): { position: Point2; direction: WireCell }[] {
|
|
|
|
): { position: Point2; direction: WireCell }[] {
|
|
|
|
const segmentLength = Math.floor(1 - Math.random() ** 2) * 10 + 30
|
|
|
|
const segmentLength = Math.floor(1 - Math.random() ** 2) * 10 + 30
|
|
|
|
let currentPosition = startingPoint
|
|
|
|
let currentPosition = startingPoint
|
|
|
|