-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathphysics_world.cpp
More file actions
149 lines (122 loc) · 4.23 KB
/
physics_world.cpp
File metadata and controls
149 lines (122 loc) · 4.23 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
#include "physics_world.h"
#include "object.h"
#include <iostream>
PhysicsWorld::PhysicsWorld() : initialized(false) {
worldId = b2_nullWorldId;
}
PhysicsWorld::~PhysicsWorld() {
destroy();
}
void PhysicsWorld::init(float gravity_y) {
if (initialized) {
destroy();
}
b2WorldDef worldDef = b2DefaultWorldDef();
worldDef.gravity = {0.0f, toMeters(gravity_y)};
worldId = b2CreateWorld(&worldDef);
initialized = true;
}
void PhysicsWorld::destroy() {
if (initialized && b2World_IsValid(worldId)) {
b2DestroyWorld(worldId);
worldId = b2_nullWorldId;
initialized = false;
}
}
void PhysicsWorld::step(float dt) {
if (!initialized) return;
int subStepCount = 4;
b2World_Step(worldId, dt, subStepCount);
}
b2BodyId PhysicsWorld::createBody(Object* obj, PhysicsBodyType type, float density, float friction, float restitution) {
if (!initialized) return b2_nullBodyId;
b2BodyDef bodyDef = b2DefaultBodyDef();
bodyDef.position = {toMeters(obj->pos.x), toMeters(obj->pos.y)};
switch (type) {
case PhysicsBodyType::DYNAMIC:
bodyDef.type = b2_dynamicBody;
break;
case PhysicsBodyType::STATIC:
case PhysicsBodyType::SENSOR:
bodyDef.type = b2_staticBody;
break;
case PhysicsBodyType::KINEMATIC:
bodyDef.type = b2_kinematicBody;
break;
}
b2BodyId bodyId = b2CreateBody(worldId, &bodyDef);
b2Body_SetUserData(bodyId, obj);
b2ShapeDef shapeDef = b2DefaultShapeDef();
shapeDef.density = density;
shapeDef.material.friction = friction;
shapeDef.material.restitution = restitution;
shapeDef.userData = obj;
if (type == PhysicsBodyType::SENSOR) {
shapeDef.isSensor = true;
shapeDef.enableSensorEvents = true;
}
// Enable sensor events for dynamic bodies so they can trigger sensors
// Enable contact events for dynamic and kinematic bodies for collision callbacks
if (type == PhysicsBodyType::DYNAMIC) {
shapeDef.enableSensorEvents = true;
shapeDef.enableContactEvents = true;
}
if (type == PhysicsBodyType::KINEMATIC) {
shapeDef.enableContactEvents = true;
}
b2Polygon box = b2MakeBox(toMeters(obj->width2), toMeters(obj->height2));
b2CreatePolygonShape(bodyId, &shapeDef, &box);
return bodyId;
}
void PhysicsWorld::destroyBody(b2BodyId bodyId) {
if (b2Body_IsValid(bodyId)) {
b2DestroyBody(bodyId);
}
}
void PhysicsWorld::enableBody(b2BodyId bodyId) {
if (b2Body_IsValid(bodyId)) {
b2Body_Enable(bodyId);
}
}
void PhysicsWorld::disableBody(b2BodyId bodyId) {
if (b2Body_IsValid(bodyId)) {
b2Body_Disable(bodyId);
}
}
void PhysicsWorld::applyForce(b2BodyId bodyId, float fx, float fy) {
if (!b2Body_IsValid(bodyId)) return;
b2Vec2 force = {toMeters(fx), toMeters(fy)};
b2Vec2 point = b2Body_GetPosition(bodyId);
b2Body_ApplyForce(bodyId, force, point, true);
}
void PhysicsWorld::applyForceToCenter(b2BodyId bodyId, float fx, float fy) {
if (!b2Body_IsValid(bodyId)) return;
b2Vec2 force = {toMeters(fx), toMeters(fy)};
b2Body_ApplyForceToCenter(bodyId, force, true);
}
void PhysicsWorld::setLinearVelocity(b2BodyId bodyId, float vx, float vy) {
if (!b2Body_IsValid(bodyId)) return;
b2Vec2 velocity = {toMeters(vx), toMeters(vy)};
b2Body_SetLinearVelocity(bodyId, velocity);
}
void PhysicsWorld::setTransform(b2BodyId bodyId, float x, float y, float angle) {
if (!b2Body_IsValid(bodyId)) return;
b2Vec2 position = {toMeters(x), toMeters(y)};
b2Rot rotation = b2MakeRot(angle);
b2Body_SetTransform(bodyId, position, rotation);
}
b2Vec2 PhysicsWorld::getPosition(b2BodyId bodyId) {
if (!b2Body_IsValid(bodyId)) return {0, 0};
b2Vec2 pos = b2Body_GetPosition(bodyId);
return {toPixels(pos.x), toPixels(pos.y)};
}
b2Vec2 PhysicsWorld::getLinearVelocity(b2BodyId bodyId) {
if (!b2Body_IsValid(bodyId)) return {0, 0};
b2Vec2 vel = b2Body_GetLinearVelocity(bodyId);
return {toPixels(vel.x), toPixels(vel.y)};
}
float PhysicsWorld::getAngle(b2BodyId bodyId) {
if (!b2Body_IsValid(bodyId)) return 0.0f;
b2Rot rot = b2Body_GetRotation(bodyId);
return b2Rot_GetAngle(rot);
}