lr-core
Version:
Line Rider core library
126 lines (97 loc) • 3.43 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _v = require('../../v2');
var _v2 = _interopRequireDefault(_v);
var _Line = require('./Line.js');
var _Line2 = _interopRequireDefault(_Line);
var _LineTypes = require('./LineTypes.js');
var _LineTypes2 = _interopRequireDefault(_LineTypes);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const MAX_FORCE_LENGTH = 10;
const MIN_EXTENSION_RATIO = 0.25;
class SolidLine extends _Line2.default {
constructor(data) {
super(data);
this.flipped = data.flipped || false;
this.leftExtended = data.leftExtended || false;
this.rightExtended = data.rightExtended || false;
this.c = this.getComputed();
}
collidesWith(p) {
let offset = this.offset(p);
return this.shouldCollide(p, this.perpComp(offset), this.linePos(offset));
}
collide(p) {
let offset = this.offset(p);
let perpComp = this.perpComp(offset);
let linePos = this.linePos(offset);
if (this.shouldCollide(p, perpComp, linePos)) {
let pos = (0, _v2.default)(this.c.norm).mul(perpComp).sub(p.pos).mul(-1);
// move the previous point closer to reduce inertia and simulate friction
// retain multiplication order because multiplication is not associative
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.5.1
let v = (0, _v2.default)(this.c.norm).rotCCW().mul(p.friction).mul(perpComp);
if (p.prevPos.x >= pos.x) {
v.x *= -1;
}
if (p.prevPos.y < pos.y) {
v.y *= -1;
}
v.add(p.prevPos);
return this.doCollide(p, pos, v);
}
return null;
}
get type() {
return _LineTypes2.default.SOLID;
}
get collidable() {
return true;
}
get extension() {
return Math.min(MIN_EXTENSION_RATIO, MAX_FORCE_LENGTH / this.length);
}
get leftBound() {
return this.leftExtended ? -this.extension : 0;
}
get rightBound() {
return this.rightExtended ? 1 + this.extension : 1;
}
getComputed() {
let { vec, norm, invLengthSq, length, extension, leftBound, rightBound } = this;
return { vec, norm, invLengthSq, length, extension, leftBound, rightBound };
}
offset(p) {
return (0, _v2.default)(p.pos).sub(this.p1);
}
// perpendicular component
perpComp(offset) {
return this.c.norm.dot(offset);
}
// normalized parallel component
// or closest relative position on the line to the point
// this is the slowest function
// so maybe come up with a faster boundary checking algo
linePos(offset) {
return this.c.vec.dot(offset) * this.c.invLengthSq;
}
shouldCollide(p, perpComp, linePos) {
let pntDirection = this.c.norm.dot(p.vel);
let pointMovingIntoLine = pntDirection > 0;
let pointInForceBounds = perpComp > 0 && perpComp < MAX_FORCE_LENGTH && linePos >= this.c.leftBound && linePos <= this.c.rightBound;
return pointMovingIntoLine && pointInForceBounds;
}
doCollide(p, pos, prevPos) {
return p.updateState({ pos, prevPos });
}
equals(line) {
return super.equals(line) && this.flipped === line.flipped && this.leftExtended === line.leftExtended && this.rightExtended === line.rightExtended;
}
toJSON() {
let { flipped, leftExtended, rightExtended } = this;
return Object.assign(super.toJSON(), { flipped, leftExtended, rightExtended });
}
}
exports.default = SolidLine;