Phaser.PathFollower = function (path, follower, speed, rotationOffset, angularOffset, callbackAtEnd, physicsAdjustTime){ if (speed === undefined) { speed = 1; } if (rotationOffset === undefined) { rotationOffset = 0; } if (angularOffset === undefined) { angularOffset = { angle: 0, distance: 0} ; } if (physicsAdjustTime === undefined) { physicsAdjustTime = 0; } Phaser.EventTarget.call(this); this.path = path; this.follower = follower; this._turnOffset = rotationOffset; this.callbackAtEnd = callbackAtEnd; this.physicsAdjustTime = physicsAdjustTime; this.offset = new Phaser.Point(0, 0); if (typeof speed === 'object') { this.speed = Phaser.Utils.extend(true , Object.create(Phaser.PathFollower.Defaults.speed), speed); } else { this.speed = Object.create(Phaser.PathFollower.Defaults.speed); this.speed.min = speed; this.speed.max = speed; } this._angularOffset = { angle: 0, distance: 0} ; this.setAngularOffset(angularOffset.angle, angularOffset.distance); this.branchCount = 0; this.branchPredicate = null ; this._currentDistance = 0; this._currentPoint = 0; this._currentCurve = this.path.getCurve(this._currentPoint); var pp = new Phaser.PathPoint(); if (this.path.getPathPoint(0, pp)) { this._pathSpeed = pp.speed; } if (this.physicsAdjustTime !== 0) { this.virtualParticle = new Phaser.Point(pp.x, pp.y); } else { this.virtualParticle = null ; } this.maximumGap = 1000; this.path.processData(this, this._currentPoint, false ); this._pauseTime = 0; this._accelerationTime = 0; this.yoyo = false ; if (!follower.events) { follower.events = { } ; } follower.events.onPathPointReached = new Phaser.Signal(); follower.events.onPathBranchReached = new Phaser.Signal(); follower.events.onCountFinished = new Phaser.Signal(); follower.events.onPathStart = new Phaser.Signal(); follower.events.onPathYoyo = new Phaser.Signal(); follower.events.onPathEnd = new Phaser.Signal(); follower.events.onPathLoop = new Phaser.Signal(); follower.followerPathName = this.path.name; Object.defineProperty(this.speed, 'avg', { get: function (){ return (this.min + this.max) / 2; } } ); } ; Phaser.PathFollower.EVENT_REACHED_POINT = "event_reached_point"; Phaser.PathFollower.EVENT_BRANCH_CHOICE = "event_branch_choice"; Phaser.PathFollower.EVENT_COUNT_FINISH = "event_count_finish"; Phaser.PathFollower.EVENT_PATH_START = "event_path_start"; Phaser.PathFollower.EVENT_PATH_END = "event_path_end"; Phaser.PathFollower.EVENT_PATH_LOOPED = "event_path_looped"; Phaser.PathFollower.tempPoint = new Phaser.Point(); Phaser.PathFollower.Defaults = { speed: { min: 1, max: 1, theta: null , lambda: null , _target: null , _elapsed: 0, _current: null , _previous: null } } ; Phaser.PathFollower.prototype.destroy = function (){ this.follower.events.onPathPointReached.removeAll(); this.follower.events.onPathBranchReached.removeAll(); this.follower.events.onCountFinished.removeAll(); this.follower.events.onPathStart.removeAll(); this.follower.events.onPathEnd.removeAll(); this.follower.events.onPathLoop.removeAll(); } ; Phaser.PathFollower.prototype.update = function (){ if (this._pauseTime != 0) { if (game.time.now < this._pauseTime) { return true ; } this._pauseTime = 0; if (this.follower.animations !== undefined) { if (this.follower.animations.currentAnim) { this.follower.animations.paused = false ; } } } var waitForFollower = false ; if (this.physicsAdjustTime && this.virtualParticle) { if (game.physics.arcade.distanceBetween(this.follower, this.virtualParticle) >= this.maximumGap) { waitForFollower = true ; } } if (!waitForFollower) { this._currentDistance += this._calculateDistance(); } var direction = (this.speed.avg * this._pathSpeed) >= 0? 1: -1; while ((direction == 1 && this._currentDistance >= _AN_Read_length("length", this._currentCurve)) || (direction == -1 && this._currentDistance < 0)){ var memCurveLength = _AN_Read_length("length", this._currentCurve); if (direction == -1) { var branchTaken = false ; var point = this.path.processData(this, this._currentPoint, true ); this.follower.events.onPathPointReached.dispatch(this.follower, point); this.takeBranchIfAvailable(); this._currentPoint-- ; if (this._currentPoint < 0) { if (this.path.loops) { this.follower.events.onPathLoop.dispatch(point); this._currentPoint = this.path.numPoints() - 1; } else { if (!this.yoyo) { this.follower.events.onPathEnd.dispatch(); } else { this.follower.events.onPathYoyo.dispatch(); var speed = { min: this.speed.min, max: this.speed.max} ; this.speed.min = - speed.max; this.speed.max = - speed.min; this._currentPoint = 0; this._currentCurve = this.path.getCurve(this._currentPoint); this._currentDistance = 0; return true ; } } } if (!branchTaken) { this._currentCurve = this.path.getCurve(this._currentPoint); if (!this._currentCurve) { return this.takeBranchIfAvailable(); } this._currentDistance += _AN_Read_length("length", this._currentCurve); } } else { this._currentPoint++ ; if (this.path.atEnd(this._currentPoint)) { if (this.path.loops) { this.follower.events.onPathLoop.dispatch(); this._currentPoint = 0; } else { if (!this.takeBranchIfAvailable()) { if (!this.yoyo) { this.follower.events.onPathEnd.dispatch(); } else { this.follower.events.onPathYoyo.dispatch(); var speed = { min: this.speed.min, max: this.speed.max} ; this.speed.min = - speed.max; this.speed.max = - speed.min; this._currentPoint = _AN_Read_length("length", this.path) - 2; this._currentCurve = this.path.getCurve(this._currentPoint); this._currentDistance = _AN_Read_length("length", this._currentCurve); return true ; } } } } point = this.path.processData(this, this._currentPoint, false ); this.follower.events.onPathPointReached.dispatch(this.follower, point); this.takeBranchIfAvailable(); this._currentDistance -= memCurveLength; this._currentCurve = this.path.getCurve(this._currentPoint); if (!this._currentCurve) { return this.takeBranchIfAvailable(); } } this._pathSpeed = point.speed; } return this.setPosition(); } ; Phaser.PathFollower.prototype._calculateDistance = function (){ if (this.speed.min === this.speed.max) { return game.time.elapsed * this.speed.avg * this._pathSpeed; } else { this.speed._elapsed += game.time.elapsed; this.speed._current = this.speed.current || this.speed.avg; if (this.speed._elapsed >= this.speed.theta) { this.speed._current = this.speed._target; this.speed._target = null ; this.speed._elapsed = 0; } if (!this.speed._target) { var min = Phaser.Math.clamp(this.speed._current - (this.speed._current * this.speed.lambda), this.speed.min, this.speed.max); var max = Phaser.Math.clamp(this.speed._current + (this.speed._current * this.speed.lambda), this.speed.min, this.speed.max); this.speed._target = game.rnd.realInRange(min, max); } var step = Phaser.Math.smoothstep(this.speed._elapsed, 0, this.speed.theta); return Phaser.Math.linear(this.speed._current, this.speed._target, step) * this._pathSpeed; ; } } ; Phaser.PathFollower.prototype.setPosition = function (){ if (!this.follower) { return false ; } this._currentCurve.getPointWithDistance(this._currentDistance, Phaser.PathFollower.tempPoint); var ox = this.offset.x; var oy = this.offset.y; if (this._angularOffset.distance != 0) { var angle = (this.follower.rotation + this._angularOffset.angle); ox += Math.cos(angle) * this._angularOffset.distance; oy += Math.sin(angle) * this._angularOffset.distance; } if (this.physicsAdjustTime) { this.virtualParticle.x = Phaser.PathFollower.tempPoint.x + ox; this.virtualParticle.y = Phaser.PathFollower.tempPoint.y + oy; if (this.follower.body) { game.physics.arcade.moveToObject(this.follower, this.virtualParticle, 100, this.physicsAdjustTime); } } else { this.follower.x = Phaser.PathFollower.tempPoint.x + ox; this.follower.y = Phaser.PathFollower.tempPoint.y + oy; } if (this._turnOffset !== undefined && this.follower.rotation !== undefined) { this.follower.rotation = this._currentCurve.getAngleWithDistance(this._currentDistance) + this._turnOffset; } return true ; } ; Phaser.PathFollower.prototype.takeBranchIfAvailable = function (){ var p = new Phaser.PathPoint(); if (this.path.getPathPoint(this._currentPoint, p)) { if (!p.branchPath || !this.branchPredicate || !this.branchPredicate(p, this.path)) { return false ; } this.changePath(p.branchPath, p.branchPointIndex); return true ; } return false ; } ; Phaser.PathFollower.prototype.changePath = function (branchPath, branchPointIndex){ this.path = branchPath; this._pathSpeed = this.path.getPathPointReference(0).speed; this._currentPoint = branchPointIndex; this._currentCurve = this.path.getCurve(this._currentPoint); if (!this._currentCurve) { return this.takeBranchIfAvailable(); } this.setPosition(); } ; Phaser.PathFollower.prototype.setOffset = function (x, y){ this.follower.x -= this.offset.x; this.follower.y -= this.offset.y; this.offset.x = x; this.offset.y = y; this.follower.x += this.offset.x; this.follower.y += this.offset.y; } ; Phaser.PathFollower.prototype.setAngularOffset = function (angle, distance){ this._angularOffset.angle = angle; this._angularOffset.distance = distance; } ; Phaser.PathFollower.prototype.pause = function (delay){ this._pauseTime = game.time.now + delay; if (this.follower.animations !== undefined) { if (this.follower.animations.currentAnim) { this.follower.animations.paused = true ; } } } ; Object.defineProperty(Phaser.PathFollower.prototype, 'paused', { get: function (){ return !!this._pauseTime; } , set: function (val){ if (!!val) { this.pause(Number.MAX_VALUE); } else { this._pauseTime = game.time.now - 1; } } , enumerable: true , configurable: true } );