UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

982 lines (788 loc) 27.8 kB
var Body = require('../../../src/physics/arcade/Body'); function createMockWorld () { return { defaults: { debugShowBody: true, debugShowVelocity: true, bodyDebugColor: 0xff0000, velocityDebugColor: 0x00ff00 }, bounds: { x: 0, y: 0, width: 800, height: 600, right: 800, bottom: 600 }, checkCollision: { left: true, right: true, up: true, down: true }, pendingDestroy: { add: function () {} } }; } function createMockGameObject (overrides) { var obj = { x: 0, y: 0, angle: 0, rotation: 0, scaleX: 1, scaleY: 1, displayOriginX: 0, displayOriginY: 0, displayWidth: 64, displayHeight: 64 }; if (overrides) { for (var key in overrides) { obj[key] = overrides[key]; } } return obj; } describe('Body', function () { var world; beforeEach(function () { world = createMockWorld(); }); describe('constructor (no game object)', function () { it('should create a Body with default values when no game object is given', function () { var body = new Body(world); expect(body.isBody).toBe(true); expect(body.enable).toBe(true); expect(body.isCircle).toBe(false); expect(body.radius).toBe(0); expect(body.width).toBe(64); expect(body.height).toBe(64); expect(body.halfWidth).toBe(32); expect(body.halfHeight).toBe(32); expect(body.mass).toBe(1); expect(body.immovable).toBe(false); expect(body.moves).toBe(true); expect(body.allowGravity).toBe(true); expect(body.allowDrag).toBe(true); expect(body.allowRotation).toBe(true); expect(body.maxSpeed).toBe(-1); expect(body.useDamping).toBe(false); expect(body.directControl).toBe(false); expect(body.collideWorldBounds).toBe(false); expect(body.worldBounce).toBeNull(); expect(body.gameObject).toBeUndefined(); }); it('should initialise velocity, acceleration, drag, and gravity as zero vectors', function () { var body = new Body(world); expect(body.velocity.x).toBe(0); expect(body.velocity.y).toBe(0); expect(body.acceleration.x).toBe(0); expect(body.acceleration.y).toBe(0); expect(body.drag.x).toBe(0); expect(body.drag.y).toBe(0); expect(body.gravity.x).toBe(0); expect(body.gravity.y).toBe(0); }); it('should set maxVelocity to (10000, 10000) by default', function () { var body = new Body(world); expect(body.maxVelocity.x).toBe(10000); expect(body.maxVelocity.y).toBe(10000); }); it('should set friction to (1, 0) by default', function () { var body = new Body(world); expect(body.friction.x).toBe(1); expect(body.friction.y).toBe(0); }); it('should set slideFactor to (1, 1) by default', function () { var body = new Body(world); expect(body.slideFactor.x).toBe(1); expect(body.slideFactor.y).toBe(1); }); }); describe('constructor (with game object)', function () { it('should use displayWidth and displayHeight from the game object', function () { var go = createMockGameObject({ displayWidth: 32, displayHeight: 48 }); var body = new Body(world, go); expect(body.width).toBe(32); expect(body.height).toBe(48); expect(body.halfWidth).toBe(16); expect(body.halfHeight).toBe(24); }); it('should store the game object reference', function () { var go = createMockGameObject(); var body = new Body(world, go); expect(body.gameObject).toBe(go); }); it('should set position from game object x/y minus scaled origin', function () { var go = createMockGameObject({ x: 100, y: 200, scaleX: 1, scaleY: 1, displayOriginX: 0, displayOriginY: 0 }); var body = new Body(world, go); expect(body.position.x).toBe(100); expect(body.position.y).toBe(200); }); }); describe('updateCenter', function () { it('should set center to position plus half-dimensions', function () { var body = new Body(world); body.position.set(100, 200); body.halfWidth = 32; body.halfHeight = 32; body.updateCenter(); expect(body.center.x).toBe(132); expect(body.center.y).toBe(232); }); }); describe('setOffset', function () { it('should set both x and y offset', function () { var body = new Body(world); var result = body.setOffset(10, 20); expect(body.offset.x).toBe(10); expect(body.offset.y).toBe(20); expect(result).toBe(body); }); it('should use x for y when y is omitted', function () { var body = new Body(world); body.setOffset(15); expect(body.offset.x).toBe(15); expect(body.offset.y).toBe(15); }); }); describe('setSize', function () { it('should set source width/height and derived dimensions', function () { var body = new Body(world); body.setSize(40, 80); expect(body.sourceWidth).toBe(40); expect(body.sourceHeight).toBe(80); expect(body.width).toBe(40); expect(body.height).toBe(80); expect(body.halfWidth).toBe(20); expect(body.halfHeight).toBe(40); }); it('should clear circle mode', function () { var body = new Body(world); body.isCircle = true; body.radius = 20; body.setSize(40, 40); expect(body.isCircle).toBe(false); expect(body.radius).toBe(0); }); it('should return this', function () { var body = new Body(world); var result = body.setSize(32, 32); expect(result).toBe(body); }); }); describe('setCircle', function () { it('should enable circle mode with the given radius', function () { var body = new Body(world); body.setCircle(20); expect(body.isCircle).toBe(true); expect(body.radius).toBe(20); expect(body.sourceWidth).toBe(40); expect(body.sourceHeight).toBe(40); expect(body.width).toBe(40); expect(body.height).toBe(40); expect(body.halfWidth).toBe(20); expect(body.halfHeight).toBe(20); }); it('should set offset when provided', function () { var body = new Body(world); body.setCircle(20, 5, 10); expect(body.offset.x).toBe(5); expect(body.offset.y).toBe(10); }); it('should disable circle mode when radius is zero or negative', function () { var body = new Body(world); body.setCircle(20); body.setCircle(0); expect(body.isCircle).toBe(false); }); it('should return this', function () { var body = new Body(world); var result = body.setCircle(10); expect(result).toBe(body); }); }); describe('stop', function () { it('should zero velocity, acceleration, speed, and angular values', function () { var body = new Body(world); body.velocity.set(100, 200); body.acceleration.set(50, 50); body.speed = 223; body.angularVelocity = 45; body.angularAcceleration = 10; body.stop(); expect(body.velocity.x).toBe(0); expect(body.velocity.y).toBe(0); expect(body.acceleration.x).toBe(0); expect(body.acceleration.y).toBe(0); expect(body.speed).toBe(0); expect(body.angularVelocity).toBe(0); expect(body.angularAcceleration).toBe(0); }); it('should return this', function () { var body = new Body(world); var result = body.stop(); expect(result).toBe(body); }); }); describe('getBounds', function () { it('should populate the given object with x, y, right, bottom', function () { var body = new Body(world); body.position.set(10, 20); body.width = 50; body.height = 80; var bounds = {}; var result = body.getBounds(bounds); expect(bounds.x).toBe(10); expect(bounds.y).toBe(20); expect(bounds.right).toBe(60); expect(bounds.bottom).toBe(100); expect(result).toBe(bounds); }); }); describe('hitTest', function () { it('should return true for a point inside a rectangular body', function () { var body = new Body(world); body.position.set(0, 0); body.width = 100; body.height = 100; expect(body.hitTest(50, 50)).toBe(true); }); it('should return false for a point outside a rectangular body', function () { var body = new Body(world); body.position.set(0, 0); body.width = 100; body.height = 100; expect(body.hitTest(150, 50)).toBe(false); }); it('should return true for a point inside a circular body', function () { var body = new Body(world); body.setCircle(50); body.position.set(0, 0); body.center.set(50, 50); expect(body.hitTest(50, 50)).toBe(true); }); it('should return false for a point outside a circular body', function () { var body = new Body(world); body.setCircle(50); body.position.set(0, 0); body.center.set(50, 50); expect(body.hitTest(150, 150)).toBe(false); }); }); describe('onFloor / onCeiling / onWall', function () { it('onFloor should return true when blocked.down is true', function () { var body = new Body(world); body.blocked.down = true; expect(body.onFloor()).toBe(true); }); it('onCeiling should return true when blocked.up is true', function () { var body = new Body(world); body.blocked.up = true; expect(body.onCeiling()).toBe(true); }); it('onWall should return true when blocked.left is true', function () { var body = new Body(world); body.blocked.left = true; expect(body.onWall()).toBe(true); }); it('onWall should return true when blocked.right is true', function () { var body = new Body(world); body.blocked.right = true; expect(body.onWall()).toBe(true); }); it('onFloor should return false when not blocked', function () { var body = new Body(world); expect(body.onFloor()).toBe(false); }); }); describe('deltaAbsX / deltaAbsY', function () { it('should return the absolute value of _dx', function () { var body = new Body(world); body._dx = -50; expect(body.deltaAbsX()).toBe(50); }); it('should return the absolute value of _dy', function () { var body = new Body(world); body._dy = -30; expect(body.deltaAbsY()).toBe(30); }); it('should return zero when _dx is zero', function () { var body = new Body(world); body._dx = 0; expect(body.deltaAbsX()).toBeCloseTo(0); }); }); describe('deltaX / deltaY / deltaXFinal / deltaYFinal / deltaZ', function () { it('deltaX should return _dx', function () { var body = new Body(world); body._dx = 7; expect(body.deltaX()).toBe(7); }); it('deltaY should return _dy', function () { var body = new Body(world); body._dy = -3; expect(body.deltaY()).toBe(-3); }); it('deltaXFinal should return _tx', function () { var body = new Body(world); body._tx = 15; expect(body.deltaXFinal()).toBe(15); }); it('deltaYFinal should return _ty', function () { var body = new Body(world); body._ty = 25; expect(body.deltaYFinal()).toBe(25); }); it('deltaZ should return the difference between rotation and preRotation', function () { var body = new Body(world); body.rotation = 90; body.preRotation = 45; expect(body.deltaZ()).toBe(45); }); }); describe('setVelocity', function () { it('should set velocity x and y', function () { var body = new Body(world); body.setVelocity(100, 200); expect(body.velocity.x).toBe(100); expect(body.velocity.y).toBe(200); }); it('should update speed to the magnitude of velocity', function () { var body = new Body(world); body.setVelocity(3, 4); expect(body.speed).toBe(5); }); it('should use x for y when y is omitted', function () { var body = new Body(world); body.setVelocity(50); expect(body.velocity.x).toBe(50); expect(body.velocity.y).toBe(50); }); it('should return this', function () { var body = new Body(world); var result = body.setVelocity(10, 10); expect(result).toBe(body); }); it('setVelocityX should only change x and update speed', function () { var body = new Body(world); body.setVelocity(100, 100); body.setVelocityX(50); expect(body.velocity.x).toBe(50); expect(body.velocity.y).toBe(100); }); it('setVelocityY should only change y and update speed', function () { var body = new Body(world); body.setVelocity(100, 100); body.setVelocityY(50); expect(body.velocity.x).toBe(100); expect(body.velocity.y).toBe(50); }); }); describe('setMaxVelocity / setMaxSpeed', function () { it('setMaxVelocity should set both components', function () { var body = new Body(world); body.setMaxVelocity(500, 300); expect(body.maxVelocity.x).toBe(500); expect(body.maxVelocity.y).toBe(300); }); it('setMaxSpeed should set maxSpeed', function () { var body = new Body(world); body.setMaxSpeed(999); expect(body.maxSpeed).toBe(999); }); }); describe('setBounce', function () { it('should set bounce x and y', function () { var body = new Body(world); body.setBounce(0.5, 0.8); expect(body.bounce.x).toBe(0.5); expect(body.bounce.y).toBe(0.8); }); it('setBounceX should set only x', function () { var body = new Body(world); body.setBounceX(0.6); expect(body.bounce.x).toBe(0.6); }); it('setBounceY should set only y', function () { var body = new Body(world); body.setBounceY(0.4); expect(body.bounce.y).toBe(0.4); }); }); describe('setCollideWorldBounds', function () { it('should enable collideWorldBounds', function () { var body = new Body(world); body.setCollideWorldBounds(true); expect(body.collideWorldBounds).toBe(true); }); it('should default to true when no argument given', function () { var body = new Body(world); body.setCollideWorldBounds(); expect(body.collideWorldBounds).toBe(true); }); it('should create worldBounce vector when bounce values are provided', function () { var body = new Body(world); body.setCollideWorldBounds(true, 0.5, 0.8); expect(body.worldBounce).not.toBeNull(); expect(body.worldBounce.x).toBe(0.5); expect(body.worldBounce.y).toBe(0.8); }); it('should set onWorldBounds when provided', function () { var body = new Body(world); body.setCollideWorldBounds(true, undefined, undefined, true); expect(body.onWorldBounds).toBe(true); }); }); describe('setAcceleration / setGravity / setDrag', function () { it('setAcceleration should set both components', function () { var body = new Body(world); body.setAcceleration(200, 300); expect(body.acceleration.x).toBe(200); expect(body.acceleration.y).toBe(300); }); it('setGravity should set both components', function () { var body = new Body(world); body.setGravity(0, 980); expect(body.gravity.x).toBe(0); expect(body.gravity.y).toBe(980); }); it('setDrag should set both components', function () { var body = new Body(world); body.setDrag(100, 50); expect(body.drag.x).toBe(100); expect(body.drag.y).toBe(50); }); it('setDamping should set useDamping', function () { var body = new Body(world); body.setDamping(true); expect(body.useDamping).toBe(true); }); }); describe('setMass / setImmovable / setEnable', function () { it('setMass should update mass', function () { var body = new Body(world); body.setMass(5); expect(body.mass).toBe(5); }); it('setImmovable should set immovable to true by default', function () { var body = new Body(world); body.setImmovable(); expect(body.immovable).toBe(true); }); it('setImmovable should accept false', function () { var body = new Body(world); body.setImmovable(false); expect(body.immovable).toBe(false); }); it('setEnable should set enable to true by default', function () { var body = new Body(world); body.enable = false; body.setEnable(); expect(body.enable).toBe(true); }); it('setEnable should accept false', function () { var body = new Body(world); body.setEnable(false); expect(body.enable).toBe(false); }); }); describe('setAllowDrag / setAllowGravity / setAllowRotation', function () { it('setAllowDrag should default to true', function () { var body = new Body(world); body.allowDrag = false; body.setAllowDrag(); expect(body.allowDrag).toBe(true); }); it('setAllowGravity should default to true', function () { var body = new Body(world); body.allowGravity = false; body.setAllowGravity(); expect(body.allowGravity).toBe(true); }); it('setAllowRotation should accept false', function () { var body = new Body(world); body.setAllowRotation(false); expect(body.allowRotation).toBe(false); }); }); describe('setSlideFactor', function () { it('should set both slide factor components', function () { var body = new Body(world); body.setSlideFactor(0.5, 0.25); expect(body.slideFactor.x).toBe(0.5); expect(body.slideFactor.y).toBe(0.25); }); }); describe('setDirectControl', function () { it('should default to true', function () { var body = new Body(world); body.setDirectControl(); expect(body.directControl).toBe(true); }); it('should accept false', function () { var body = new Body(world); body.setDirectControl(false); expect(body.directControl).toBe(false); }); }); describe('resetFlags', function () { it('should reset overlapX, overlapY, overlapR, and embedded', function () { var body = new Body(world); body.overlapX = 10; body.overlapY = 20; body.overlapR = 5; body.embedded = true; body.resetFlags(); expect(body.overlapX).toBe(0); expect(body.overlapY).toBe(0); expect(body.overlapR).toBe(0); expect(body.embedded).toBe(false); }); it('should copy touching to wasTouching by default', function () { var body = new Body(world); body.touching.down = true; body.touching.none = false; body.resetFlags(false); expect(body.wasTouching.down).toBe(true); expect(body.wasTouching.none).toBe(false); }); it('should reset wasTouching to defaults when clear is true', function () { var body = new Body(world); body.touching.down = true; body.resetFlags(true); expect(body.wasTouching.none).toBe(true); expect(body.wasTouching.down).toBe(false); }); }); describe('willDrawDebug', function () { it('should return true when debugShowBody is true', function () { var body = new Body(world); body.debugShowBody = true; body.debugShowVelocity = false; expect(body.willDrawDebug()).toBe(true); }); it('should return true when debugShowVelocity is true', function () { var body = new Body(world); body.debugShowBody = false; body.debugShowVelocity = true; expect(body.willDrawDebug()).toBe(true); }); it('should return false when both are false', function () { var body = new Body(world); body.debugShowBody = false; body.debugShowVelocity = false; expect(body.willDrawDebug()).toBe(false); }); }); describe('setBoundsRectangle', function () { it('should set a custom bounds rectangle', function () { var body = new Body(world); var rect = { x: 10, y: 10, width: 400, height: 300, right: 410, bottom: 310 }; body.setBoundsRectangle(rect); expect(body.customBoundsRectangle).toBe(rect); }); it('should revert to world bounds when null is passed', function () { var body = new Body(world); body.setBoundsRectangle(null); expect(body.customBoundsRectangle).toBe(world.bounds); }); }); describe('destroy', function () { it('should set enable to false and add to pendingDestroy', function () { var added = []; var mockW = createMockWorld(); mockW.pendingDestroy = { add: function (b) { added.push(b); } }; var body = new Body(mockW); body.enable = true; body.destroy(); expect(body.enable).toBe(false); expect(added.length).toBe(1); expect(added[0]).toBe(body); }); }); describe('processX / processY', function () { it('processX should move x position and update center', function () { var body = new Body(world); body.position.set(100, 100); body.halfWidth = 32; body.halfHeight = 32; body.processX(10, null, false, false); expect(body.x).toBe(110); expect(body.center.x).toBe(142); }); it('processX should set velocity.x scaled by slideFactor.x', function () { var body = new Body(world); body.slideFactor.x = 0.5; body.processX(0, 100, false, false); expect(body.velocity.x).toBe(50); }); it('processX should set blocked.left when left is true', function () { var body = new Body(world); body.processX(0, null, true, false); expect(body.blocked.left).toBe(true); expect(body.blocked.none).toBe(false); }); it('processX should set blocked.right when right is true', function () { var body = new Body(world); body.processX(0, null, false, true); expect(body.blocked.right).toBe(true); expect(body.blocked.none).toBe(false); }); it('processY should move y position and update center', function () { var body = new Body(world); body.position.set(100, 100); body.halfWidth = 32; body.halfHeight = 32; body.processY(15, null, false, false); expect(body.y).toBe(115); expect(body.center.y).toBe(147); }); it('processY should set velocity.y scaled by slideFactor.y', function () { var body = new Body(world); body.slideFactor.y = 0.25; body.processY(0, 200, false, false); expect(body.velocity.y).toBe(50); }); it('processY should set blocked.down when down is true', function () { var body = new Body(world); body.processY(0, null, false, true); expect(body.blocked.down).toBe(true); expect(body.blocked.none).toBe(false); }); }); describe('x / y / left / right / top / bottom properties', function () { it('x getter should return position.x', function () { var body = new Body(world); body.position.x = 42; expect(body.x).toBe(42); }); it('x setter should update position.x', function () { var body = new Body(world); body.x = 99; expect(body.position.x).toBe(99); }); it('right should equal x plus width', function () { var body = new Body(world); body.position.x = 50; body.width = 64; expect(body.right).toBe(114); }); it('bottom should equal y plus height', function () { var body = new Body(world); body.position.y = 30; body.height = 64; expect(body.bottom).toBe(94); }); }); });