avocado-old/packages/topdown/camera.js

99 lines
2.3 KiB
JavaScript
Raw Normal View History

2019-04-05 07:17:01 -05:00
import {compose} from '@avocado/core';
2019-04-05 11:54:38 -05:00
import {Rectangle, Vector} from '@avocado/math';
2019-04-05 07:17:01 -05:00
import {EventEmitter, Property} from '@avocado/mixins';
const decorate = compose(
EventEmitter,
Vector.Mixin('areaSize', 'areaWidth', 'areaHeight', {
default: [0, 0],
track: true,
}),
Property('drag', {
2019-04-11 12:19:57 -05:00
default: 0.2,
2019-04-05 07:17:01 -05:00
}),
Vector.Mixin('position', 'x', 'y', {
default: [0, 0],
}),
Vector.Mixin('realPosition', 'realX', 'realY', {
default: [0, 0],
track: true,
}),
Vector.Mixin('viewSize', 'viewWidth', 'viewHeight', {
default: [0, 0],
track: true,
}),
);
export class Camera extends decorate(class {}) {
constructor() {
super();
this.onAreaSizeChanged = this.onAreaSizeChanged.bind(this);
this.on('areaSizeChanged', this.onAreaSizeChanged);
this.onViewSizeChanged = this.onViewSizeChanged.bind(this);
this.on('viewSizeChanged', this.onViewSizeChanged);
}
destroy() {
this.off('areaSizeChanged', this.onAreaSizeChanged);
this.off('viewSizeChanged', this.onViewSizeChanged);
}
onAreaSizeChanged() {
this.position = this.position;
}
onViewSizeChanged() {
this.position = this.position;
}
get position() {
return super.position;
}
set position(position) {
if (0 === Vector.area(this.areaSize)) {
return super.position = position;
}
if (0 === Vector.area(this.viewSize)) {
return super.position = position;
}
const halfViewSize = Vector.scale(this.viewSize, 0.5);
super.position = Vector.clamp(
position,
halfViewSize,
Vector.sub(this.areaSize, halfViewSize)
);
}
2019-04-05 11:54:38 -05:00
get rectangle() {
return Rectangle.compose(
Vector.sub(this.position, Vector.scale(this.viewSize, 0.5)),
this.viewSize,
);
}
2019-04-05 07:17:01 -05:00
tick(elapsed) {
2019-04-10 19:17:28 -05:00
if (Vector.equals(this.position, this.realPosition)) {
return;
}
2019-04-11 12:19:57 -05:00
if (0 === this.drag) {
this.realPosition = this.position;
}
if (Vector.equalsClose(this.position, this.realPosition, 0.5)) {
2019-04-05 07:17:01 -05:00
this.realPosition = this.position;
return;
}
2019-04-11 12:19:57 -05:00
// Sanity check.
const k = elapsed / this.drag;
if (k >= 1) {
this.realPosition = this.position;
return;
}
const diff = Vector.sub(this.position, this.realPosition);
const magnitude = Vector.scale(diff, k);
this.realPosition = Vector.add(this.realPosition, magnitude);
2019-04-05 07:17:01 -05:00
}
}