7#include <Box2D/Box2D.h>
14b2BodyType parseBodyType(
const std::string &
type) {
15 if (
type ==
"static")
return b2_staticBody;
16 if (
type ==
"kinematic")
return b2_kinematicBody;
17 if (
type ==
"dynamic")
return b2_dynamicBody;
21const char *bodyTypeName(b2BodyType t) {
23 case b2_staticBody:
return "static";
24 case b2_kinematicBody:
return "kinematic";
25 case b2_dynamicBody:
return "dynamic";
26 default:
return "static";
35 if (body_ && world_ && world_->
raw()) {
37 b2Fixture *
f = body_->GetFixtureList();
39 b2Fixture *next =
f->GetNext();
40 auto *wrap =
static_cast<Fixture *
>(
f->GetUserData());
47 body_->SetUserData(
nullptr);
48 world_->
raw()->DestroyBody(body_);
56 if (body_) body_->SetUserData(
nullptr);
62 if (!body_ || !world_ || !world_->
raw()) {
66 b2Fixture *
f = body_->GetFixtureList();
68 b2Fixture *next =
f->GetNext();
69 auto *wrap =
static_cast<Fixture *
>(
f->GetUserData());
76 body_->SetUserData(
nullptr);
77 world_->
raw()->DestroyBody(body_);
84 if (!body_ || !world_)
return;
85 body_->SetTransform(b2Vec2(world_->
toMeters(
x), world_->
toMeters(
y)), body_->GetAngle());
89 if (!body_ || !world_)
return 0.f;
90 return world_->
toPixels(body_->GetPosition().x);
94 if (!body_ || !world_)
return 0.f;
95 return world_->
toPixels(body_->GetPosition().y);
100 body_->SetTransform(body_->GetPosition(), radians);
104 if (!body_)
return 0.f;
105 return body_->GetAngle();
109 if (!body_ || !world_)
return;
110 body_->SetLinearVelocity(b2Vec2(world_->
toMeters(vx), world_->
toMeters(vy)));
114 if (!body_ || !world_)
return 0.f;
115 return world_->
toPixels(body_->GetLinearVelocity().x);
119 if (!body_ || !world_)
return 0.f;
120 return world_->
toPixels(body_->GetLinearVelocity().y);
124 if (!body_ || !world_)
return 0.f;
125 return world_->
toPixels(body_->GetLinearVelocity().Length());
131 if (!body_ || !world_)
return 0.f;
132 return world_->
toPixels(body_->GetWorldCenter().x);
136 if (!body_ || !world_)
return 0.f;
137 return world_->
toPixels(body_->GetWorldCenter().y);
142 body_->SetAngularVelocity(omega);
146 if (!body_)
return 0.f;
147 return body_->GetAngularVelocity();
151 if (!body_ || !world_)
return;
153 body_->ApplyForceToCenter(b2Vec2(world_->
toMeters(fx), world_->
toMeters(fy)),
true);
157 if (!body_ || !world_)
return;
163 if (!body_ || !world_)
return;
164 body_->ApplyLinearImpulse(b2Vec2(world_->
toMeters(ix), world_->
toMeters(iy)),
165 body_->GetWorldCenter(),
true);
170 body_->ApplyAngularImpulse(impulse,
true);
175 body_->SetType(parseBodyType(bodyType));
179 if (!body_)
return "static";
180 return bodyTypeName(body_->GetType());
185 body_->SetFixedRotation(fixed);
199 body_->SetBullet(bullet);
206 body_->SetAwake(awake);
217 float density,
float friction,
float restitution) {
218 if (!body_ || !world_)
throw eve::Exception(
"Body.newRectangleFixture: body destroyed");
220 throw eve::Exception(
"Body.newRectangleFixture: width/height must be > 0");
222 b2PolygonShape shape;
228 def.density = density;
229 def.friction = friction;
230 def.restitution = restitution;
232 b2Fixture *
raw = body_->CreateFixture(&def);
234 raw->SetUserData(fx);
235 world_->fixtures_.insert(fx);
240 if (!body_ || !world_)
throw eve::Exception(
"Body.newCircleFixture: body destroyed");
241 if (radius <= 0.f)
throw eve::Exception(
"Body.newCircleFixture: radius must be > 0");
244 shape.m_radius = world_->
toMeters(radius);
248 def.density = density;
249 def.friction = friction;
250 def.restitution = restitution;
252 b2Fixture *
raw = body_->CreateFixture(&def);
254 raw->SetUserData(fx);
255 world_->fixtures_.insert(fx);
Fixture * newRectangleFixture(float width, float height, float density=1.f, float friction=0.2f, float restitution=0.f)
width/height in pixels; density kg/m² (Box2D units).
float getLinearVelocityX() const
void applyForceAt(float fx, float fy, float x, float y)
Force applied at a world pixel position.
void setBullet(bool bullet)
CCD bullet mode (recommended for fast small bodies).
void setAwake(bool awake)
Wakes / sleeps the body manually.
void setType(const std::string &bodyType)
"static" | "kinematic" | "dynamic".
void setAngle(float radians)
Rotation in radians.
float getLinearVelocityY() const
void applyLinearImpulse(float ix, float iy)
Instantaneous linear impulse.
Fixture * newCircleFixture(float radius, float density=1.f, float friction=0.2f, float restitution=0.f)
void setFixedRotation(bool fixed)
Locks rotation so the body cannot spin.
void applyForce(float fx, float fy)
Force (pixels/s² * kg) applied at the center of mass.
bool isFixedRotation() const
void setAngularVelocity(float omega)
Angular velocity in radians/s.
float getAngularVelocity() const
void destroy()
Destroys the body inside its world.
void applyAngularImpulse(float impulse)
Instantaneous angular impulse.
float getWorldCenterY() const
float getLinearSpeed() const
Magnitude of the linear velocity.
std::string getType() const
void invalidate()
Internal: marks the wrapper invalid after world destruction.
void setPosition(float x, float y)
Position in pixels.
float getWorldCenterX() const
World center of mass in pixels.
Fixture * newRectangleFixtureAt(float width, float height, float offsetX, float offsetY, float density=1.f, float friction=0.2f, float restitution=0.f)
Rectangle fixture with a local pixel-space offset from the body origin.
float getMass() const
Mass in kilograms (Box2D units).
void setActive(bool active)
Disables/enables the body and its fixtures.
void setLinearVelocity(float vx, float vy)
Linear velocity in pixels/s.
Body(World *world, b2Body *body, int id)
Internal: wraps a Box2D body (use World::newBody).
2D fixture: a shape attached to a Body with material + filter settings. Also carries a string tag use...
Box2D world wrapper (2D physics) with pixel-space coordinates. Handles stepping, gravity,...
void forgetBody(Body *body)
void forgetFixture(Fixture *fixture)
float toPixels(float meters) const
Converts a meter-space length to pixels.
b2World * raw()
The underlying Box2D world (advanced use).
float toMeters(float pixels) const
Converts a pixel-space length to meters.