Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
FogNetwork
GitHub Repository: FogNetwork/Tsunami
Path: blob/main/public/games/files/garbage-collector/js/entities/physics-entity.js
1036 views
1
/*jshint camelcase: false*/
2
/*globals define*/
3
define([
4
'box2d',
5
'entities/entity',
6
'geometry/geometry-factory',
7
'utils',
8
'utils-box2d',
9
'world'
10
], function( Box2D, Entity, GeometryFactory, Utils, Box2DUtils, world ) {
11
'use strict';
12
13
var Vec2 = Box2D.Common.Math.b2Vec2;
14
var Body = Box2D.Dynamics.b2Body;
15
var BodyDef = Box2D.Dynamics.b2BodyDef;
16
var FixtureDef = Box2D.Dynamics.b2FixtureDef;
17
18
var shapeClasses = {
19
circle: Box2D.Collision.Shapes.b2CircleShape,
20
polygon: Box2D.Collision.Shapes.b2PolygonShape
21
};
22
23
var defaultShape = 'circle';
24
25
var bodyTypes = {
26
'static': Body.b2_staticBody,
27
'dynamic': Body.b2_dynamicBody,
28
'kinematic': Body.b2_kinematicBody
29
};
30
31
var setAs = {
32
array: 'SetAsArray',
33
box: 'SetAsBox',
34
edge: 'SetAsEdge',
35
orientedBox: 'SetAsOrientedBox',
36
vector: 'SetAsVector'
37
};
38
39
var set = Utils.set;
40
41
function PhysicsEntity( options ) {
42
if ( !options ) {
43
return;
44
}
45
46
this.fixture = null;
47
this.initialize( options );
48
49
// This tautology stops the Entity constructor from changing the position/angle.
50
var angle = this.angle;
51
Entity.call( this, this.x, this.y );
52
this.angle = -angle;
53
54
// Add any shapes.
55
if ( options.shapes ) {
56
this.shapes = this.shapes.concat( options.shapes.map(function( shapeData ) {
57
return GeometryFactory.create( JSON.stringify( shapeData ) );
58
}));
59
}
60
}
61
62
PhysicsEntity.prototype = new Entity();
63
PhysicsEntity.prototype.constructor = PhysicsEntity;
64
65
PhysicsEntity.prototype.initialize = function( options ) {
66
options = options || {};
67
68
var fixDef = new FixtureDef();
69
set( fixDef, options.fixture );
70
this.fixtureShape( fixDef, options );
71
72
var bodyDef = new BodyDef();
73
set( bodyDef, options.body );
74
// Calling set() with a options.body.type will stick a
75
// 'static'/'dynamic'/'kinematic' string in bodyDef.type, so we need to
76
// convert it to the correct Box2D flag.
77
if ( options.body && typeof bodyDef.type === 'string' ) {
78
bodyDef.type = bodyTypes[ bodyDef.type ] || Body.b2_staticBody;
79
}
80
81
this.fixture = world.CreateBody( bodyDef ).CreateFixture( fixDef );
82
this.body.SetUserData( this );
83
};
84
85
/**
86
* Creates a shape of the class given by the string shape called with a
87
* shapeOptions array.
88
*
89
* Possible values for shape are:
90
* - circle (default)
91
* - polygon
92
*/
93
PhysicsEntity.prototype.fixtureShape = function( fixDef, options ) {
94
var shape = typeof options.shape !== 'undefined' ? options.shape : defaultShape;
95
96
var Shape = shapeClasses[ shape ];
97
if ( typeof Shape === 'undefined' ) {
98
Shape = shapeClasses[ defaultShape ];
99
}
100
101
fixDef.shape = new Shape();
102
103
// Set up shape properties.
104
if ( shape === 'circle' ) {
105
if ( typeof options.radius !== 'undefined' ) {
106
fixDef.shape.SetRadius( options.radius );
107
}
108
109
return;
110
}
111
112
// Handle SetAs functions for each possible type.
113
var type = options.type,
114
data = options.data;
115
116
if ( shape !== 'polygon' ||
117
typeof type === 'undefined' ||
118
typeof data === 'undefined' ) {
119
return;
120
}
121
122
var setAsFunction = setAs[ type ];
123
if ( typeof setAsFunction === 'undefined' ) {
124
return;
125
}
126
127
setAsFunction = fixDef.shape[ setAsFunction ];
128
129
// Data is an array.
130
if ( type === 'array' ||
131
type === 'vector' ) {
132
// Convert flat array of numbers to a Vec2 array.
133
var vector = Box2DUtils.b2Vec2Array( data );
134
setAsFunction.call( fixDef.shape, vector, vector.length );
135
}
136
137
// Data is an object:
138
// - hx:Number
139
// - hy:Number
140
else if ( type === 'box' ) {
141
setAsFunction.call( fixDef.shape, data.hx, data.hy );
142
}
143
144
// Data is an object:
145
// - hx:Number
146
// - hy:Number
147
// - center:Vec2
148
// - angle:Number
149
else if ( type === 'orientedbox' ) {
150
var center;
151
if ( typeof data.center !== 'undefined' ) {
152
center = new Vec2( data.center.x, data.center.y );
153
} else {
154
center = new Vec2( 0, 0 );
155
}
156
157
setAsFunction.call( fixDef.shape, data.hx, data.hy, center, data.angle );
158
}
159
160
// Data is an array of 4 numbers.
161
else if ( type === 'edge' ) {
162
setAsFunction.call(
163
fixDef.shape,
164
new Vec2( data[0], data[1] ),
165
new Vec2( data[2], data[3] )
166
);
167
}
168
};
169
170
PhysicsEntity.prototype.accelerate = function( x, y ) {
171
this.body.ApplyImpulse(
172
new Vec2( x, y ),
173
this.worldCenter
174
);
175
};
176
177
PhysicsEntity.prototype.update = function( dt ) {
178
Entity.prototype.update.call( this, dt );
179
this.vx = Utils.roundNearZero( this.vx );
180
this.vy = Utils.roundNearZero( this.vy );
181
};
182
183
PhysicsEntity.prototype.aabb = function() {
184
var aabb = this.fixture.GetAABB();
185
186
return {
187
xmin: aabb.lowerBound.x,
188
ymin: aabb.lowerBound.y,
189
xmax: aabb.upperBound.x,
190
ymax: aabb.upperBound.y
191
};
192
};
193
194
Object.defineProperty( PhysicsEntity.prototype, 'body', {
195
get: function() {
196
return this.fixture.GetBody();
197
}
198
});
199
200
Object.defineProperty( PhysicsEntity.prototype, 'material', {
201
get: function() {
202
return this.fixture.GetFilterData().categoryBits;
203
},
204
205
set: function( material ) {
206
var filterData = this.fixture.GetFilterData();
207
filterData.categoryBits = material;
208
this.fixture.SetFilterData( filterData );
209
}
210
});
211
212
Object.defineProperty( PhysicsEntity.prototype, 'position', {
213
get: function() {
214
return this.body.GetPosition();
215
}
216
});
217
218
Object.defineProperty( PhysicsEntity.prototype, 'worldCenter', {
219
get: function() {
220
return this.body.GetWorldCenter();
221
}
222
});
223
224
Object.defineProperty( PhysicsEntity.prototype, 'x', {
225
enumerable: true,
226
227
get: function() {
228
return this.position.x;
229
},
230
231
set: function( x ) {
232
this.position.x = x || 0;
233
this.worldCenter.x = x || 0;
234
}
235
});
236
237
Object.defineProperty( PhysicsEntity.prototype, 'y', {
238
enumerable: true,
239
240
get: function() {
241
return this.position.y;
242
},
243
244
set: function( y ) {
245
this.position.y = y || 0;
246
this.worldCenter.y = y || 0;
247
}
248
});
249
250
Object.defineProperty( PhysicsEntity.prototype, 'angle', {
251
enumerable: true,
252
253
get: function() {
254
return -this.body.GetAngle();
255
},
256
257
set: function( angle ) {
258
this.body.SetAngle( -angle || 0 );
259
}
260
});
261
262
Object.defineProperty( PhysicsEntity.prototype, 'velocity', {
263
get: function() {
264
return this.body.GetLinearVelocity();
265
},
266
267
set: function( velocity ) {
268
this.body.SetLinearVelocity( velocity );
269
}
270
});
271
272
Object.defineProperty( PhysicsEntity.prototype, 'vx', {
273
get: function() {
274
return this.velocity.x;
275
},
276
277
set: function( vx ) {
278
this.velocity.x = vx || 0;
279
}
280
});
281
282
Object.defineProperty( PhysicsEntity.prototype, 'vy', {
283
get: function() {
284
return this.velocity.y;
285
},
286
287
set: function( vy ) {
288
this.velocity.y = vy || 0;
289
}
290
});
291
292
Object.defineProperty( PhysicsEntity.prototype, 'va', {
293
get: function() {
294
return this.body.GetAngularVelocity();
295
},
296
297
set: function( va ) {
298
this.body.SetAngularVelocity( va || 0 );
299
}
300
});
301
302
return PhysicsEntity;
303
});
304
305