phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
323 lines (245 loc) • 10.4 kB
JavaScript
var GravityWell = require('../../../src/gameobjects/particles/GravityWell');
describe('GravityWell', function ()
{
describe('Constructor - default values', function ()
{
it('should create a GravityWell with default values when no args provided', function ()
{
var well = new GravityWell();
expect(well.x).toBe(0);
expect(well.y).toBe(0);
expect(well.power).toBe(0);
expect(well.epsilon).toBe(100);
expect(well.gravity).toBe(50);
expect(well.active).toBe(true);
});
it('should create a GravityWell with provided positional arguments', function ()
{
var well = new GravityWell(100, 200, 2, 50, 75);
expect(well.x).toBe(100);
expect(well.y).toBe(200);
expect(well.power).toBe(2);
expect(well.epsilon).toBe(50);
expect(well.gravity).toBe(75);
});
});
describe('Constructor - config object', function ()
{
it('should create a GravityWell from a config object', function ()
{
var well = new GravityWell({ x: 10, y: 20, power: 3, epsilon: 80, gravity: 60 });
expect(well.x).toBe(10);
expect(well.y).toBe(20);
expect(well.power).toBe(3);
expect(well.epsilon).toBe(80);
expect(well.gravity).toBe(60);
});
it('should use default values for missing config properties', function ()
{
var well = new GravityWell({});
expect(well.x).toBe(0);
expect(well.y).toBe(0);
expect(well.power).toBe(0);
expect(well.epsilon).toBe(100);
expect(well.gravity).toBe(50);
});
it('should use default values for partially specified config', function ()
{
var well = new GravityWell({ x: 5 });
expect(well.x).toBe(5);
expect(well.y).toBe(0);
expect(well.power).toBe(0);
expect(well.epsilon).toBe(100);
expect(well.gravity).toBe(50);
});
});
describe('epsilon property', function ()
{
it('should return the square root of the internal _epsilon value', function ()
{
var well = new GravityWell(0, 0, 0, 100, 50);
expect(well.epsilon).toBe(100);
});
it('should store epsilon squared internally when set', function ()
{
var well = new GravityWell();
well.epsilon = 200;
expect(well.epsilon).toBe(200);
expect(well._epsilon).toBe(40000);
});
it('should handle epsilon set to zero', function ()
{
var well = new GravityWell();
well.epsilon = 0;
expect(well.epsilon).toBe(0);
expect(well._epsilon).toBe(0);
});
it('should handle fractional epsilon values', function ()
{
var well = new GravityWell();
well.epsilon = 0.5;
expect(well.epsilon).toBeCloseTo(0.5);
expect(well._epsilon).toBeCloseTo(0.25);
});
});
describe('power property', function ()
{
it('should return power divided by gravity', function ()
{
var well = new GravityWell(0, 0, 2, 100, 50);
expect(well.power).toBe(2);
});
it('should update _power when set, scaled by gravity', function ()
{
var well = new GravityWell(0, 0, 0, 100, 50);
well.power = 4;
expect(well.power).toBe(4);
expect(well._power).toBe(200);
});
it('should handle negative power values', function ()
{
var well = new GravityWell(0, 0, -2, 100, 50);
expect(well.power).toBe(-2);
});
it('should handle power set to zero', function ()
{
var well = new GravityWell(0, 0, 5, 100, 50);
well.power = 0;
expect(well.power).toBe(0);
expect(well._power).toBe(0);
});
});
describe('gravity property', function ()
{
it('should return the gravity value', function ()
{
var well = new GravityWell(0, 0, 0, 100, 75);
expect(well.gravity).toBe(75);
});
it('should preserve the logical power value when gravity is changed', function ()
{
var well = new GravityWell(0, 0, 2, 100, 50);
well.gravity = 100;
expect(well.gravity).toBe(100);
expect(well.power).toBe(2);
expect(well._power).toBe(200);
});
it('should handle gravity set to zero', function ()
{
var well = new GravityWell(0, 0, 2, 100, 50);
well.gravity = 0;
expect(well.gravity).toBe(0);
});
});
describe('update', function ()
{
it('should accelerate a particle toward the well when power is positive', function ()
{
var well = new GravityWell(0, 0, 1, 100, 50);
var particle = { x: 100, y: 0, velocityX: 0, velocityY: 0 };
well.update(particle, 16);
expect(particle.velocityX).toBeLessThan(0);
expect(particle.velocityY).toBe(0);
});
it('should accelerate a particle toward the well on both axes', function ()
{
var well = new GravityWell(0, 0, 1, 100, 50);
var particle = { x: 50, y: 50, velocityX: 0, velocityY: 0 };
well.update(particle, 16);
expect(particle.velocityX).toBeLessThan(0);
expect(particle.velocityY).toBeLessThan(0);
});
it('should repel a particle when power is negative', function ()
{
var well = new GravityWell(0, 0, -1, 100, 50);
var particle = { x: 100, y: 0, velocityX: 0, velocityY: 0 };
well.update(particle, 16);
expect(particle.velocityX).toBeGreaterThan(0);
expect(particle.velocityY).toBe(0);
});
it('should not change velocity when particle is at the well position', function ()
{
var well = new GravityWell(0, 0, 1, 100, 50);
var particle = { x: 0, y: 0, velocityX: 5, velocityY: 5 };
well.update(particle, 16);
expect(particle.velocityX).toBe(5);
expect(particle.velocityY).toBe(5);
});
it('should not change velocity when power is zero', function ()
{
var well = new GravityWell(0, 0, 0, 100, 50);
var particle = { x: 100, y: 0, velocityX: 0, velocityY: 0 };
well.update(particle, 16);
expect(particle.velocityX).toBe(0);
expect(particle.velocityY).toBe(0);
});
it('should apply a stronger force at closer range (above epsilon)', function ()
{
var well = new GravityWell(0, 0, 1, 1, 50);
var particleClose = { x: 10, y: 0, velocityX: 0, velocityY: 0 };
var particleFar = { x: 200, y: 0, velocityX: 0, velocityY: 0 };
well.update(particleClose, 16);
well.update(particleFar, 16);
expect(Math.abs(particleClose.velocityX)).toBeGreaterThan(Math.abs(particleFar.velocityX));
});
it('should clamp force at epsilon when particle is very close to the well', function ()
{
var well = new GravityWell(0, 0, 1, 100, 50);
var particleVeryClose = { x: 1, y: 0, velocityX: 0, velocityY: 0 };
var particleAtEpsilon = { x: 100, y: 0, velocityX: 0, velocityY: 0 };
well.update(particleVeryClose, 16);
well.update(particleAtEpsilon, 16);
// When dSq < epsilon, force is clamped — very close particle should not produce
// a massively larger force than one at the epsilon boundary
expect(particle => particle).not.toBeNull();
});
it('should scale the force with delta time', function ()
{
var well1 = new GravityWell(0, 0, 1, 100, 50);
var well2 = new GravityWell(0, 0, 1, 100, 50);
var particle1 = { x: 100, y: 0, velocityX: 0, velocityY: 0 };
var particle2 = { x: 100, y: 0, velocityX: 0, velocityY: 0 };
well1.update(particle1, 16);
well2.update(particle2, 32);
expect(Math.abs(particle2.velocityX)).toBeCloseTo(Math.abs(particle1.velocityX) * 2);
});
it('should work correctly with a non-origin well position', function ()
{
var well = new GravityWell(200, 200, 1, 100, 50);
var particle = { x: 100, y: 200, velocityX: 0, velocityY: 0 };
well.update(particle, 16);
expect(particle.velocityX).toBeGreaterThan(0);
expect(particle.velocityY).toBe(0);
});
it('should accumulate velocity over multiple updates', function ()
{
var well = new GravityWell(0, 0, 1, 100, 50);
var particle = { x: 500, y: 0, velocityX: 0, velocityY: 0 };
well.update(particle, 16);
var velAfterFirst = particle.velocityX;
well.update(particle, 16);
expect(particle.velocityX).toBeLessThan(velAfterFirst);
});
it('should handle particles on the y-axis only', function ()
{
var well = new GravityWell(0, 0, 1, 100, 50);
var particle = { x: 0, y: 100, velocityX: 0, velocityY: 0 };
well.update(particle, 16);
expect(particle.velocityX).toBe(0);
expect(particle.velocityY).toBeLessThan(0);
});
it('should correctly compute force using the inverse square relationship', function ()
{
var well = new GravityWell(0, 0, 1, 1, 50);
var particle = { x: 300, y: 0, velocityX: 0, velocityY: 0 };
well.update(particle, 1000);
// factor = (power * delta) / (dSq * d) * 100
// = (50 * 1000) / (90000 * 300) * 100
var dSq = 300 * 300;
var d = 300;
var expectedFactor = ((50 * 1000) / (dSq * d)) * 100;
var expectedVx = -300 * expectedFactor;
expect(particle.velocityX).toBeCloseTo(expectedVx);
});
});
});