phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
382 lines (310 loc) • 13.3 kB
JavaScript
var EdgeZone = require('../../../../src/gameobjects/particles/zones/EdgeZone');
function makeSource (points)
{
return {
getPoints: function (quantity, stepRate)
{
return points.map(function (p)
{
return { x: p.x, y: p.y };
});
}
};
}
function makeParticle ()
{
return { x: 0, y: 0 };
}
describe('EdgeZone', function ()
{
describe('constructor', function ()
{
it('should set source, quantity, and stepRate from arguments', function ()
{
var source = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var zone = new EdgeZone(source, 5, 2);
expect(zone.source).toBe(source);
expect(zone.quantity).toBe(5);
expect(zone.stepRate).toBe(2);
});
it('should default yoyo to false', function ()
{
var source = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var zone = new EdgeZone(source, 2);
expect(zone.yoyo).toBe(false);
});
it('should default seamless to true', function ()
{
var source = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var zone = new EdgeZone(source, 2);
expect(zone.seamless).toBe(true);
});
it('should default total to -1', function ()
{
var source = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var zone = new EdgeZone(source, 2);
expect(zone.total).toBe(-1);
});
it('should accept explicit yoyo, seamless, and total values', function ()
{
var source = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var zone = new EdgeZone(source, 2, 1, true, false, 5);
expect(zone.yoyo).toBe(true);
expect(zone.seamless).toBe(false);
expect(zone.total).toBe(5);
});
it('should initialise counter to -1', function ()
{
var source = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var zone = new EdgeZone(source, 2);
expect(zone.counter).toBe(-1);
});
it('should populate points by calling updateSource', function ()
{
var pts = [{ x: 0, y: 0 }, { x: 5, y: 0 }, { x: 10, y: 0 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3);
expect(zone.points.length).toBeGreaterThan(0);
});
it('should remove duplicate endpoint when seamless is true', function ()
{
var pts = [{ x: 0, y: 0 }, { x: 5, y: 0 }, { x: 0, y: 0 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, false, true);
expect(zone.points.length).toBe(2);
});
it('should not remove endpoint when seamless is false', function ()
{
var pts = [{ x: 0, y: 0 }, { x: 5, y: 0 }, { x: 0, y: 0 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, false, false);
expect(zone.points.length).toBe(3);
});
it('should not remove endpoint when endpoints differ', function ()
{
var pts = [{ x: 0, y: 0 }, { x: 5, y: 0 }, { x: 10, y: 0 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, false, true);
expect(zone.points.length).toBe(3);
});
});
describe('updateSource', function ()
{
it('should return this for chaining', function ()
{
var source = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var zone = new EdgeZone(source, 2);
expect(zone.updateSource()).toBe(zone);
});
it('should refresh points from the source', function ()
{
var pts = [{ x: 0, y: 0 }, { x: 5, y: 0 }];
var source = {
callCount: 0,
getPoints: function ()
{
this.callCount++;
return pts.map(function (p) { return { x: p.x, y: p.y }; });
}
};
var zone = new EdgeZone(source, 2);
var callsBefore = source.callCount;
zone.updateSource();
expect(source.callCount).toBe(callsBefore + 1);
});
it('should update _length to match point count', function ()
{
var source = makeSource([{ x: 0, y: 0 }, { x: 5, y: 0 }, { x: 10, y: 0 }]);
var zone = new EdgeZone(source, 3);
expect(zone._length).toBe(zone.points.length);
});
it('should clamp counter when point count decreases', function ()
{
var pts = [{ x: 0, y: 0 }, { x: 5, y: 0 }, { x: 10, y: 0 }, { x: 15, y: 0 }];
var source = {
pts: pts,
getPoints: function ()
{
return this.pts.map(function (p) { return { x: p.x, y: p.y }; });
}
};
var zone = new EdgeZone(source, 4, undefined, false, false);
// Advance counter to index 3
zone.counter = 3;
// Now reduce the point list
source.pts = [{ x: 0, y: 0 }, { x: 5, y: 0 }];
zone.updateSource();
expect(zone.counter).toBeLessThanOrEqual(zone._length - 1);
});
it('should remove seamless duplicate after source refresh', function ()
{
var source = {
pts: [{ x: 0, y: 0 }, { x: 5, y: 0 }, { x: 0, y: 0 }],
getPoints: function ()
{
return this.pts.map(function (p) { return { x: p.x, y: p.y }; });
}
};
var zone = new EdgeZone(source, 3, undefined, false, true);
expect(zone.points.length).toBe(2);
});
});
describe('changeSource', function ()
{
it('should replace the source', function ()
{
var source1 = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var source2 = makeSource([{ x: 1, y: 1 }, { x: 2, y: 2 }]);
var zone = new EdgeZone(source1, 2);
zone.changeSource(source2);
expect(zone.source).toBe(source2);
});
it('should return this for chaining', function ()
{
var source1 = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var source2 = makeSource([{ x: 1, y: 1 }, { x: 2, y: 2 }]);
var zone = new EdgeZone(source1, 2);
expect(zone.changeSource(source2)).toBe(zone);
});
it('should update points from the new source', function ()
{
var source1 = makeSource([{ x: 0, y: 0 }, { x: 10, y: 0 }]);
var source2 = makeSource([{ x: 99, y: 88 }, { x: 77, y: 66 }]);
var zone = new EdgeZone(source1, 2);
zone.changeSource(source2);
expect(zone.points[0].x).toBe(99);
expect(zone.points[0].y).toBe(88);
});
});
describe('getPoint', function ()
{
it('should set particle x and y to the first point on first call', function ()
{
var pts = [{ x: 10, y: 20 }, { x: 30, y: 40 }, { x: 50, y: 60 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, false, false);
var particle = makeParticle();
zone.getPoint(particle);
expect(particle.x).toBe(10);
expect(particle.y).toBe(20);
});
it('should advance to the next point on each call', function ()
{
var pts = [{ x: 1, y: 1 }, { x: 2, y: 2 }, { x: 3, y: 3 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, false, false);
var particle = makeParticle();
zone.getPoint(particle);
expect(particle.x).toBe(1);
zone.getPoint(particle);
expect(particle.x).toBe(2);
zone.getPoint(particle);
expect(particle.x).toBe(3);
});
it('should wrap counter back to 0 when yoyo is false', function ()
{
var pts = [{ x: 1, y: 1 }, { x: 2, y: 2 }, { x: 3, y: 3 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, false, false);
var particle = makeParticle();
zone.getPoint(particle); // index 0
zone.getPoint(particle); // index 1
zone.getPoint(particle); // index 2
zone.getPoint(particle); // wraps to 0
expect(particle.x).toBe(1);
expect(particle.y).toBe(1);
});
it('should reverse direction at end when yoyo is true', function ()
{
// When counter reaches _length in forward direction, direction flips
// and counter is reset to _length-1 (repeating the last point once).
var pts = [{ x: 1, y: 0 }, { x: 2, y: 0 }, { x: 3, y: 0 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, true, false);
var particle = makeParticle();
zone.getPoint(particle); // forward: index 0 → x=1
zone.getPoint(particle); // forward: index 1 → x=2
zone.getPoint(particle); // forward: index 2 → x=3
// counter++ → 3 >= 3: direction flips to 1, counter = 2 → reads x=3
zone.getPoint(particle);
expect(particle.x).toBe(3);
// Now going backward: counter-- → 1 → x=2
zone.getPoint(particle);
expect(particle.x).toBe(2);
});
it('should reverse direction at start when yoyo is true', function ()
{
// When counter reaches -1 in reverse direction, direction flips
// and counter is reset to 0 (repeating the first point once).
var pts = [{ x: 10, y: 0 }, { x: 20, y: 0 }, { x: 30, y: 0 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, true, false);
var particle = makeParticle();
zone.getPoint(particle); // 0 → x=10
zone.getPoint(particle); // 1 → x=20
zone.getPoint(particle); // 2 → x=30
zone.getPoint(particle); // flip: dir=1, counter=2 → x=30
zone.getPoint(particle); // dir=1: counter-- → 1 → x=20
zone.getPoint(particle); // dir=1: counter-- → 0 → x=10
// counter-- → -1: flip dir=0, counter=0 → reads x=10
zone.getPoint(particle);
expect(particle.x).toBe(10);
// Now going forward again: counter++ → 1 → x=20
zone.getPoint(particle);
expect(particle.x).toBe(20);
});
it('should cycle all points correctly without yoyo over multiple loops', function ()
{
var pts = [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 3, undefined, false, false);
var particle = makeParticle();
var xs = [];
for (var i = 0; i < 9; i++)
{
zone.getPoint(particle);
xs.push(particle.x);
}
expect(xs).toEqual([0, 1, 2, 0, 1, 2, 0, 1, 2]);
});
it('should handle a single-point source', function ()
{
var source = makeSource([{ x: 7, y: 13 }]);
var zone = new EdgeZone(source, 1, undefined, false, false);
var particle = makeParticle();
zone.getPoint(particle);
expect(particle.x).toBe(7);
expect(particle.y).toBe(13);
zone.getPoint(particle);
expect(particle.x).toBe(7);
expect(particle.y).toBe(13);
});
it('should not mutate particle when points array is empty', function ()
{
var source = { getPoints: function () { return []; } };
var zone = new EdgeZone(source, 0, undefined, false, false);
var particle = { x: 42, y: 99 };
zone.getPoint(particle);
expect(particle.x).toBe(42);
expect(particle.y).toBe(99);
});
it('should produce a yoyo sequence over a full back-and-forth cycle', function ()
{
// With 4 points and yoyo=true, when forward traversal reaches the last
// point the direction flips but counter stays at _length-1, so that
// last point is emitted again before moving backward.
var pts = [{ x: 0, y: 0 }, { x: 1, y: 0 }, { x: 2, y: 0 }, { x: 3, y: 0 }];
var source = makeSource(pts);
var zone = new EdgeZone(source, 4, undefined, true, false);
var particle = makeParticle();
var xs = [];
for (var i = 0; i < 6; i++)
{
zone.getPoint(particle);
xs.push(particle.x);
}
// 0, 1, 2, 3 (forward), then flip: 3 (repeated), 2 (backward)
expect(xs).toEqual([0, 1, 2, 3, 3, 2]);
});
});
});