Path: blob/main/public/games/files/garbage-collector/js/entities/physics-entity.js
1036 views
/*jshint camelcase: false*/1/*globals define*/2define([3'box2d',4'entities/entity',5'geometry/geometry-factory',6'utils',7'utils-box2d',8'world'9], function( Box2D, Entity, GeometryFactory, Utils, Box2DUtils, world ) {10'use strict';1112var Vec2 = Box2D.Common.Math.b2Vec2;13var Body = Box2D.Dynamics.b2Body;14var BodyDef = Box2D.Dynamics.b2BodyDef;15var FixtureDef = Box2D.Dynamics.b2FixtureDef;1617var shapeClasses = {18circle: Box2D.Collision.Shapes.b2CircleShape,19polygon: Box2D.Collision.Shapes.b2PolygonShape20};2122var defaultShape = 'circle';2324var bodyTypes = {25'static': Body.b2_staticBody,26'dynamic': Body.b2_dynamicBody,27'kinematic': Body.b2_kinematicBody28};2930var setAs = {31array: 'SetAsArray',32box: 'SetAsBox',33edge: 'SetAsEdge',34orientedBox: 'SetAsOrientedBox',35vector: 'SetAsVector'36};3738var set = Utils.set;3940function PhysicsEntity( options ) {41if ( !options ) {42return;43}4445this.fixture = null;46this.initialize( options );4748// This tautology stops the Entity constructor from changing the position/angle.49var angle = this.angle;50Entity.call( this, this.x, this.y );51this.angle = -angle;5253// Add any shapes.54if ( options.shapes ) {55this.shapes = this.shapes.concat( options.shapes.map(function( shapeData ) {56return GeometryFactory.create( JSON.stringify( shapeData ) );57}));58}59}6061PhysicsEntity.prototype = new Entity();62PhysicsEntity.prototype.constructor = PhysicsEntity;6364PhysicsEntity.prototype.initialize = function( options ) {65options = options || {};6667var fixDef = new FixtureDef();68set( fixDef, options.fixture );69this.fixtureShape( fixDef, options );7071var bodyDef = new BodyDef();72set( bodyDef, options.body );73// Calling set() with a options.body.type will stick a74// 'static'/'dynamic'/'kinematic' string in bodyDef.type, so we need to75// convert it to the correct Box2D flag.76if ( options.body && typeof bodyDef.type === 'string' ) {77bodyDef.type = bodyTypes[ bodyDef.type ] || Body.b2_staticBody;78}7980this.fixture = world.CreateBody( bodyDef ).CreateFixture( fixDef );81this.body.SetUserData( this );82};8384/**85* Creates a shape of the class given by the string shape called with a86* shapeOptions array.87*88* Possible values for shape are:89* - circle (default)90* - polygon91*/92PhysicsEntity.prototype.fixtureShape = function( fixDef, options ) {93var shape = typeof options.shape !== 'undefined' ? options.shape : defaultShape;9495var Shape = shapeClasses[ shape ];96if ( typeof Shape === 'undefined' ) {97Shape = shapeClasses[ defaultShape ];98}99100fixDef.shape = new Shape();101102// Set up shape properties.103if ( shape === 'circle' ) {104if ( typeof options.radius !== 'undefined' ) {105fixDef.shape.SetRadius( options.radius );106}107108return;109}110111// Handle SetAs functions for each possible type.112var type = options.type,113data = options.data;114115if ( shape !== 'polygon' ||116typeof type === 'undefined' ||117typeof data === 'undefined' ) {118return;119}120121var setAsFunction = setAs[ type ];122if ( typeof setAsFunction === 'undefined' ) {123return;124}125126setAsFunction = fixDef.shape[ setAsFunction ];127128// Data is an array.129if ( type === 'array' ||130type === 'vector' ) {131// Convert flat array of numbers to a Vec2 array.132var vector = Box2DUtils.b2Vec2Array( data );133setAsFunction.call( fixDef.shape, vector, vector.length );134}135136// Data is an object:137// - hx:Number138// - hy:Number139else if ( type === 'box' ) {140setAsFunction.call( fixDef.shape, data.hx, data.hy );141}142143// Data is an object:144// - hx:Number145// - hy:Number146// - center:Vec2147// - angle:Number148else if ( type === 'orientedbox' ) {149var center;150if ( typeof data.center !== 'undefined' ) {151center = new Vec2( data.center.x, data.center.y );152} else {153center = new Vec2( 0, 0 );154}155156setAsFunction.call( fixDef.shape, data.hx, data.hy, center, data.angle );157}158159// Data is an array of 4 numbers.160else if ( type === 'edge' ) {161setAsFunction.call(162fixDef.shape,163new Vec2( data[0], data[1] ),164new Vec2( data[2], data[3] )165);166}167};168169PhysicsEntity.prototype.accelerate = function( x, y ) {170this.body.ApplyImpulse(171new Vec2( x, y ),172this.worldCenter173);174};175176PhysicsEntity.prototype.update = function( dt ) {177Entity.prototype.update.call( this, dt );178this.vx = Utils.roundNearZero( this.vx );179this.vy = Utils.roundNearZero( this.vy );180};181182PhysicsEntity.prototype.aabb = function() {183var aabb = this.fixture.GetAABB();184185return {186xmin: aabb.lowerBound.x,187ymin: aabb.lowerBound.y,188xmax: aabb.upperBound.x,189ymax: aabb.upperBound.y190};191};192193Object.defineProperty( PhysicsEntity.prototype, 'body', {194get: function() {195return this.fixture.GetBody();196}197});198199Object.defineProperty( PhysicsEntity.prototype, 'material', {200get: function() {201return this.fixture.GetFilterData().categoryBits;202},203204set: function( material ) {205var filterData = this.fixture.GetFilterData();206filterData.categoryBits = material;207this.fixture.SetFilterData( filterData );208}209});210211Object.defineProperty( PhysicsEntity.prototype, 'position', {212get: function() {213return this.body.GetPosition();214}215});216217Object.defineProperty( PhysicsEntity.prototype, 'worldCenter', {218get: function() {219return this.body.GetWorldCenter();220}221});222223Object.defineProperty( PhysicsEntity.prototype, 'x', {224enumerable: true,225226get: function() {227return this.position.x;228},229230set: function( x ) {231this.position.x = x || 0;232this.worldCenter.x = x || 0;233}234});235236Object.defineProperty( PhysicsEntity.prototype, 'y', {237enumerable: true,238239get: function() {240return this.position.y;241},242243set: function( y ) {244this.position.y = y || 0;245this.worldCenter.y = y || 0;246}247});248249Object.defineProperty( PhysicsEntity.prototype, 'angle', {250enumerable: true,251252get: function() {253return -this.body.GetAngle();254},255256set: function( angle ) {257this.body.SetAngle( -angle || 0 );258}259});260261Object.defineProperty( PhysicsEntity.prototype, 'velocity', {262get: function() {263return this.body.GetLinearVelocity();264},265266set: function( velocity ) {267this.body.SetLinearVelocity( velocity );268}269});270271Object.defineProperty( PhysicsEntity.prototype, 'vx', {272get: function() {273return this.velocity.x;274},275276set: function( vx ) {277this.velocity.x = vx || 0;278}279});280281Object.defineProperty( PhysicsEntity.prototype, 'vy', {282get: function() {283return this.velocity.y;284},285286set: function( vy ) {287this.velocity.y = vy || 0;288}289});290291Object.defineProperty( PhysicsEntity.prototype, 'va', {292get: function() {293return this.body.GetAngularVelocity();294},295296set: function( va ) {297this.body.SetAngularVelocity( va || 0 );298}299});300301return PhysicsEntity;302});303304305