SectorFlow
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 - 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);
Developer | Not Important |
Username | clindsey |
Uploaded | July 13, 2022 |
Rating | 3 |
Size | 8,266 Kb |
Views | 44,528 |
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!
Name | Size |
FluxTabulate | 10,632 Kb |
Spectrum-shift | 4,680 Kb |
WorldGenerator | 4,767 Kb |
ThreeWorld | 9,606 Kb |
FlowField | 5,931 Kb |
Immutable.js | 2,057 Kb |
WorldColors | 6,256 Kb |
Flame-view-1.0.0 | 5,892 Kb |
SquiggleParty | 3,990 Kb |
Wave-pendulum | 3,399 Kb |
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!
Name | Username | Size |
Canvas snow | Win7killer | 2,572 Kb |
C.Rowe Button | Brownerd | 2,473 Kb |
A Pen by Manoz | Manoz | 2,424 Kb |
Compare resources on mobile sites | Gyusza | 3,226 Kb |
Single element checkbox | Ivijaygupta | 1,996 Kb |
Project MMetro beta | Atomicsong | 5,157 Kb |
Weather App | Kw7oe | 3,162 Kb |
Parallax-ish Sliding Content | Jdsteinbach | 2,748 Kb |
Loading animation - freedom purchase | Rocbear | 2,567 Kb |
React JS Movie Info App | MTushar | 4,870 Kb |
Surf anonymously, prevent hackers from acquiring your IP address, send anonymous email, and encrypt your Internet connection. High speed, ultra secure, and easy to use. Instant setup. Hide Your IP Now!