|
|
@@ -0,0 +1,238 @@ |
|
|
// Original imp: https://github.com/jdnichollsc/Phaser-Kinetic-Scrolling-Plugin |
|
|
// Adapted to phaser 3 By Christian Panadero |
|
|
export default class KineticScroll { |
|
|
private pointerId |
|
|
private startX |
|
|
private startY |
|
|
|
|
|
private screenX |
|
|
private screenY |
|
|
|
|
|
private pressedDown |
|
|
private timestamp |
|
|
private beginTime |
|
|
private velocityY |
|
|
private velocityX |
|
|
private amplitudeY |
|
|
private amplitudeX |
|
|
|
|
|
// from move function |
|
|
private now |
|
|
private thresholdOfTapTime |
|
|
private thresholdOfTapDistance |
|
|
private dragging |
|
|
private settings |
|
|
|
|
|
// from end |
|
|
private autoScrollX |
|
|
private autoScrollY |
|
|
private velocityWheelXAbs |
|
|
private velocityWheelYAbs |
|
|
private targetX |
|
|
private targetY |
|
|
private velocityWheelX |
|
|
private velocityWheelY |
|
|
|
|
|
// from update |
|
|
private elapsed |
|
|
|
|
|
private scene: Phaser.Scene |
|
|
constructor (scene: Phaser.Scene) { |
|
|
this.scene = scene |
|
|
this.settings = { |
|
|
kineticMovement: true, |
|
|
timeConstantScroll: 325, |
|
|
horizontalScroll: true, |
|
|
verticalScroll: true, |
|
|
horizontalWheel: true, |
|
|
verticalWheel: false, |
|
|
deltaWheel: 40, |
|
|
onUpdate: null |
|
|
} |
|
|
} |
|
|
|
|
|
beginMove (pointer) { |
|
|
this.pointerId = pointer.id |
|
|
this.startX = this.scene.input.x |
|
|
this.startY = this.scene.input.y |
|
|
|
|
|
this.screenX = pointer.screenX |
|
|
this.screenY = pointer.screenY |
|
|
|
|
|
this.pressedDown = true |
|
|
|
|
|
this.timestamp = Date.now() |
|
|
|
|
|
// the time of press down |
|
|
this.beginTime = this.timestamp |
|
|
this.velocityY = this.amplitudeY = this.velocityX = this.amplitudeX = 0 |
|
|
} |
|
|
|
|
|
canCameraMoveY () { |
|
|
const cam = this.scene.cameras.main |
|
|
const camJson = cam.toJSON() |
|
|
const camBoundH = camJson['bounds']['height'] |
|
|
return cam.scrollY > 0 && cam.scrollY + cam.height < camBoundH |
|
|
} |
|
|
|
|
|
canCameraMoveX () { |
|
|
const cam = this.scene.cameras.main |
|
|
const camJson = cam.toJSON() |
|
|
const camBoundW = camJson['bounds']['width'] |
|
|
const camBoundX = camJson['bounds']['x'] |
|
|
const camBoundRight = camBoundW + camBoundX |
|
|
return cam.scrollX > 0 && cam.scrollX + cam.width < camBoundRight |
|
|
} |
|
|
|
|
|
move (pointer, x, y) { |
|
|
if (!this.pressedDown) return |
|
|
|
|
|
// If it is not the current pointer |
|
|
if (this.pointerId !== pointer.id) return |
|
|
|
|
|
this.now = Date.now() |
|
|
const elapsed = this.now - this.timestamp |
|
|
this.timestamp = this.now |
|
|
|
|
|
let deltaX = 0 |
|
|
let deltaY = 0 |
|
|
|
|
|
// It`s a fast tap not move |
|
|
if ( |
|
|
this.now - this.beginTime < this.thresholdOfTapTime |
|
|
&& Math.abs(pointer.screenY - this.screenY) < this.thresholdOfTapDistance |
|
|
&& Math.abs(pointer.screenX - this.screenX) < this.thresholdOfTapDistance |
|
|
) return |
|
|
|
|
|
const cam = this.scene.cameras.main |
|
|
if (this.settings.horizontalScroll) { |
|
|
deltaX = x - this.startX |
|
|
if (deltaX !== 0) { |
|
|
this.dragging = true |
|
|
} |
|
|
this.startX = x |
|
|
this.velocityX = 0.8 * (1000 * deltaX / (1 + elapsed)) + 0.2 * this.velocityX |
|
|
cam.setScroll(cam.scrollX - deltaX, cam.scrollY) |
|
|
} |
|
|
|
|
|
if (this.settings.verticalScroll) { |
|
|
deltaY = y - this.startY |
|
|
if (deltaY !== 0) { |
|
|
this.dragging = true |
|
|
} |
|
|
this.startY = y |
|
|
this.velocityY = 0.8 * (1000 * deltaY / (1 + elapsed)) + 0.2 * this.velocityY |
|
|
cam.setScroll(cam.scrollX, cam.scrollY - deltaY) |
|
|
} |
|
|
|
|
|
if (typeof this.settings.onUpdate === 'function') { |
|
|
let updateX = 0 |
|
|
if (this.canCameraMoveX()) { |
|
|
updateX = deltaX |
|
|
} |
|
|
|
|
|
let updateY = 0 |
|
|
if (this.canCameraMoveY()) { |
|
|
updateY = deltaY |
|
|
} |
|
|
|
|
|
this.settings.onUpdate(updateX, updateY) |
|
|
} |
|
|
} |
|
|
|
|
|
endMove () { |
|
|
this.pointerId = null |
|
|
this.pressedDown = false |
|
|
this.autoScrollX = false |
|
|
this.autoScrollY = false |
|
|
|
|
|
if (!this.settings.kineticMovement) return |
|
|
|
|
|
this.now = Date.now() |
|
|
|
|
|
const cam = this.scene.cameras.main |
|
|
if (this.withinGame()) { |
|
|
if (this.velocityX > 10 || this.velocityX < -10) { |
|
|
this.amplitudeX = 0.8 * this.velocityX |
|
|
this.targetX = Math.round(cam.scrollX - this.amplitudeX) |
|
|
this.autoScrollX = true |
|
|
} |
|
|
|
|
|
if (this.velocityY > 10 || this.velocityY < -10) { |
|
|
this.amplitudeY = 0.8 * this.velocityY |
|
|
this.targetY = Math.round(cam.scrollY - this.amplitudeY) |
|
|
this.autoScrollY = true |
|
|
} |
|
|
} |
|
|
|
|
|
if (!this.withinGame()) { |
|
|
this.velocityWheelXAbs = Math.abs(this.velocityWheelX) |
|
|
this.velocityWheelYAbs = Math.abs(this.velocityWheelY) |
|
|
if ( |
|
|
this.settings.horizontalScroll |
|
|
&& (this.velocityWheelXAbs < 0.1 || !this.withinGame()) |
|
|
) { |
|
|
this.autoScrollX = true |
|
|
} |
|
|
if ( |
|
|
this.settings.verticalScroll |
|
|
&& (this.velocityWheelYAbs < 0.1 || !this.withinGame()) |
|
|
) { |
|
|
this.autoScrollY = true |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
update () { |
|
|
this.elapsed = Date.now() - this.timestamp |
|
|
this.velocityWheelXAbs = Math.abs(this.velocityWheelX) |
|
|
this.velocityWheelYAbs = Math.abs(this.velocityWheelY) |
|
|
|
|
|
let delta = 0 |
|
|
const cam = this.scene.cameras.main |
|
|
if (this.autoScrollX && this.amplitudeX !== 0) { |
|
|
|
|
|
delta = -this.amplitudeX * Math.exp(-this.elapsed / this.settings.timeConstantScroll) |
|
|
if (this.canCameraMoveX() && (delta > 0.5 || delta < -0.5)) { |
|
|
cam.setScroll(this.targetX - delta, cam.scrollY) |
|
|
} else { |
|
|
this.autoScrollX = false |
|
|
cam.setScroll(this.targetX, cam.scrollY) |
|
|
} |
|
|
} |
|
|
|
|
|
if (this.autoScrollY && this.amplitudeY !== 0) { |
|
|
|
|
|
delta = -this.amplitudeY * Math.exp(-this.elapsed / this.settings.timeConstantScroll) |
|
|
if (this.canCameraMoveY() && (delta > 0.5 || delta < -0.5)) { |
|
|
cam.setScroll(cam.scrollX, this.targetY - delta) |
|
|
} else { |
|
|
this.autoScrollY = false |
|
|
cam.setScroll(cam.scrollX, this.targetY) |
|
|
} |
|
|
} |
|
|
|
|
|
if (!this.autoScrollX && !this.autoScrollY) { |
|
|
this.dragging = false |
|
|
} |
|
|
|
|
|
if (this.settings.horizontalWheel && this.velocityWheelXAbs > 0.1) { |
|
|
this.dragging = true |
|
|
this.amplitudeX = 0 |
|
|
this.autoScrollX = false |
|
|
cam.setScroll(cam.scrollX - this.velocityWheelX, cam.scrollY) |
|
|
this.velocityWheelX *= 0.95 |
|
|
} |
|
|
|
|
|
if (this.settings.verticalWheel && this.velocityWheelYAbs > 0.1) { |
|
|
this.dragging = true |
|
|
this.autoScrollY = false |
|
|
cam.setScroll(cam.scrollX, cam.scrollY - this.velocityWheelY) |
|
|
this.velocityWheelY *= 0.95 |
|
|
} |
|
|
} |
|
|
|
|
|
withinGame () { |
|
|
return true |
|
|
} |
|
|
} |