Menu

[r2402]: / trunk / FrankEngine / Source / Objects / gameObject.h  Maximize  Restore  History

Download this file

657 lines (528 with data), 26.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
////////////////////////////////////////////////////////////////////////////////////////
/*
Game Object
Copyright 2013 Frank Force - http://www.frankforce.com
- 2d object in the x/y plain
- automatically added to world group by default when constructed
- automatically deleted during garbage collection phase after destroy is called
- may have a physics object
- may have a parents or multiple children
- has a unique handle
- can't be copied
*/
////////////////////////////////////////////////////////////////////////////////////////
#pragma once
#include "../objects/gameObjectManager.h"
#include "../physics/physics.h"
#define gameobject_cast(OBJECT, TYPE) (((OBJECT)->GetType() == GOT_##TYPE)? static_cast<TYPE*>(OBJECT) : NULL)
////////////////////////////////////////////////////////////////////////////////////////
/*
Game Object Smart Pointer
*/
////////////////////////////////////////////////////////////////////////////////////////
template <class T = GameObject>
struct GameObjectSmartPointer
{
GameObjectSmartPointer() : handle(0) {}
GameObjectSmartPointer(const T* object) :
handle(object?object->GetHandle() : 0) {}
operator T* () const { return static_cast<T*>(g_objectManager.GetObjectFromHandle(handle)); }
bool operator == (const T& o) const { return (handle == o.GetHandle()); }
bool operator != (const T& o) const { return (handle != o.GetHandle()); }
GameObjectHandle GetHandle() const { return handle; }
void SetHandle(GameObjectHandle h) { handle = h; }
private:
GameObjectHandle handle = 0;
};
////////////////////////////////////////////////////////////////////////////////////////
/*
Game Object
*/
////////////////////////////////////////////////////////////////////////////////////////
enum GameObjectType;
class GameObject : private Uncopyable
{
public: // basic functionality
explicit GameObject(const struct GameObjectStub& stub, GameObject* _parent = NULL, bool addToWorld = true);
explicit GameObject(const XForm2& xf, GameObject* _parent = NULL, GameObjectType _gameObjectType = GameObjectType(0), bool addToWorld = true);
virtual ~GameObject() = 0;
// every object has a unique handle, use object handles instead of pointers to keep track of objects
GameObjectHandle GetHandle() const { return handle; }
bool operator == (const GameObject& other) const { return (handle == other.GetHandle()); }
bool operator != (const GameObject& other) const { return (handle != other.GetHandle()); }
template <class T> bool operator == (const GameObjectSmartPointer<T> o) const { return (handle == o.GetHandle()); }
template <class T> bool operator != (const GameObjectSmartPointer<T> o) const { return (handle != o.GetHandle()); }
// call this function mark an object for destruction instead of calling delete
// all of the object's children will also be removed and marked to be destroyed
virtual void Destroy();
virtual void UnDestroy() { flags &= ~ObjectFlag_Destroyed; }
bool IsDestroyed() const { return flags & ObjectFlag_Destroyed; }
// detach and kill particle emitters
void DetachEmitters();
// Kill() is how objects die during normal gameplay
// override this to make special things happen when an object dies
virtual void Kill() { DetachEmitters(); Destroy(); }
virtual void ApplyDamage(float damage, GameObject* attacker = NULL, GameDamageType damageType = GameDamageType_Default) {}
virtual bool CanBeDamagedBy(GameDamageType damageType) const { return true; }
public: // sound
static float defaultFrequencyRandomness;
static float defaultSoundDistanceMin;
static float defaultSoundDistanceMax;
struct SoundObjectSmartPointer virtual Play(enum Sound_ID si, float volume = 1, float frequency = 1, float frequencyRandomness = defaultFrequencyRandomness, float distanceMin = defaultSoundDistanceMin, float distanceMax = defaultSoundDistanceMax);
public: // game object information
GameObjectType GetType() const { return gameObjectType; }
void SetType(GameObjectType type) { gameObjectType = type; }
const struct ObjectTypeInfo* GetObjectInfo() const;
Vector2 GetStubSize() const { return stubSize; }
void SetStubSize(const Vector2& _stubSize) { stubSize = _stubSize; }
XForm2 GetStubXF() const { return stubXF; }
void SetStubXF(const XForm2& _stubXF) { stubXF = _stubXF; }
const GameTeam GetTeam() const { return team; }
void SetTeam(GameTeam _team) { team = _team; }
public: // hack sedd to resolve missing features
// dynamic type info (only to be used for objects that can be cast to these types)
virtual bool IsPlayer() const { return false; }
virtual bool IsOwnedByPlayer() const { return false; }
virtual bool IsActor() const { return false; }
virtual bool IsCharacter() const { return false; }
virtual bool IsParticleEmitter() const { return false; }
virtual bool IsProjectile() const { return false; }
virtual bool IsTerrain() const { return false; }
virtual bool IsLight() const { return false; }
virtual bool Bounce(const Vector2& direction) { return false; }
virtual bool IsFlying() const { return false; }
// generic gameside functions
virtual bool IsDead() const { return false; }
virtual void SetIsStunned() {}
virtual bool CanPickUp(GameObject* pickerUpper = NULL) const { return false; }
virtual void TriggerActivate(bool activate, GameObject* activator = NULL, int data = 0) {}
virtual bool IsPathable(bool canFly) const { return true; }
// called for each object when terrain is deformed
virtual void TerrainDeform(const Vector2& pos, float radius) {}
// get position that should be targeted if something aimed at this
virtual const Vector2 GetPosTarget() const { return GetPosWorld(); }
// can be used to prevent objects from rapidly playing sounds
void SetSoundTimer() { soundTimer.Set(); }
bool HasPlayedSound(float time) const { return soundTimer.IsSet() && soundTimer < time; }
public: // transforms
const XForm2& GetXFLocal() const { return xfLocal; }
const XForm2& GetXFWorld() const { return xfWorld; }
const XForm2& GetXFWorldLast() const { return xfWorldLast; }
void SetPosLocal(const Vector2& pos) { xfLocal.position = pos; }
void SetAngleLocal(float angle) { xfLocal.angle = angle; }
void SetXFLocal(const XForm2& xf) { xfLocal = xf; }
void SetXFWorld(const XForm2& xf)
{
ASSERT(xf.IsFinite());
if (HasPhysics())
SetXFPhysics(xf);
if (HasParent())
{
xfWorld = xf;
xfLocal = xfWorld * parent->xfWorld.Inverse();
return;
}
xfWorld = xf;
SetXFLocal(xf);
}
void SetPosWorld(const Vector2& pos)
{
ASSERT(pos.IsFinite());
if (HasPhysics())
SetPosPhysics(pos);
if (HasParent())
{
xfWorld.position = pos;
xfLocal.position = (xfWorld * parent->xfWorld.Inverse()).position;
return;
}
xfWorld.position = pos;
SetPosLocal(pos);
}
void SetAngleWorld(float angle)
{
ASSERT(isfinite(angle));
if (HasPhysics())
SetAnglePhysics(angle);
if (HasParent())
{
xfWorld.angle = angle;
xfLocal.angle = (xfWorld * parent->xfWorld.Inverse()).angle;
return;
}
xfWorld.angle = angle;
SetAngleLocal(angle);
}
// shortcuts to quickly get at parts of the xform
const Vector2& GetPosLocal() const { return xfLocal.position; }
const Vector2& GetPosWorld() const { return xfWorld.position; }
const float GetAngleLocal() const { return xfLocal.angle; }
const float GetAngleWorld() const { return xfWorld.angle; }
const Vector2 GetRightLocal() const { return xfLocal.GetRight(); }
const Vector2 GetRightWorld() const { return xfWorld.GetRight(); }
const Vector2 GetUpLocal() const { return xfLocal.GetUp(); }
const Vector2 GetUpWorld() const { return xfWorld.GetUp(); }
// resurcive update of object and child transform
virtual void UpdateTransforms();
// call to wipe out interpolation data for this object and it's children
// so an object can instantly transport to a new position rather then interpolating
void ResetLastWorldTransforms();
// get the delta xform used for interpolation
XForm2 GetXFDelta() const { return xfWorld - xfWorldLast; }
protected: // lower level object functions
// automatically called for all object during update phase
virtual void Update() {}
// automatically called for every visible object during render phase
virtual void Render();
// automatically called for every visible object during render post phase (after main render is complete)
virtual void RenderPost() {}
public: // children and parents
void AttachChild(GameObject& child);
void DetachChild(GameObject& child);
bool HasChildren() const { return !(children.empty()); }
void DetachParent() { if (parent) parent->DetachChild(*this); }
void DetachChildren();
void DestroyChildren();
virtual void WasDetachedFromParent() {}
bool HasParent() const { return parent != NULL; }
GameObject* GetParent() { return parent; }
const GameObject* GetParent() const { return parent; }
GameObject* GetFirstChild() { return children.front(); }
const GameObject* GetFirstChild() const { return children.front(); }
list<GameObject*>& GetChildren() { return children; }
const list<GameObject*>& GetChildren() const { return children; }
public: // interpolation (used by rendering)
// use this transform when rendering to get the interpolated xform
XForm2 GetXFInterpolated() const;
XForm2 GetXFInterpolated(float percent) const;
Matrix44 GetMatrixInterpolated() const;
public: // rendering
void SetVisible(bool visible);
bool IsVisible() const { return (flags & ObjectFlag_Visible) != 0; }
// order of rendering for objects within a given render pass
// lower numbers draw earlier
int GetRenderGroup() const { return renderGroup; }
void SetRenderGroup(int _renderGroup) { renderGroup = _renderGroup; }
// called to render a stub in the editor
static void StubRender(const GameObjectStub& stub, float alpha);
// called to render a stub on the map (by default stubs don't appear on the map)
static void StubRenderMap(const GameObjectStub& stub, float alpha) {}
// called to show a description of the object in editor
static WCHAR* StubDescription() { return L"Unknown object type."; }
// called to show a description of the object in editor
static WCHAR* StubAttributesDescription() { return L"N/A"; }
// fill in default attributes when stub is created
static char* StubAttributesDefault() { return ""; }
// return size of stub for selection in the editor
static Vector2 StubSelectSize(const GameObjectStub& stub);
public: // physics
bool HasPhysics() const { return physicsBody != NULL; }
b2Body* GetPhysicsBody() { return physicsBody; }
const b2Body* GetPhysicsBody() const { return physicsBody; }
// set box2d collision filter
// Set group of objects to never collide (negative) or always collide (positive). Zero means no collision group.
void SetPhysicsFilter(int16 groupIndex = 0, uint16 categoryBits = 0x0001, uint16 maskBits = 0xFFFF);
int16 GetPhysicsGroup() const;
// check if objects should collide. if a fixture is null that indicates it is a raycast collide test
virtual bool ShouldCollide(const GameObject& otherObject, const b2Fixture* myFixture, const b2Fixture* otherFixture) const { return true; }
// special check for line of sight collision
virtual bool ShouldCollideSight() const { return true; }
// collision callbacks (these are batched up and called after physics)
// getting a null fixture for the other object indicates that it is a raycast collision
virtual void CollisionAdd(GameObject& otherObject, const ContactEvent& contactEvent, b2Fixture* myFixture, b2Fixture* otherFixture) {}
virtual void CollisionPersist(GameObject& otherObject, const ContactEvent& contactEvent, b2Fixture* myFixture, b2Fixture* otherFixture) {}
virtual void CollisionRemove(GameObject& otherObject, const ContactEvent& contactEvent, b2Fixture* myFixture, b2Fixture* otherFixture) {}
virtual void CollisionResult(GameObject& otherObject, const ContactResult& contactResult, b2Fixture* myFixture, b2Fixture* otherFixture) {}
// collision pre-solve callback, called immediatly during physics update
virtual void CollisionPreSolve(GameObject& otherObject, const ContactEvent& contactEvent, b2Fixture* myFixture, b2Fixture* otherFixture, const b2Manifold* oldManifold) {}
// create/destroy functions for physics
void CreatePhysicsBody(b2BodyType type = b2_dynamicBody, bool fixedRotation = false, bool allowSleeping = true);
void CreatePhysicsBody(const b2BodyDef& bodyDef);
void DestroyPhysicsBody();
b2Fixture* AddFixture(const b2FixtureDef& fixtureDef);
b2Fixture* AddFixture(const b2Shape& shape, float density = Physics::defaultDensity, float friction = Physics::defaultFriction, float restitution = Physics::defaultRestitution, void* userData = NULL);
b2Fixture* AddSensor(const b2Shape& shape, void* userData = NULL);
b2Fixture* AddFixtureBox(const Vector2& size, float density = Physics::defaultDensity, float friction = Physics::defaultFriction, float restitution = Physics::defaultRestitution);
b2Fixture* AddFixtureBox(const Vector2& size, const XForm2& offset, float density = Physics::defaultDensity, float friction = Physics::defaultFriction, float restitution = Physics::defaultRestitution);
b2Fixture* AddFixtureCircle(const float radius, float density = Physics::defaultDensity, float friction = Physics::defaultFriction, float restitution = Physics::defaultRestitution);
b2Fixture* AddFixturePolygon(const Vector2* points, int count, float density = Physics::defaultDensity, float friction = Physics::defaultFriction, float restitution = Physics::defaultRestitution);
b2Fixture* AddFixtureEdge(const Vector2& p1, const Vector2& p2, float density = Physics::defaultDensity, float friction = Physics::defaultFriction, float restitution = Physics::defaultRestitution);
b2Fixture* AddFixtureEdge(const Vector2& p1, const Vector2& p2, const Vector2& p0, const Vector2& p3,float density = Physics::defaultDensity, float friction = Physics::defaultFriction, float restitution = Physics::defaultRestitution);
b2Fixture* AddSensorBox(const Vector2& size);
b2Fixture* AddSensorCircle(const float radius);
b2Fixture* AddSensorPolygon(const Vector2* points, int count);
void RemoveFixture(b2Fixture& fixture);
static GameObject* GetFromPhysicsBody(b2Body& body) { return static_cast<GameObject*>(body.GetUserData()); }
// get info about the attached physics body
virtual Vector2 GetVelocity() const;
virtual void SetVelocity(const Vector2& v);
virtual void SetAngularVelocity(const float v);
virtual float GetSpeed() const { return GetVelocity().Length(); }
virtual float GetSpeedSquared() const { return GetVelocity().LengthSquared(); }
virtual float GetAngularVelocity() const;
virtual float GetMass() const;
virtual float GetKineticEnergy() const;
virtual XForm2 GetXFPhysics() const;
virtual bool IsStatic() const;
virtual void SetXFPhysics(const Vector2& position, float angle = 0) { SetXFPhysics(XForm2(position, angle)); }
virtual void SetXFPhysics(const XForm2& xf);
virtual void SetPosPhysics(const Vector2& pos);
virtual void SetAnglePhysics(float angle);
virtual void SetLinearDamping(float damp) { if (GetPhysicsBody()) GetPhysicsBody()->SetLinearDamping(damp); }
virtual void SetAngularDamping(float damp) { if (GetPhysicsBody()) GetPhysicsBody()->SetAngularDamping(damp); }
virtual void SetMass(float mass);
virtual void SetMassCenter(const Vector2& center);
virtual void SetRotationalInertia(float I);
virtual void SetRestitution(float restitution);
virtual void SetFriction(float friction);
virtual bool TestPoint(const Vector2& point) const;
// apply forces to the attached physics body
virtual void ApplyTorque(float torque);
virtual void ApplyAngularAcceleration(float angularAcceleration);
virtual void ApplyForce(const Vector2& force, const Vector2& pos);
virtual void ApplyForce(const Vector2& force);
virtual void ApplyImpulse(const Vector2& impulse, const Vector2& pos);
virtual void ApplyImpulse(const Vector2& impulse);
virtual void ApplyAcceleration(const Vector2& a, const Vector2& pos);
virtual void ApplyAcceleration(const Vector2& a);
virtual void ApplyRotation(float angle);
virtual void CapSpeed(float speed);
virtual void CapAngularSpeed(float speed);
// stuff that has to do with gravity
bool HasGravity() const {return (flags & ObjectFlag_Gravity) != 0;}
void SetHasGravity(bool hasGravity);
virtual Vector2 GetGravity() const;
void SetGravityScale(float scale) { ASSERT(HasPhysics()) GetPhysicsBody()->SetGravityScale(scale); }
float GetGravityScale() const { ASSERT(HasPhysics()) return GetPhysicsBody()->GetGravityScale(); }
// move up heiarachy until we find a physical object if there is one
const GameObject* GetAttachedPhysics() const;
GameObject* GetAttachedPhysics();
public: // streaming
// check if object should be streamed out
virtual bool ShouldStreamOut() const;
// automatically called when an object gets streamed out
virtual void StreamOut() { Destroy(); }
// automatically called if an object still exists when trying to stream in
virtual void StreamIn() {}
// true if the object should do seralized setreaming
static bool IsSerializable() { return false; }
// saves this object out to a stub for seralized streaming
virtual GameObjectStub Serialize() const;
// get combined aabb for all the fixtures in this physics body
Box2AABB GetPhysicsAABB(bool includeSensors = false) const;
// is this object (and it's children) fully contained inside the aabb?
bool FullyContainedBy(const Box2AABB& bbox) const;
// is this object (or it's children) partially contained inside the aabb?
bool PartiallyContainedBy(const Box2AABB& bbox) const;
// was the object added this frame?
bool WasJustAdded() const { return (flags & ObjectFlag_JustAdded) != 0; }
public: // allocation
void* operator new (size_t size) { return g_objectManager.AllocateBlock(size); }
void operator delete (void* block) { g_objectManager.FreeBlock(block); }
private: // private stuff
GameObjectHandle handle; // the unique handle of this object
GameObjectType gameObjectType; // the type of game object if it has one
b2Body* physicsBody; // the physics body if it has one
int renderGroup; // order objects are rendered in with their render pass
Vector2 stubSize; // size from the stub, used for streaming
XForm2 stubXF; // xf when spawned
GameTimer soundTimer; // can be used to limit how often objects play sounds
XForm2 xfLocal; // transform in local space
XForm2 xfWorld; // transform from local to world space (only updated once per frame)
XForm2 xfWorldLast; // world space transform from last frame, used for interpolation
list<GameObject*> children; // list of children
GameObject* parent; // parent if it has one
GameTeam team; // team object is on
enum ObjectFlags
{
ObjectFlag_Destroyed = 0x01, // is marked for deletion
ObjectFlag_Visible = 0x02, // should be rendered
ObjectFlag_JustAdded = 0x04, // was just created this frame
ObjectFlag_Gravity = 0x08, // should gravity be applied
};
UINT flags; // bit field of flags for the object
static GameObjectHandle nextUniqueHandleValue; // used only internaly to give out unique handles
// should object be destroyed when world is reset?
// only a few special objects like the camera and terrain will need to override this
virtual bool DestroyOnWorldReset() const { return true; }
public: // public data members
static const GameObjectHandle invalidHandle; // represents an invalid object handle
private: // special functions to get and reset the next unique handle
// these friends are really only necessary so they can call to the special get and set handle functions
friend class ObjectEditor;
friend class Terrain;
friend class GameObjectManager;
// these functions should only be used by editors and startup code
static GameObjectHandle GetNextUniqueHandleValue() { return nextUniqueHandleValue; }
static void SetNextUniqueHandleValue(GameObjectHandle _nextUniqueHandleValue) { nextUniqueHandleValue = _nextUniqueHandleValue; }
};
////////////////////////////////////////////////////////////////////////////////////////
/*
Inline functions
*/
////////////////////////////////////////////////////////////////////////////////////////
inline void GameObject::DetachChildren()
{
for (list<GameObject*>::iterator it = children.begin(); it != children.end(); ++it)
{
(**it).WasDetachedFromParent();
(**it).parent = NULL;
}
children.clear();
}
inline void GameObject::DestroyChildren()
{
for (list<GameObject*>::iterator it = children.begin(); it != children.end(); ++it)
(**it).Destroy();
}
inline XForm2 GameObject::GetXFInterpolated(float percent) const { return xfWorld.Interpolate(GetXFDelta(), percent); }
inline XForm2 GameObject::GetXFInterpolated() const { return GetXFInterpolated(g_interpolatePercent); }
inline Matrix44 GameObject::GetMatrixInterpolated() const { return Matrix44(GetXFInterpolated()); }
inline bool GameObject::IsStatic() const { return (!physicsBody || physicsBody->GetType() == b2_staticBody); }
inline Vector2 GameObject::GetVelocity() const { return physicsBody? physicsBody->GetLinearVelocity() : Vector2::Zero(); }
inline void GameObject::SetVelocity(const Vector2& v)
{
ASSERT(v.IsFinite());
if (physicsBody)
physicsBody->SetLinearVelocity(v);
}
inline void GameObject::SetAngularVelocity(const float v)
{
ASSERT(isfinite(v));
if (physicsBody)
physicsBody->SetAngularVelocity(v);
}
inline float GameObject::GetAngularVelocity() const { return physicsBody? physicsBody->GetAngularVelocity() : 0; }
inline float GameObject::GetMass() const { return physicsBody? physicsBody->GetMass() : 0; }
inline float GameObject::GetKineticEnergy() const { return physicsBody? physicsBody->GetMass() * physicsBody->GetLinearVelocity().LengthSquared() : 0; }
inline void GameObject::ApplyTorque(float torque)
{
ASSERT(isfinite(torque));
if (physicsBody)
physicsBody->ApplyTorque(torque, true);
}
inline void GameObject::ApplyAngularAcceleration(float angularAcceleration)
{
ApplyTorque(angularAcceleration * physicsBody->GetInertia());
}
inline void GameObject::ApplyImpulse(const Vector2& impulse, const Vector2& pos)
{
ASSERT(impulse.IsFinite() && pos.IsFinite());
if (physicsBody)
physicsBody->ApplyLinearImpulse(impulse, pos, true);
}
inline void GameObject::ApplyImpulse(const Vector2& impulse)
{
ApplyImpulse(impulse, physicsBody->GetWorldCenter());
}
inline void GameObject::ApplyForce(const Vector2& force, const Vector2& pos)
{
ASSERT(force.IsFinite() && pos.IsFinite());
if (physicsBody)
physicsBody->ApplyForce(force, pos, true);
}
inline void GameObject::ApplyForce(const Vector2& force)
{
ApplyForce(force, physicsBody->GetWorldCenter());
}
inline void GameObject::ApplyAcceleration(const Vector2& accel, const Vector2& pos)
{
ApplyForce(accel*physicsBody->GetMass(), pos);
}
inline void GameObject::ApplyAcceleration(const Vector2& accel)
{
ApplyAcceleration(accel, physicsBody->GetWorldCenter());
}
inline void GameObject::ApplyRotation(float angle)
{
ASSERT(isfinite(angle));
if (physicsBody)
{
const XForm2 xf = GetXFPhysics();
SetXFPhysics(xf.position, xf.angle + angle);
}
else
xfLocal.angle += angle;
}
inline void GameObject::SetXFPhysics(const XForm2& xf)
{
ASSERT(physicsBody && xf.IsFinite());
physicsBody->SetTransform(xf.position, xf.angle);
}
inline void GameObject::SetPosPhysics(const Vector2& pos)
{
ASSERT(physicsBody && pos.IsFinite());
physicsBody->SetTransform(pos, GetXFPhysics().angle);
}
inline void GameObject::SetAnglePhysics(float angle)
{
ASSERT(physicsBody && isfinite(angle));
physicsBody->SetTransform(physicsBody->GetTransform().p, angle);
}
inline XForm2 GameObject::GetXFPhysics() const
{
return physicsBody? physicsBody->GetTransform() : xfWorld;
}
inline void GameObject::CapSpeed(float maxSpeed)
{
ASSERT(isfinite(maxSpeed));
if (!physicsBody)
return;
const Vector2 velocity = physicsBody->GetLinearVelocity();
const float currentSpeed = velocity.Length();
if (currentSpeed > maxSpeed)
physicsBody->SetLinearVelocity(velocity * (maxSpeed/currentSpeed));
}
inline void GameObject::CapAngularSpeed(float maxSpeed)
{
ASSERT(isfinite(maxSpeed));
if (!physicsBody)
return;
const float currentSpeed = physicsBody->GetAngularVelocity();
if (fabs(currentSpeed) > maxSpeed)
physicsBody->SetAngularVelocity(maxSpeed * (currentSpeed > 0? 1 : -1));
}
inline void GameObject::CreatePhysicsBody(const b2BodyDef& bodyDef)
{
ASSERT(!physicsBody);
ASSERT(!HasParent());
ASSERT(bodyDef.userData); // must be connected to an object
physicsBody = g_physics->CreatePhysicsBody(bodyDef);
// update xform so it appears in the correct spot
xfLocal = GetPhysicsBody()->GetTransform();
xfWorld = xfLocal;
}
inline void GameObject::DestroyPhysicsBody()
{
if (physicsBody)
{
b2Body* oldPhysicsBody = physicsBody;
physicsBody = NULL;
g_physics->DestroyPhysicsBody(oldPhysicsBody);
}
}
inline GameObject* GameObject::GetAttachedPhysics() { return const_cast<GameObject*>(static_cast<const GameObject*>(this)->GetAttachedPhysics()); }
inline const GameObject* GameObject::GetAttachedPhysics() const
{
// search for the physical object in the heiarachy
const GameObject* physicsObject = this;
while (physicsObject && !physicsObject->HasPhysics())
{ physicsObject = physicsObject->GetParent(); }
return physicsObject;
}
inline void GameObject::SetHasGravity(bool hasGravity)
{
if (physicsBody)
SetGravityScale(hasGravity ? 1.0f : 0.0f);
if (hasGravity)
flags |= ObjectFlag_Gravity;
else
flags &= ~ObjectFlag_Gravity;
}
inline void GameObject::SetVisible(bool visible)
{
if (visible)
flags |= ObjectFlag_Visible;
else
flags &= ~ObjectFlag_Visible;
}
MongoDB Logo MongoDB