class Path { constructor() { this.onComplete = new Action(); this.complete = true; this.pathNodes = [];//new List<Vector2>(); this.currentIndex = 0; this.distanceAlongCurrentNodePair = 0; } movePath(offset /*Vector2*/) { for (var i = 0; i < this.pathNodes.length; i++) { this.pathNodes[i].x += offset.x; this.pathNodes[i].y += offset.y; } } addNode(node /*Vector2*/) { this.pathNodes.push(node); this.complete = false; } clear() { if (this.hasPath && !this.complete) { this.callOnComplete(); } this.pathNodes.length = 0; this.distanceAlongCurrentNodePair = 0; this.currentIndex = 0; this.complete = true; } resetPosition() { this.distanceAlongCurrentNodePair = 0; this.currentIndex = 0; this.complete = false; } get percentAlongtPath() { var totalDistance = 0; var traveledDistance = 0; var segment = new Vector2(); for (var i = 0; i < this.pathNodes.length - 1; i++) { segment.subVectors(this.pathNodes[i + 1], this.pathNodes[i]); totalDistance += segment.length(); if (this.currentIndex < i) { traveledDistance += segment.magnitude; } else if(this.currentIndex == i) { traveledDistance += this.distanceAlongCurrentNodePair; } } return traveledDistance / totalDistance; } getTotalDistance() { let segment = new Vector2(); let totalDistance = 0; for (var i = 0; i < this.pathNodes.length - 1; i++) { segment.subVectors(this.pathNodes[i + 1], this.pathNodes[i]); totalDistance += segment.length(); } return totalDistance; } set percentAlongPath(value) { var totalDistance = 0; var segment = new Vector2(); for (var i = 0; i < this.pathNodes.length - 1; i++) { segment.subVectors(this.pathNodes[i + 1], this.pathNodes[i]); totalDistance += segment.length(); } this.move(totalDistance * value); } move(distance /*float*/) { var nextPoint = new Vector2(); var segment = new Vector2(); if (this.pathNodes.length == 1) nextPoint = this.pathNodes[0]; if (this.pathNodes.length > 1 && this.currentIndex < this.pathNodes.length - 1) { var startPoint = this.pathNodes[this.currentIndex]; var endPoint = this.pathNodes[this.currentIndex + 1]; segment.subVectors(endPoint, startPoint); nextPoint.addVectors(startPoint, segment.normalize().multiplyScalar(this.distanceAlongCurrentNodePair)); } while (distance > 0) { //if we are out of pathnodes then return the last node, or 0 if the path has no nodes for some crazy reason. if (this.currentIndex >= this.pathNodes.length - 1) { this.complete = true; this.callOnComplete(); return this.pathNodes.length > 0 ? this.pathNodes[this.currentIndex] : new Vector2(0, 0); } var startPoint = this.pathNodes[this.currentIndex]; var endPoint = this.pathNodes[this.currentIndex + 1]; segment.subVectors(endPoint, startPoint); var availableLength = segment.length() - this.distanceAlongCurrentNodePair; if (availableLength > distance) { //nextPoint = startPoint + segment * ((this.distanceAlongCurrentNodePair + distance) / segment.length()); nextPoint.addVectors(startPoint, segment.multiplyScalar( (this.distanceAlongCurrentNodePair + distance) / segment.length()) ); this.distanceAlongCurrentNodePair += distance; distance = 0; } else { distance -= availableLength; this.distanceAlongCurrentNodePair = 0; this.currentIndex++; } } return nextPoint; } callOnComplete() { this.onComplete.clearAndCall(); } get hasPath() { return this.pathNodes.length > 0; } getPositionIn(distance /*float*/) { var nextPoint = new Vector2(); var localIndex = this.currentIndex; var localDistanceCurrent = this.distanceAlongCurrentNodePair; var segment = new Vector2(); while (distance > 0) { //if we are out of pathnodes then return the last node, or 0 if the path has no nodes for some crazy reason. if (localIndex >= this.pathNodes.length - 1) { return this.pathNodes.length > 0 ? this.pathNodes[localIndex] : new Vector2(0, 0); } var startPoint = this.pathNodes[localIndex]; var endPoint = this.pathNodes[localIndex + 1]; segment.subVectors(endPoint, startPoint); var availableLength = segment.length() - localDistanceCurrent; if (availableLength > distance) { //startPoint + segment * ((localDistanceCurrent + distance) / segment.length()); nextPoint.addVectors(startPoint, segment.multiplyScalar((localDistanceCurrent + distance) / segment.length())); localDistanceCurrent += distance; distance = 0; } else { distance -= availableLength; localDistanceCurrent = 0; localIndex++; } } return nextPoint; } }