SectorFlow

Developer
Size
8,266 Kb
Views
44,528

How do I make an sectorflow?

Pathfinding for large areas, using flow fields and breaking the map into smaller sectors. What is a sectorflow? How do you make a sectorflow? This script and codes were developed by Not Important on 13 July 2022, Wednesday.

SectorFlow Previews

SectorFlow - Script Codes HTML Codes

<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>sectorFlow</title> <link rel="stylesheet" href="css/style.css">
</head>
<body> <canvas id="canvas" width="400" height="400"></canvas>
<ul> <li>move the mouse around the field to generate flow fields leading to that point</li> <li>the system is optimized by breaking the map into many smaller sectors to generate the flow fields then stitching them together</li>
</ul> <script src='https://code.createjs.com/easeljs-0.8.0.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/chance/0.5.6/chance.js'></script>
<script src='http://code.jquery.com/jquery-2.1.3.js'></script> <script src="js/index.js"></script>
</body>
</html>

SectorFlow - Script Codes CSS Codes

canvas { background-color: #dedede;
}

SectorFlow - Script Codes JS Codes

(function() { var FlowField, FlowNode, GridView, SectorTile, SectorView, WorldData, createGrid, mapData, options, rng, stageEl, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; rng = new Chance(19870910); options = { width: 5, height: 5, sector: { width: 4, height: 4 }, tile: { width: 20, height: 20 } }; options.grid = { width: options.sector.width * options.tile.width, height: options.sector.height * options.tile.height }; FlowField = (function() { FlowField.prototype.neighborDirections = [[0, -1], [1, 0], [0, 1], [-1, 0]]; function FlowField(x1, y1, gridData) { this.x = x1; this.y = y1; this.gridData = gridData; this.callback = bind(this.callback, this); } FlowField.prototype.callback = function(node) { if (!node.data.open) { return; } node.visited = true; node.iteration = 1; return this.openNodes.push(node); }; FlowField.prototype.directionFlow = function(vX, vY, costCallback, flowCallback) { var height, i, j, k, l, lX, lY, node, offsetX, offsetY, ref, ref1, ref2, ref3, ref4, results, vector, width, x, y; this.reset(); this.openNodes = []; ref = options.sector, width = ref.width, height = ref.height; lX = vX === -1 ? 0 : width - 1; lY = vY === -1 ? 0 : height - 1; offsetX = options.sector.width * this.x; offsetY = options.sector.height * this.y; if (vX === -1 || vX === 1) { for (y = i = 0, ref1 = height; 0 <= ref1 ? i < ref1 : i > ref1; y = 0 <= ref1 ? ++i : --i) { node = this.gridData.getNode(lX + offsetX, y + offsetY); this.callback(node); } } if (vY === -1 || vY === 1) { for (x = j = 0, ref2 = width; 0 <= ref2 ? j < ref2 : j > ref2; x = 0 <= ref2 ? ++j : --j) { node = this.gridData.getNode(x + offsetX, lY + offsetY); this.callback(node); } } this.costMap(1, costCallback); this.flowMap(flowCallback); if (vX === -1 || vX === 1) { for (y = k = 0, ref3 = height; 0 <= ref3 ? k < ref3 : k > ref3; y = 0 <= ref3 ? ++k : --k) { node = this.gridData.getNode(lX + offsetX, y + offsetY); if (!node.data.open) { continue; } vector = this.neighborVector(node, vX, 0); flowCallback(lX, y, vector); } } if (vY === -1 || vY === 1) { results = []; for (x = l = 0, ref4 = width; 0 <= ref4 ? l < ref4 : l > ref4; x = 0 <= ref4 ? ++l : --l) { node = this.gridData.getNode(x + offsetX, lY + offsetY); if (!node.data.open) { continue; } vector = this.neighborVector(node, 0, vY); results.push(flowCallback(x, lY, vector)); } return results; } }; FlowField.prototype.neighborVector = function(node, vX, vY) { var height, i, len, n, neighborNode, neighborNodes, offsetX, offsetY, ref, vector, width; neighborNode = this.gridData.getNode(node.x + vX, node.y + vY); if (neighborNode.data.open) { vector = { x: vX, y: vY }; } else { offsetX = options.sector.width * this.x; offsetY = options.sector.height * this.y; ref = options.sector, width = ref.width, height = ref.height; neighborNodes = this.collectNeighbors(node, function(n) { var rX, rY; rX = n.x - offsetX; rY = n.y - offsetY; if (!(rX < width && rY < height)) { return false; } if (!(rX >= 0 && rY >= 0)) { return false; } return n.iteration >= 0; }); for (i = 0, len = neighborNodes.length; i < len; i++) { n = neighborNodes[i]; if (n.data.open) { vector = { x: n.x - node.x, y: n.y - node.y }; break; } } } return vector; }; FlowField.prototype.process = function(x, y, costCallback, flowCallback) { var offsetX, offsetY; this.reset(); offsetX = options.sector.width * this.x; offsetY = options.sector.height * this.y; this.openNodes = [this.gridData.getNode(x + offsetX, y + offsetY)]; this.costMap(0, costCallback); return this.flowMap(flowCallback); }; FlowField.prototype.flowMap = function(flowCallback) { var height, i, lowestNode, neighbors, node, offsetX, offsetY, ref, ref1, results, vector, width, x, y; ref = options.sector, width = ref.width, height = ref.height; offsetX = options.sector.width * this.x; offsetY = options.sector.height * this.y; results = []; for (y = i = 0, ref1 = height; 0 <= ref1 ? i < ref1 : i > ref1; y = 0 <= ref1 ? ++i : --i) { results.push((function() { var j, ref2, results1; results1 = []; for (x = j = 0, ref2 = width; 0 <= ref2 ? j < ref2 : j > ref2; x = 0 <= ref2 ? ++j : --j) { node = this.gridData.getNode(x + offsetX, y + offsetY); if (!node.data.open) { continue; } if (!node.visited) { continue; } neighbors = this.collectNeighbors(node, function(n) { var rX, rY; rX = n.x - offsetX; rY = n.y - offsetY; if (!(rX < width && rY < height)) { return false; } if (!(rX >= 0 && rY >= 0)) { return false; } return n.iteration >= 0; }); lowestNode = neighbors.pop(); neighbors.map(function(n) { if (!n.data.open) { return; } if (n.iteration == null) { return; } if (lowestNode.iteration > n.iteration) { return lowestNode = n; } }); if (!lowestNode) { continue; } vector = { x: lowestNode.x - node.x, y: lowestNode.y - node.y }; if (node.iteration === 0) { vector = { x: 0, y: 0 }; } results1.push(flowCallback(x, y, vector)); } return results1; }).call(this)); } return results; }; FlowField.prototype.reset = function() { var height, i, node, offsetX, offsetY, ref, ref1, results, width, x, y; offsetX = options.sector.width * this.x; offsetY = options.sector.height * this.y; ref = options.sector, width = ref.width, height = ref.height; results = []; for (y = i = 0, ref1 = height; 0 <= ref1 ? i < ref1 : i > ref1; y = 0 <= ref1 ? ++i : --i) { results.push((function() { var j, ref2, results1; results1 = []; for (x = j = 0, ref2 = width; 0 <= ref2 ? j < ref2 : j > ref2; x = 0 <= ref2 ? ++j : --j) { node = this.gridData.getNode(x + offsetX, y + offsetY); results1.push(node.visited = false); } return results1; }).call(this)); } return results; }; FlowField.prototype.floodCallback = function(node) { if (!node.data.open) { return false; } if (node.visited) { return false; } node.visited = true; return true; }; FlowField.prototype.costMap = function(iteration, costCallback) { var newNodes, node, nodes, x, y; newNodes = []; while (node = this.openNodes.pop()) { node.visited = true; node.iteration = iteration; x = node.x, y = node.y; costCallback(x, y); nodes = this.collectNeighbors(node, this.floodCallback); newNodes = newNodes.concat(nodes); } this.openNodes = this.openNodes.concat(newNodes); if (this.openNodes.length) { return this.costMap(iteration + 1, costCallback); } }; FlowField.prototype.collectNeighbors = function(arg, checkCallback) { var dX, dY, height, i, len, node, nodes, ref, ref1, ref2, tX, tY, width, x, y; x = arg.x, y = arg.y; ref = options.sector, width = ref.width, height = ref.height; nodes = []; ref1 = this.neighborDirections; for (i = 0, len = ref1.length; i < len; i++) { ref2 = ref1[i], dX = ref2[0], dY = ref2[1]; tX = x + dX; tY = y + dY; node = this.gridData.getNode(tX, tY); if (!node) { continue; } if (!checkCallback(node)) { continue; } nodes.push(node); } return nodes; }; return FlowField; })(); FlowNode = (function() { function FlowNode(x1, y1, iteration1, data1) { this.x = x1; this.y = y1; this.iteration = iteration1; this.data = data1 != null ? data1 : {}; } return FlowNode; })(); WorldData = (function() { function WorldData(mapData) { this.buildData(mapData); } WorldData.prototype.buildData = function(mapData) { var i, node, ref, results, x, y; this.width = mapData[0].length; this.height = mapData.length; this.nodes = []; results = []; for (y = i = 0, ref = this.height; 0 <= ref ? i < ref : i > ref; y = 0 <= ref ? ++i : --i) { this.nodes.push([]); results.push((function() { var j, ref1, results1; results1 = []; for (x = j = 0, ref1 = this.width; 0 <= ref1 ? j < ref1 : j > ref1; x = 0 <= ref1 ? ++j : --j) { node = new FlowNode(x, y, -2e308, { open: !!mapData[y][x] }); results1.push(this.nodes[y][x] = node); } return results1; }).call(this)); } return results; }; WorldData.prototype.getNode = function(x, y) { var node; if (!((this.nodes[y] != null) && (this.nodes[y][x] != null))) { return node = new FlowNode(x, y, -2e308, { open: false }); } return this.nodes[y][x]; }; return WorldData; })(); SectorTile = (function() { SectorTile.prototype.directionLookup = { '1_0': 0, '2_1': 90, '1_2': 180, '0_1': 270, '2_0': 45, '2_2': 135, '0_2': 225, '0_0': 315, '1_1': 0 }; function SectorTile(x, y, node1) { this.node = node1; this.el = new createjs.Container; this.el.x = x; this.el.y = y; this.render(); } SectorTile.prototype.render = function() { this.drawBackground(); return this.drawArrow(); }; SectorTile.prototype.drawBackground = function() { var backgroundEl, g; if (this.node.data.open) { return; } g = new createjs.Graphics; backgroundEl = new createjs.Shape(g); g.f('#880000').dr(0, 0, options.tile.width, options.tile.height); return this.el.addChild(backgroundEl); }; SectorTile.prototype.drawArrow = function() { var g, height, width, x, y; g = new createjs.Graphics; this.arrowEl = new createjs.Shape(g); width = options.tile.width * 0.25; height = options.tile.height * 0.75; x = (options.tile.width - width) / 2; y = (options.tile.height - height) / 2; g.lf(['#333333', '#dedede'], [0, 1], 0, 0, 0, height).dr(x, y, width, height); this.arrowEl.regX = options.tile.width / 2; this.arrowEl.regY = options.tile.height / 2; this.arrowEl.x = options.tile.width / 2; this.arrowEl.y = options.tile.height / 2; return this.el.addChild(this.arrowEl); }; SectorTile.prototype.setVector = function(arg) { var x, y; x = arg.x, y = arg.y; if (!this.node.data.open) { return; } if (x === 0 && y === 0) { return; } this.arrowEl.visible = true; return this.arrowEl.rotation = this.directionLookup[(x + 1) + "_" + (y + 1)]; }; SectorTile.prototype.clearVector = function() { return this.arrowEl.visible = false; }; return SectorTile; })(); SectorView = (function() { function SectorView(worldData, x1, y1) { this.worldData = worldData; this.x = x1; this.y = y1; this.markFlow = bind(this.markFlow, this); this.el = new createjs.Container; this.render(); this.flowField = new FlowField(this.x, this.y, this.worldData); } SectorView.prototype.reset = function() { var i, len, ref, results, row, sectorTile, x, y; ref = this.sectorTiles; results = []; for (y = i = 0, len = ref.length; i < len; y = ++i) { row = ref[y]; results.push((function() { var j, len1, results1; results1 = []; for (x = j = 0, len1 = row.length; j < len1; x = ++j) { sectorTile = row[x]; results1.push(sectorTile.clearVector()); } return results1; })()); } return results; }; SectorView.prototype.markCost = function() {}; SectorView.prototype.markFlow = function(x, y, vector) { return this.sectorTiles[y][x].setVector(vector); }; SectorView.prototype.render = function() { this.drawTiles(); return this.el.cache(0, 0, options.grid.width, options.grid.height); }; SectorView.prototype.drawTiles = function() { var height, i, node, pX, pY, ref, ref1, results, sectorTile, wX, wY, width, x, y; this.sectorTiles = []; ref = options.sector, width = ref.width, height = ref.height; results = []; for (y = i = 0, ref1 = height; 0 <= ref1 ? i < ref1 : i > ref1; y = 0 <= ref1 ? ++i : --i) { this.sectorTiles[y] = []; results.push((function() { var j, ref2, results1; results1 = []; for (x = j = 0, ref2 = width; 0 <= ref2 ? j < ref2 : j > ref2; x = 0 <= ref2 ? ++j : --j) { pX = x * options.tile.width; pY = y * options.tile.height; wX = this.x * options.sector.width + x; wY = this.y * options.sector.height + y; node = this.worldData.getNode(wX, wY); sectorTile = new SectorTile(pX, pY, node); this.el.addChild(sectorTile.el); results1.push(this.sectorTiles[y][x] = sectorTile); } return results1; }).call(this)); } return results; }; SectorView.prototype.process = function(x, y) { this.vX = this.vY = void 0; if (!this.sectorTiles[y][x].node.data.open) { return; } this.flowField.process(x, y, this.markCost, this.markFlow); return this.el.updateCache(); }; SectorView.prototype.directionFlow = function(vX, vY) { if (vX === this.vX && vY === this.vY) { return; } this.vX = vX; this.vY = vY; this.flowField.directionFlow(vX, vY, this.markCost, this.markFlow); return this.el.updateCache(); }; return SectorView; })(); GridView = (function() { function GridView(width1, height1) { this.width = width1; this.height = height1; this.onMouseMove = bind(this.onMouseMove, this); this.el = new createjs.Container; this.createWorldData(); this.addSectors(); this.addEventListeners(); } GridView.prototype.createWorldData = function() { var height, width; width = options.width * options.sector.width; height = options.height * options.sector.height; return this.worldData = new WorldData(mapData(width, height)); }; GridView.prototype.addSectors = function() { var i, pX, pY, ref, results, sectorView, x, y; this.sectors = []; results = []; for (y = i = 0, ref = options.height; 0 <= ref ? i < ref : i > ref; y = 0 <= ref ? ++i : --i) { this.sectors[y] = []; results.push((function() { var j, ref1, results1; results1 = []; for (x = j = 0, ref1 = options.width; 0 <= ref1 ? j < ref1 : j > ref1; x = 0 <= ref1 ? ++j : --j) { pX = x * options.grid.width; pY = y * options.grid.height; sectorView = this.addSector(pX, pY, x, y); this.el.addChild(sectorView.el); results1.push(this.sectors[y][x] = sectorView); } return results1; }).call(this)); } return results; }; GridView.prototype.addSector = function(x, y, sectorX, sectorY) { var sectorView; sectorView = new SectorView(this.worldData, sectorX, sectorY); sectorView.el.x = x; sectorView.el.y = y; return sectorView; }; GridView.prototype.addEventListeners = function() { var height, width; width = options.width, height = options.height; this.cX = this.cY = void 0; return $('canvas').mousemove(this.onMouseMove); }; GridView.prototype.onMouseMove = function(arg) { var i, mX, mY, offsetX, offsetY, ref, results, sX, sY, sector, sectorX, sectorY, vX, vY, x, y; offsetX = arg.offsetX, offsetY = arg.offsetY; sectorX = ~~(offsetX / options.grid.width); sectorY = ~~(offsetY / options.grid.height); mX = offsetX % options.grid.width; mY = offsetY % options.grid.height; x = ~~(mX / options.tile.width); y = ~~(mY / options.tile.height); if (this.cX !== x || this.cY !== y) { this.cX = x; this.cY = y; results = []; for (sY = i = 0, ref = options.height; 0 <= ref ? i < ref : i > ref; sY = 0 <= ref ? ++i : --i) { results.push((function() { var j, ref1, results1; results1 = []; for (sX = j = 0, ref1 = options.width; 0 <= ref1 ? j < ref1 : j > ref1; sX = 0 <= ref1 ? ++j : --j) { sector = this.sectors[sY][sX]; sector.reset(); if (sX === sectorX && sY === sectorY) { results1.push(sector.process(x, y)); } else { vX = 0; vY = 0; if (sectorX > sX) { vX = 1; } if (sectorX < sX) { vX = -1; } if (sectorY > sY) { vY = 1; } if (sectorY < sY) { vY = -1; } results1.push(sector.directionFlow(vX, vY)); } } return results1; }).call(this)); } return results; } }; return GridView; })(); mapData = function(width, height) { var data, i, j, ref, ref1, x, y; data = []; for (y = i = 0, ref = height; 0 <= ref ? i < ref : i > ref; y = 0 <= ref ? ++i : --i) { data[y] = []; for (x = j = 0, ref1 = width; 0 <= ref1 ? j < ref1 : j > ref1; x = 0 <= ref1 ? ++j : --j) { data[y][x] = rng.bool({ likelihood: 92 }); } } return data; }; createGrid = function() { var gridView; gridView = new GridView(options.width, options.height); stageEl.addChild(gridView.el); return gridView.onMouseMove({ offsetX: 0, offsetY: 0 }); }; stageEl = new createjs.Stage('canvas'); createjs.Ticker.setFPS(60); createjs.Ticker.addEventListener('tick', function() { return stageEl.update(); }); createGrid();
}).call(this);
SectorFlow - Script Codes
SectorFlow - Script Codes
Home Page Home
Developer Not Important
Username clindsey
Uploaded July 13, 2022
Rating 3
Size 8,266 Kb
Views 44,528
Do you need developer help for SectorFlow?

Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!

Not Important (clindsey) Script Codes
Create amazing marketing copy with AI!

Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!