UNPKG

detect-collisions

Version:

Points, Lines, Boxes, Polygons (also hollow), Ellipses, Circles. RayCasting, offsets, rotation, scaling, bounding box padding, flags for static and ghost/trigger bodies

226 lines (225 loc) 5.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Circle = void 0; const model_1 = require("../model"); const utils_1 = require("../utils"); /** * collider - circle */ class Circle extends model_1.SATCircle { /** * collider - circle */ constructor(position, radius, options) { super((0, utils_1.ensureVectorPoint)(position), radius); /** * offset copy without angle applied */ this.offsetCopy = { x: 0, y: 0 }; /** * was the polygon modified and needs update in the next checkCollision */ this.dirty = false; /* * circles are convex */ this.isConvex = true; /** * circle type */ this.type = model_1.BodyType.Circle; /** * faster than type */ this.typeGroup = model_1.BodyGroup.Circle; /** * always centered */ this.isCentered = true; (0, utils_1.extendBody)(this, options); this.unscaledRadius = radius; } /** * get this.pos.x */ get x() { return this.pos.x; } /** * updating this.pos.x by this.x = x updates AABB */ set x(x) { this.pos.x = x; this.markAsDirty(); } /** * get this.pos.y */ get y() { return this.pos.y; } /** * updating this.pos.y by this.y = y updates AABB */ set y(y) { this.pos.y = y; this.markAsDirty(); } /** * allow get scale */ get scale() { return this.r / this.unscaledRadius; } /** * shorthand for setScale() */ set scale(scale) { this.setScale(scale); } /** * scaleX = scale in case of Circles */ get scaleX() { return this.scale; } /** * scaleY = scale in case of Circles */ get scaleY() { return this.scale; } // Don't overwrite docs from BodyProps get group() { return this._group; } // Don't overwrite docs from BodyProps set group(group) { this._group = (0, utils_1.getGroup)(group); } /** * update position BY MOVING FORWARD IN ANGLE DIRECTION */ move(speed = 1, updateNow = true) { (0, utils_1.move)(this, speed, updateNow); return this; } /** * update position BY TELEPORTING */ setPosition(x, y, updateNow = true) { this.pos.x = x; this.pos.y = y; this.markAsDirty(updateNow); return this; } /** * update scale */ setScale(scaleX, _scaleY = scaleX, updateNow = true) { this.r = this.unscaledRadius * Math.abs(scaleX); this.markAsDirty(updateNow); return this; } /** * set rotation */ setAngle(angle, updateNow = true) { this.angle = angle; const { x, y } = this.getOffsetWithAngle(); this.offset.x = x; this.offset.y = y; this.markAsDirty(updateNow); return this; } /** * set offset from center */ setOffset(offset, updateNow = true) { this.offsetCopy.x = offset.x; this.offsetCopy.y = offset.y; const { x, y } = this.getOffsetWithAngle(); this.offset.x = x; this.offset.y = y; this.markAsDirty(updateNow); return this; } /** * get body bounding box, without padding */ getAABBAsBBox() { const x = this.pos.x + this.offset.x; const y = this.pos.y + this.offset.y; return { minX: x - this.r, maxX: x + this.r, minY: y - this.r, maxY: y + this.r, }; } /** * Draws collider on a CanvasRenderingContext2D's current path */ draw(context) { const x = this.pos.x + this.offset.x; const y = this.pos.y + this.offset.y; const r = Math.abs(this.r); if (this.isTrigger) { const max = Math.max(8, this.r); for (let i = 0; i < max; i++) { const arc = (i / max) * 2 * Math.PI; const arcPrev = ((i - 1) / max) * 2 * Math.PI; const fromX = x + Math.cos(arcPrev) * this.r; const fromY = y + Math.sin(arcPrev) * this.r; const toX = x + Math.cos(arc) * this.r; const toY = y + Math.sin(arc) * this.r; (0, utils_1.dashLineTo)(context, fromX, fromY, toX, toY); } } else { context.moveTo(x + r, y); context.arc(x, y, r, 0, Math.PI * 2); } } /** * Draws Bounding Box on canvas context */ drawBVH(context) { (0, utils_1.drawBVH)(context, this); } /** * inner function for after position change update aabb in system */ updateBody(updateNow = this.dirty) { var _a; if (updateNow) { (_a = this.system) === null || _a === void 0 ? void 0 : _a.insert(this); this.dirty = false; } } /** * update instantly or mark as dirty */ markAsDirty(updateNow = false) { if (updateNow) { this.updateBody(true); } else { this.dirty = true; } } /** * internal for getting offset with applied angle */ getOffsetWithAngle() { if ((!this.offsetCopy.x && !this.offsetCopy.y) || !this.angle) { return this.offsetCopy; } const sin = Math.sin(this.angle); const cos = Math.cos(this.angle); const x = this.offsetCopy.x * cos - this.offsetCopy.y * sin; const y = this.offsetCopy.x * sin + this.offsetCopy.y * cos; return { x, y }; } } exports.Circle = Circle;