SleakEngine 1.0.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
RigidbodyComponent.hpp
Go to the documentation of this file.
1#ifndef _RIGIDBODY_COMPONENT_HPP_
2#define _RIGIDBODY_COMPONENT_HPP_
3
4#include <ECS/Component.hpp>
5#include <Core/OSDef.hpp>
6#include <Math/Vector.hpp>
7
8namespace Sleak {
9
10 /// How a rigidbody participates in collision response.
11 /// @ingroup physics
12 enum class BodyType {
13 Static, // Never moves, infinite mass
14 Kinematic, // Moves but controlled by code, full pushback
15 Dynamic // Mass-based response, affected by gravity
16 };
17
18 /// Tracks velocity, gravity, and collision state for a GameObject; PhysicsWorld drives its integration.
19 ///
20 /// Pair this with a ColliderComponent to make an object participate in
21 /// simulation. The collider supplies the shape, the rigidbody supplies
22 /// the motion state, and Physics::PhysicsWorld integrates and resolves
23 /// both. Without a collider, the rigidbody moves but never collides.
24 ///
25 /// BodyType decides the response. Static bodies never move. Kinematic
26 /// bodies move under your control and push others without being
27 /// pushed. Dynamic bodies respond by mass and fall under their own
28 /// gravity vector, which defaults to standard earth gravity but is
29 /// yours to change: platformers and voxel games routinely run heavier
30 /// gravity for a snappier feel.
31 ///
32 /// Gravity is off by default, so call SetUseGravity(true) on anything
33 /// that should fall. Collision flags are separated into ground and
34 /// wall contacts, which is what a character controller needs to tell
35 /// "landed" from "walked into something". Those flags are per-frame:
36 /// call ClearCollisionState() once you have consumed them.
37 ///
38 /// @code{.cpp}
39 /// player->AddComponent<Sleak::ColliderComponent>(
40 /// Sleak::Physics::BoundingSphere(
41 /// Sleak::Math::Vector3D(0, 0, 0), 0.3f));
42 /// player->AddComponent<Sleak::RigidbodyComponent>(
43 /// Sleak::BodyType::Dynamic);
44 ///
45 /// auto* rb = player->GetComponent<Sleak::RigidbodyComponent>();
46 /// rb->SetUseGravity(true);
47 /// rb->SetGravity(Sleak::Math::Vector3D(0.0f, -32.0f, 0.0f));
48 /// rb->SetMass(80.0f);
49 /// rb->SetTerminalVelocity(60.0f);
50 ///
51 /// // Later, in an update
52 /// if (rb->IsGrounded() && jumpPressed) {
53 /// Sleak::Math::Vector3D v = rb->GetVelocity();
54 /// v.SetY(6.0f);
55 /// rb->SetVelocity(v);
56 /// }
57 /// if (rb->HadWallCollision()) {
58 /// SlideAlong(rb->GetWallNormal());
59 /// }
60 /// rb->ClearCollisionState();
61 /// @endcode
62 ///
63 /// @see ColliderComponent, Physics::PhysicsWorld, BodyType,
64 /// FirstPersonController
65 /// @ingroup physics
66 class ENGINE_API RigidbodyComponent : public Component {
67 public:
69 ~RigidbodyComponent() override = default;
70
71 bool Initialize() override;
72 void Update(float deltaTime) override;
73
74 /// Pushes the body out along normal by penetration and updates ground/wall collision state.
75 void ResolveCollision(const Math::Vector3D& normal, float penetration);
76
77 BodyType GetBodyType() const { return m_bodyType; }
78 void SetBodyType(BodyType type) { m_bodyType = type; }
79
80 // General collision state (any collision this frame)
81 bool HadCollision() const { return m_hadCollision; }
82 Math::Vector3D GetLastCollisionNormal() const { return m_lastCollisionNormal; }
83
84 // Separate ground vs wall collision tracking
85 bool HadGroundCollision() const { return m_hadGroundCollision; }
86 Math::Vector3D GetGroundNormal() const { return m_groundNormal; }
87 bool HadWallCollision() const { return m_hadWallCollision; }
88 Math::Vector3D GetWallNormal() const { return m_wallNormal; }
89
90 /// Resets HadCollision/HadGroundCollision/HadWallCollision for the next frame.
91 void ClearCollisionState();
92
93 // Velocity
94 Math::Vector3D GetVelocity() const { return m_velocity; }
95 void SetVelocity(const Math::Vector3D& velocity) { m_velocity = velocity; }
96 void AddForce(const Math::Vector3D& force) { m_velocity = m_velocity + force * (1.0f / m_mass); }
97
98 // Gravity
99 Math::Vector3D GetGravity() const { return m_gravity; }
100 void SetGravity(const Math::Vector3D& gravity) { m_gravity = gravity; }
101 bool GetUseGravity() const { return m_useGravity; }
102 void SetUseGravity(bool useGravity) { m_useGravity = useGravity; }
103
104 // Grounded state
105 bool IsGrounded() const { return m_isGrounded; }
106 void SetGrounded(bool grounded) { m_isGrounded = grounded; }
107
108 // Mass
109 float GetMass() const { return m_mass; }
110 void SetMass(float mass) { m_mass = mass > 0.0f ? mass : 1.0f; }
111
112 // Terminal velocity
113 float GetTerminalVelocity() const { return m_terminalVelocity; }
114 void SetTerminalVelocity(float tv) { m_terminalVelocity = tv; }
115
116 private:
117 BodyType m_bodyType;
118
119 // Collision tracking
120 Math::Vector3D m_lastCollisionNormal;
121 bool m_hadCollision = false;
122
123 Math::Vector3D m_groundNormal = Math::Vector3D(0, 1, 0);
124 bool m_hadGroundCollision = false;
125
126 Math::Vector3D m_wallNormal;
127 bool m_hadWallCollision = false;
128
129 // Physics state
130 Math::Vector3D m_velocity = Math::Vector3D(0, 0, 0);
131 Math::Vector3D m_gravity = Math::Vector3D(0, -9.81f, 0);
132 bool m_useGravity = false;
133 bool m_isGrounded = false;
134 float m_mass = 1.0f;
135 float m_terminalVelocity = 50.0f;
136 };
137
138} // namespace Sleak
139
140#endif // _RIGIDBODY_COMPONENT_HPP_
GameObject * owner
Definition Component.hpp:81
Component(GameObject *object)
Definition Component.hpp:61
Math::Vector3D GetVelocity() const
void SetUseGravity(bool useGravity)
Math::Vector3D GetGroundNormal() const
Math::Vector3D GetWallNormal() const
void Update(float deltaTime) override
void SetGravity(const Math::Vector3D &gravity)
Math::Vector3D GetGravity() const
RigidbodyComponent(GameObject *owner, BodyType type=BodyType::Kinematic)
bool Initialize() override
One-time setup, called after the component is attached and the owner is initialized.
~RigidbodyComponent() override=default
void SetBodyType(BodyType type)
void SetVelocity(const Math::Vector3D &velocity)
void AddForce(const Math::Vector3D &force)
void ResolveCollision(const Math::Vector3D &normal, float penetration)
Pushes the body out along normal by penetration and updates ground/wall collision state.
Math::Vector3D GetLastCollisionNormal() const
Root namespace for everything the engine exposes.
Definition Camera.hpp:10