added viewport smoothing

This commit is contained in:
Joe Weaver 2020-09-19 15:21:55 -04:00
parent 90996115f1
commit d452678344
2 changed files with 47 additions and 6 deletions

View File

@ -29,6 +29,10 @@ export default class Vec2 {
this.vec[1] = y; this.vec[1] = y;
} }
static get ZERO() {
return new Vec2(0, 0);
}
/** /**
* The squared magnitude of the vector * The squared magnitude of the vector
*/ */

View File

@ -3,6 +3,7 @@ import Vec4 from "../DataTypes/Vec4";
import GameNode from "../Nodes/GameNode"; import GameNode from "../Nodes/GameNode";
import CanvasNode from "../Nodes/CanvasNode"; import CanvasNode from "../Nodes/CanvasNode";
import MathUtils from "../Utils/MathUtils"; import MathUtils from "../Utils/MathUtils";
import Queue from "../DataTypes/Queue";
export default class Viewport { export default class Viewport {
private position: Vec2; private position: Vec2;
@ -10,10 +11,22 @@ export default class Viewport {
private bounds: Vec4; private bounds: Vec4;
private following: GameNode; private following: GameNode;
/**
* A queue of previous positions of what this viewport is following. Used for smoothing viewport movement
*/
private lastPositions: Queue<Vec2>;
/**
* The number of previous positions this viewport tracks
*/
private smoothingFactor: number;
constructor(){ constructor(){
this.position = new Vec2(0, 0); this.position = new Vec2(0, 0);
this.size = new Vec2(0, 0); this.size = new Vec2(0, 0);
this.bounds = new Vec4(0, 0, 0, 0); this.bounds = new Vec4(0, 0, 0, 0);
this.lastPositions = new Queue();
this.smoothingFactor = 10;
} }
/** /**
@ -29,11 +42,15 @@ export default class Viewport {
* @param y * @param y
*/ */
setPosition(vecOrX: Vec2 | number, y: number = null): void { setPosition(vecOrX: Vec2 | number, y: number = null): void {
let pos: Vec2;
if(vecOrX instanceof Vec2){ if(vecOrX instanceof Vec2){
this.position.set(vecOrX.x, vecOrX.y); pos = vecOrX;
} else { } else {
this.position.set(vecOrX, y); pos = new Vec2(vecOrX, y);
} }
this.lastPositions.clear();
this.lastPositions.enqueue(pos);
} }
/** /**
@ -56,6 +73,15 @@ export default class Viewport {
} }
} }
/**
* Sets the smoothing factor for the viewport movement.
* @param smoothingFactor The smoothing factor for the viewport
*/
setSmoothingFactor(smoothingFactor: number): void {
if(smoothingFactor < 1) smoothingFactor = 1;
this.smoothingFactor = smoothingFactor;
}
/** /**
* Returns true if the CanvasNode is inside of the viewport * Returns true if the CanvasNode is inside of the viewport
* @param node * @param node
@ -99,9 +125,20 @@ export default class Viewport {
update(deltaT: number): void { update(deltaT: number): void {
// If viewport is following an object // If viewport is following an object
if(this.following){ if(this.following){
// Update our list of previous positions
this.lastPositions.enqueue(this.following.getPosition().clone());
if(this.lastPositions.getSize() > this.smoothingFactor){
this.lastPositions.dequeue();
}
// Get the average of the last 10 positions
let pos = Vec2.ZERO;
this.lastPositions.forEach(position => pos.add(position));
pos.scale(1/this.lastPositions.getSize());
// Set this position either to the object or to its bounds // Set this position either to the object or to its bounds
this.position.x = this.following.getPosition().x - this.size.x/2; this.position.x = pos.x - this.size.x/2;
this.position.y = this.following.getPosition().y - this.size.y/2; this.position.y = pos.y - this.size.y/2;
let [min, max] = this.bounds.split(); let [min, max] = this.bounds.split();
this.position.x = MathUtils.clamp(this.position.x, min.x, max.x - this.size.x); this.position.x = MathUtils.clamp(this.position.x, min.x, max.x - this.size.x);
this.position.y = MathUtils.clamp(this.position.y, min.y, max.y - this.size.y); this.position.y = MathUtils.clamp(this.position.y, min.y, max.y - this.size.y);