class Grid{ constructor(settings, cellCount, difficulty, randomDirection){ this.margin = settings.margin; this.cellCount = createVector(cellCount, cellCount); this.nodes = []; for (let x = 0; x < this.cellCount.x; x++){ let column = []; for (let y = 0; y < this.cellCount.y; y++){ let forbidden = ranBool(7 - difficulty); if (!randomDirection){ let allowed = [ {x: 0, y: 0}, {x: 1, y: 0}, {x: 1, y: 1}, {x: 0, y: 1}, {x: this.cellCount.x - 1, y: this.cellCount.y - 1}, {x: this.cellCount.x - 1, y: this.cellCount.y - 2}, {x: this.cellCount.x - 2, y: this.cellCount.y - 2}, {x: this.cellCount.x - 2, y: this.cellCount.y - 1}, ]; allowed.forEach(a => { if (x === a.x && y === a.y){ forbidden = false; } }); } column.push(new PathNode(x, y, forbidden)); } this.nodes.push(column); } this.nodes.forEach(x => x.forEach(n => n.connectToSuccessors(this.nodes))); let nodes = []; this.nodes.forEach(x => nodes.push(...x.filter(n => n.isForbidden))); this.forbiddenNodes = nodes; nodes = []; this.nodes.forEach(x => nodes.push(...x.filter(n => !n.isForbidden))); this.allowedNodes = nodes; } get size(){ return Math.min(width - this.margin * 2, height - this.margin * 2); } get nodeSize(){ return { x: this.size / this.cellCount.x, y: this.size / this.cellCount.y }; } display(appearance, linesAreVisible){ translate(this.margin, this.margin); if (linesAreVisible){ let size = this.size; stroke(100); strokeWeight(1); for (let x = 0; x <= size + 1; x += size / this.cellCount.x){ line(x, 0, x, size); } for (let y = 0; y <= size + 1; y += size / this.cellCount.y){ line(0, y, size, y); } } translate(this.nodeSize.x / 2, this.nodeSize.y / 2); scale(this.nodeSize.x, this.nodeSize.y); noStroke(); fill(200, 50, 50); for (let n of this.forbiddenNodes){ let x = n.pos.x; let y = n.pos.y; if (appearance === 'Circles'){ let r = 0.5; ellipse(x, y, r * 2); } if (appearance === 'Rectangles'){ rect(x - 0.5, y - 0.5, 1, 1); } } } getAllowedNodesDistantTo(otherNode){ return this.allowedNodes.filter(n => n.pos.dist(otherNode.pos) > Math.max(this.cellCount.x, this.cellCount.y) / 2); } } class PathNode{ constructor(x, y, isForbidden){ this.pos = createVector(x, y); this.isForbidden = isForbidden; } get distanceToTarget(){ return this.pos.dist(game.targetNode.pos); } setMovement(movement){ this.isDiagonalAllowed = false; this.isStraightAllowed = false; switch (movement){ case "0": this.isStraightAllowed = true; break; case "1": this.isDiagonalAllowed = true; break; case "2": this.isStraightAllowed = true; this.isDiagonalAllowed = true; break; } } connectToSuccessors(nodes){ let allowed = [], successors = []; if (this.isStraightAllowed){ allowed.push( {x: 1, y: 0}, {x: 0, y: 1}, {x: -1, y: 0}, {x: 0, y: -1} ); } if (this.isDiagonalAllowed){ allowed.push( {x: 1, y: 1}, {x: 1, y: -1}, {x: -1, y: 1}, {x: -1, y: -1} ); } allowed.forEach(a => { let column = nodes[this.pos.x + a.x]; if (column){ let node = column[this.pos.y + a.y]; if (node){ if (!node.isForbidden){ successors.push(node); } } } }); this.successors = successors; } }