Last active
January 12, 2019 02:25
-
-
Save Rio6/8135d6b4145e6402e29bffbebc4f3b03 to your computer and use it in GitHub Desktop.
Improved linemove for Istrolid
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var linemove = {}; | |
linemove.center = function(points) { | |
var rst = v2.create(); | |
for(var point of points) { | |
v2.add(rst, point); | |
} | |
return v2.scale(rst, 1 / points.length); | |
} | |
// Function from https://stackoverflow.com/a/28866825/6023997 | |
linemove.isIntersecting = function(p1, p2, p3, p4) { | |
function ccw(p1, p2, p3) { | |
return (p3[1] - p1[1]) * (p2[0] - p1[0]) > (p2[1] - p1[1]) * (p3[0] - p1[0]); | |
} | |
return (ccw(p1, p3, p4) != ccw(p2, p3, p4)) && (ccw(p1, p2, p3) != ccw(p1, p2, p4)); | |
} | |
linemove.findIntersect = function (unit, target, paths) { | |
for([unit2, target2] of paths) { | |
if(unit.id != unit2.id && | |
linemove.isIntersecting(unit.pos, target, unit2.pos, target2)) { | |
return {unit: unit2, target: target2}; | |
} | |
} | |
return null; | |
} | |
linemove.resolvePaths = function(units, targets) { | |
var paths = new Map(); | |
var targets = targets.slice(); | |
var units = units.slice(); | |
var uPos = units.map(unit => unit.pos); | |
var d = v2.rotate(v2.sub( | |
linemove.center(uPos), | |
linemove.center(targets)), | |
Math.PI / 2); | |
targets.sort(function(a, b) { | |
return v2.dot(a, d) - v2.dot(b, d); | |
}); | |
units.sort(function(a, b) { | |
a = a.pos; b = b.pos; | |
return v2.dot(a, d) - v2.dot(b, d); | |
}); | |
units.forEach(function(unit, i) { | |
paths.set(unit, targets[i]); | |
}); | |
for([unit, target] of paths) { | |
var d = 500; | |
while(d-->0) { | |
var intersect = linemove.findIntersect(unit, target, paths); | |
if(intersect) { | |
// console.log("swapping", unit.id, intersect.unit.id); | |
paths.set(unit, intersect.target); | |
paths.set(intersect.unit, target); | |
target = intersect.target; | |
} else { | |
// console.log("solved", unit.id, target); | |
break; | |
} | |
if(d <= 0) | |
console.error("Can't find solution"); | |
} | |
} | |
return paths; | |
} | |
// Function from istrolid.js | |
// I changed the last part of this function to reorder movePoints | |
BattleMode.prototype.computeLineMove = function() { | |
var points, selected, totalDistance, u, walkRope; | |
selected = commander.selection; | |
if (!selected) { | |
return; | |
} | |
selected = (function() { | |
var j, len, results; | |
results = []; | |
for (j = 0, len = selected.length; j < len; j++) { | |
u = selected[j]; | |
if (u.owner === commander.number) { | |
results.push(u); | |
} | |
} | |
return results; | |
})(); | |
if (selected.length === 0) { | |
return; | |
} | |
totalDistance = function(points) { | |
var distance, j, last, len, point, ref; | |
distance = 0; | |
last = points[0]; | |
ref = points.slice(1); | |
for (j = 0, len = ref.length; j < len; j++) { | |
point = ref[j]; | |
distance += v2.distance(last, point); | |
last = point; | |
} | |
return distance; | |
}; | |
walkRope = function(points, units, cb) { | |
var dir, dist, i, j, last, len, n, point, pos, prev, results, step, stepLeft, total, use; | |
total = totalDistance(points); | |
if (total === 0 || points.length === 1 || units.length === 1) { | |
for (j = 0, len = units.length; j < len; j++) { | |
u = units[j]; | |
cb(points[0], u); | |
} | |
return; | |
} | |
step = total / (units.length - 1); | |
dir = v2.create(); | |
pos = v2.create(); | |
n = 0; | |
i = 0; | |
stepLeft = 0; | |
last = null; | |
results = []; | |
while (i < units.length) { | |
use = function(p) { | |
cb(v2.create(p), units[i]); | |
stepLeft = step; | |
return i += 1; | |
}; | |
point = points[n]; | |
if (i === 0) { | |
use(point); | |
n += 1; | |
continue; | |
} | |
if (i === units.length - 1) { | |
use(points[points.length - 1]); | |
continue; | |
} | |
if (n > points.length - 1) { | |
use(points[points.length - 1]); | |
continue; | |
} | |
prev = points[n - 1]; | |
dist = v2.distance(prev, point); | |
if (dist === stepLeft) { | |
use(point); | |
n += 1; | |
continue; | |
} else if (dist < stepLeft) { | |
stepLeft -= dist; | |
n += 1; | |
continue; | |
} else if (dist > stepLeft) { | |
v2.set(prev, pos); | |
dist = v2.distance(prev, point); | |
while (dist > stepLeft) { | |
v2.direction(point, prev, dir); | |
v2.scale(dir, stepLeft); | |
v2.add(pos, dir); | |
dist -= stepLeft; | |
use(pos); | |
} | |
n += 1; | |
results.push(stepLeft -= dist); | |
} else { | |
results.push(void 0); | |
} | |
} | |
return results; | |
}; | |
this.movePoints = []; | |
points = this.drawPoints; | |
var units = [], targets = []; | |
walkRope(points, selected, | |
function(point, unit) { | |
units.push(unit); | |
targets.push(point); | |
}); | |
// Sort them with unit id so BattleMode.prototype.moveOrder gives order correctly | |
var paths = new Map([...linemove.resolvePaths(units, targets).entries()].sort((a, b) => a[0].id - b[0].id)); | |
paths.forEach(function(point, unit) { | |
var angle, pos; | |
this.movePoints.push(point); | |
if (this.shiftOrder && unit.preOrders.length > 0) { | |
pos = unit.preOrders.last().dest; | |
} | |
if (!pos) { | |
pos = unit.pos; | |
} | |
angle = v2.angle(v2.sub(point, pos, v2.create())); | |
baseAtlas.drawSprite("img/arrow01.png", point, [1, 1], angle, [255, 255, 255, 255]); | |
//drawLine(unit.pos, point); // Draw debug line | |
}, this); | |
} | |
/* | |
// Debug lines | |
function drawLine(from, to) { | |
var offset = v2.create, rot, d; | |
v2.sub(to, from, offset); | |
rot = v2.angle(offset); | |
d = v2.mag(offset) / 437; | |
v2.scale(offset, .5); | |
v2.add(offset, from); | |
baseAtlas.drawSprite("img/laser01.png", offset, [1, d], rot, [0, 255, 0, 255]); | |
} | |
var drawSelection = types.Unit.prototype.drawSelection; | |
types.Unit.prototype.drawSelection = function() { | |
var results = drawSelection.call(this); | |
var len, order, orders; | |
orders = this.preOrders; | |
for (i = j = 0, len = orders.length; j < len; i = ++j) { | |
order = orders[i]; | |
if (order.type === "Move") { | |
if (order.dest == null) { | |
continue; | |
} | |
drawLine(this.pos, order.dest); | |
} | |
} | |
return results; | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment