diff --git a/src/js/position.js b/src/js/position.js new file mode 100644 index 0000000..8799702 --- /dev/null +++ b/src/js/position.js @@ -0,0 +1,32 @@ +import { FPS, gravity } from './constants.js' +import { add, scale, Vec2 } from './vector.js' + +/** @typedef {import('./shape').Shape} Shape */ +/** @typedef {import('./vector').Vector2D} Vector2D */ + +/** + * Update the position of the shape. + * + * @param {Shape} shape + * @param {Vector2D} [g=gravity] + */ +export function updatePosition (shape, g = gravity) { + // Apply gravity to all shapes with mass + const acceleration = shape.M > 0 ? g : Vec2(0, 0) + shape.V = add(shape.V, scale(acceleration, 1 / FPS)) + moveShape(shape, scale(shape.V, 1 / FPS)) +} + +/** + * Move a shape along a vector. + * + * @param {Shape} shape + * @param {Vector2D} v + */ +function moveShape (shape, v) { + shape.C = add(shape.C, v) + + shape.X.forEach(function (vertex, index) { + shape.X[index] = add(vertex, v) + }) +} diff --git a/test/js/position.test.js b/test/js/position.test.js new file mode 100644 index 0000000..a5323e1 --- /dev/null +++ b/test/js/position.test.js @@ -0,0 +1,47 @@ +import { expect } from 'chai' + +import { updatePosition } from '../../src/js/position.js' +import { RigidShape } from '../../src/js/shape.js' +import { Vec2 } from '../../src/js/vector.js' + +describe('Position', function () { + describe('when passed no gravity', function () { + it('should update the position using a default value', function () { + // Arrange + const shape = makeShape() + const c = {...shape.C} + const v = {...shape.V} + const x = [...shape.X] + + // Act + updatePosition(shape) + + // Assert + expect(shape.C).not.to.equal(c) + expect(shape.V).not.to.equal(v) + shape.X.forEach((vertex, i) => expect(vertex).not.to.equal(x[i])) + }) + }) +}) + +function makeShape () { + const center = Vec2(500, 200) + const friction = 20 + const restitution = 0 + const mass = 400 + const bounds = 1 + const width = 5 + const height = 5 + + const shape = RigidShape({ + center, + mass, + friction, + restitution, + bounds, + width, + height + }) + + return shape +} diff --git a/types/position.d.ts b/types/position.d.ts new file mode 100644 index 0000000..9fe838e --- /dev/null +++ b/types/position.d.ts @@ -0,0 +1,11 @@ +/** @typedef {import('./shape').Shape} Shape */ +/** @typedef {import('./vector').Vector2D} Vector2D */ +/** + * Update the position of the shape. + * + * @param {Shape} shape + * @param {Vector2D} [g=gravity] + */ +export function updatePosition(shape: Shape, g?: import("./vector.js").Vector2D | undefined): void; +export type Shape = import('./shape').Shape; +export type Vector2D = import('./vector').Vector2D;