diff --git a/CMakeLists.txt b/CMakeLists.txt index 98b7bd24..620cd7b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -439,6 +439,7 @@ include_directories (${SUPERNOVA_ROOT}/engine/core/object) include_directories (${SUPERNOVA_ROOT}/engine/core/object/audio) include_directories (${SUPERNOVA_ROOT}/engine/core/object/ui) include_directories (${SUPERNOVA_ROOT}/engine/core/object/environment) +include_directories (${SUPERNOVA_ROOT}/engine/core/object/physics) include_directories (${SUPERNOVA_ROOT}/engine/core/script) include_directories (${SUPERNOVA_ROOT}/engine/core/subsystem) include_directories (${SUPERNOVA_ROOT}/engine/core/texture) diff --git a/engine/core/Scene.cpp b/engine/core/Scene.cpp index 00b6ea8d..8c40d949 100644 --- a/engine/core/Scene.cpp +++ b/engine/core/Scene.cpp @@ -56,6 +56,7 @@ Scene::Scene(){ registerComponent(); registerComponent(); registerComponent(); + registerComponent(); registerSystem(); registerSystem(); diff --git a/engine/core/Scene.h b/engine/core/Scene.h index 6599dcf2..3bc1305f 100644 --- a/engine/core/Scene.h +++ b/engine/core/Scene.h @@ -49,6 +49,7 @@ #include "component/AudioComponent.h" #include "component/TilemapComponent.h" #include "component/Body2DComponent.h" +#include "component/Joint2DComponent.h" namespace Supernova{ diff --git a/engine/core/component/Body2DComponent.h b/engine/core/component/Body2DComponent.h index 6b862e20..2b36d731 100644 --- a/engine/core/component/Body2DComponent.h +++ b/engine/core/component/Body2DComponent.h @@ -49,7 +49,7 @@ namespace Supernova{ bool fixedRotation = false; bool bullet = false; Body2DType type = Body2DType::STATIC; - bool enable = true; + bool enabled = true; float gravityScale = 1.0f; CollisionShape2D shapes[MAX_SHAPES]; diff --git a/engine/core/component/Joint2DComponent.h b/engine/core/component/Joint2DComponent.h new file mode 100644 index 00000000..f5f384e4 --- /dev/null +++ b/engine/core/component/Joint2DComponent.h @@ -0,0 +1,38 @@ +#ifndef JOINT2D_COMPONENT_H +#define JOINT2D_COMPONENT_H + +#include "Supernova.h" + +class b2Joint; + +namespace Supernova{ + + enum class Joint2DType{ + DISTANCE, + REVOLUTE + }; + + struct Joint2DComponent{ + b2Joint* joint = NULL; + + Entity bodyA; + Entity bodyB; + Joint2DType type = Joint2DType::DISTANCE; + bool collideConnected = false; + + Vector2 localAnchorA = Vector2(0.0f, 0.0f); + Vector2 localAnchorB = Vector2(0.0f, 0.0f); + float referenceAngle = 0.0f; + float lowerAngle = 0.0f; + float upperAngle = 0.0f; + float maxMotorTorque = 0.0f; + float motorSpeed = 0.0f; + float enableLimit = false; + float enableMotor = false; + + bool needUpdate = true; + }; + +} + +#endif //JOINT2D_COMPONENT_H \ No newline at end of file diff --git a/engine/core/object/Body2D.cpp b/engine/core/object/physics/Body2D.cpp similarity index 98% rename from engine/core/object/Body2D.cpp rename to engine/core/object/physics/Body2D.cpp index eb053340..51236a8f 100644 --- a/engine/core/object/Body2D.cpp +++ b/engine/core/object/physics/Body2D.cpp @@ -224,11 +224,11 @@ void Body2D::setType(Body2DType type){ } } -void Body2D::setEnabled(bool enable){ +void Body2D::setEnabled(bool enabled){ Body2DComponent& body = getComponent(); - if (body.enable != enable){ - body.enable = enable; + if (body.enabled != enabled){ + body.enabled = enabled; body.needUpdate = true; } @@ -301,7 +301,7 @@ Body2DType Body2D::getType() const{ bool Body2D::isEnabled() const{ Body2DComponent& body = getComponent(); - return body.enable; + return body.enabled; } float Body2D::getGravityScale() const{ diff --git a/engine/core/object/Body2D.h b/engine/core/object/physics/Body2D.h similarity index 98% rename from engine/core/object/Body2D.h rename to engine/core/object/physics/Body2D.h index 855be1af..19033d3b 100644 --- a/engine/core/object/Body2D.h +++ b/engine/core/object/physics/Body2D.h @@ -46,7 +46,7 @@ namespace Supernova{ void setFixedRotation(bool fixedRotation); void setBullet(bool bullet); void setType(Body2DType type); - void setEnabled(bool enable); + void setEnabled(bool enabled); void setGravityScale(float gravityScale); Vector2 getLinearVelocity() const; diff --git a/engine/core/object/physics/Joint2D.cpp b/engine/core/object/physics/Joint2D.cpp new file mode 100644 index 00000000..eadefca3 --- /dev/null +++ b/engine/core/object/physics/Joint2D.cpp @@ -0,0 +1,27 @@ +// +// (c) 2023 Eduardo Doria. +// + +#include "Joint2D.h" + +#include "subsystem/PhysicsSystem.h" +#include "component/Body2DComponent.h" + +using namespace Supernova; + +Joint2D::Joint2D(Scene* scene, Entity entity): EntityHandle(scene, entity){ + +} + +Joint2D::~Joint2D(){ + +} + +Joint2D::Joint2D(const Joint2D& rhs): EntityHandle(rhs){ + +} + +Joint2D& Joint2D::operator=(const Joint2D& rhs){ + + return *this; +} \ No newline at end of file diff --git a/engine/core/object/physics/Joint2D.h b/engine/core/object/physics/Joint2D.h new file mode 100644 index 00000000..6a739d51 --- /dev/null +++ b/engine/core/object/physics/Joint2D.h @@ -0,0 +1,23 @@ +// +// (c) 2023 Eduardo Doria. +// + +#ifndef JOINT2D_H +#define JOINT2D_H + +#include "EntityHandle.h" + +namespace Supernova{ + + class Joint2D: public EntityHandle{ + public: + Joint2D(Scene* scene, Entity entity); + virtual ~Joint2D(); + + Joint2D(const Joint2D& rhs); + Joint2D& operator=(const Joint2D& rhs); + + }; +} + +#endif //BODY2D_H \ No newline at end of file diff --git a/engine/core/subsystem/PhysicsSystem.cpp b/engine/core/subsystem/PhysicsSystem.cpp index b9870ac3..1515c8c6 100644 --- a/engine/core/subsystem/PhysicsSystem.cpp +++ b/engine/core/subsystem/PhysicsSystem.cpp @@ -11,9 +11,31 @@ using namespace Supernova; +b2BodyType getBodyType(Body2DType type){ + if (type == Body2DType::STATIC){ + return b2_staticBody; + }else if (type == Body2DType::kINEMATIC){ + return b2_kinematicBody; + }else if (type == Body2DType::DYNAMIC){ + return b2_dynamicBody; + } + + return b2_staticBody; +} + +b2JointType getJointType(Joint2DType type){ + if (type == Joint2DType::DISTANCE){ + return e_distanceJoint; + }else if (type == Joint2DType::REVOLUTE){ + return e_revoluteJoint; + } + + return e_unknownJoint; +} + PhysicsSystem::PhysicsSystem(Scene* scene): SubSystem(scene){ - signature.set(scene->getComponentType()); + signature.set(scene->getComponentType()); this->scene = scene; @@ -66,16 +88,47 @@ int PhysicsSystem::addRectShape2D(Entity entity, float width, float height){ return -1; } +b2Body* PhysicsSystem::getBody(Entity entity){ + Body2DComponent* body = scene->findComponent(entity); + + if (body){ + return body->body; + } + + return NULL; +} + bool PhysicsSystem::loadBody2D(Body2DComponent& body){ if (world2D && !body.body){ b2BodyDef bodyDef; bodyDef.position.Set(0.0f, 0.0f); bodyDef.angle = 0.0f; - bodyDef.type = b2_dynamicBody; + bodyDef.linearVelocity = b2Vec2(body.linearVelocity.x, body.linearVelocity.y); + bodyDef.angularVelocity = body.angularVelocity; + bodyDef.linearDamping = body.linearDamping; + bodyDef.angularDamping = body.angularDamping; + bodyDef.allowSleep = body.allowSleep; + bodyDef.awake = body.awake; + bodyDef.fixedRotation = body.fixedRotation; + bodyDef.bullet = body.bullet; + bodyDef.enabled = body.enabled; + bodyDef.gravityScale = body.gravityScale; + bodyDef.type = getBodyType(body.type); + + body.needUpdate = false; body.body = world2D->CreateBody(&bodyDef); for (int i = 0; i < body.numShapes; i++){ + b2FixtureDef fixtureDef; + + fixtureDef.density = body.shapes[i].density; + fixtureDef.friction = body.shapes[i].friction; + fixtureDef.restitution = body.shapes[i].restitution; + fixtureDef.isSensor = body.shapes[i].sensor; + + body.shapes[i].needUpdate = false; + body.shapes[i].fixture = body.body->CreateFixture(body.shapes[i].shape, 1.0f); } @@ -102,6 +155,33 @@ void PhysicsSystem::destroyBody2D(Body2DComponent& body){ } } +bool PhysicsSystem::loadJoint2D(Joint2DComponent& joint){ + if (world2D && !joint.joint){ + b2JointDef jointDef; + jointDef.bodyA = getBody(joint.bodyA); + jointDef.bodyB = getBody(joint.bodyB); + jointDef.collideConnected = joint.collideConnected; + jointDef.type = getJointType(joint.type); + + joint.needUpdate = false; + + joint.joint = world2D->CreateJoint(&jointDef); + + return true; + } + + return false; +} + +void PhysicsSystem::destroyJoint2D(Joint2DComponent& joint){ + if (world2D && joint.joint){ + world2D->DestroyJoint(joint.joint); + + joint.joint = NULL; + } +} + + void PhysicsSystem::load(){ if (!world2D){ b2Vec2 gravity(0.0f, 10.0f); @@ -118,6 +198,8 @@ void PhysicsSystem::destroy(){ void PhysicsSystem::update(double dt){ auto bodies2d = scene->getComponentArray(); + auto joints2d = scene->getComponentArray(); + for (int i = 0; i < bodies2d->size(); i++){ Body2DComponent& body = bodies2d->getComponentFromIndex(i); Entity entity = bodies2d->getEntity(i); @@ -134,16 +216,9 @@ void PhysicsSystem::update(double dt){ body.body->SetAwake(body.awake); body.body->SetFixedRotation(body.fixedRotation); body.body->SetBullet(body.bullet); - body.body->SetEnabled(body.enable); + body.body->SetEnabled(body.enabled); body.body->SetGravityScale(body.gravityScale); - - if (body.type == Body2DType::STATIC){ - body.body->SetType(b2_staticBody); - }else if (body.type == Body2DType::kINEMATIC){ - body.body->SetType(b2_kinematicBody); - }else if (body.type == Body2DType::DYNAMIC){ - body.body->SetType(b2_dynamicBody); - } + body.body->SetType(getBodyType(body.type)); body.needUpdate = false; } @@ -175,6 +250,23 @@ void PhysicsSystem::update(double dt){ } } + for (int i = 0; i < joints2d->size(); i++){ + Joint2DComponent& joint = joints2d->getComponentFromIndex(i); + Entity entity = joints2d->getEntity(i); + Signature signature = scene->getSignature(entity); + + loadJoint2D(joint); + + if (joint.needUpdate){ + if (joint.type == Joint2DType::DISTANCE){ + b2DistanceJoint* distJoint = (b2DistanceJoint*)joint.joint; + //distJoint.se + } + + joint.needUpdate = false; + } + } + if (bodies2d->size() > 0){ int32 velocityIterations = 6; int32 positionIterations = 2; @@ -211,7 +303,7 @@ void PhysicsSystem::update(double dt){ body.linearVelocity = Vector2(body.body->GetLinearVelocity().x, body.body->GetLinearVelocity().y); body.angularVelocity = body.body->GetAngularVelocity(); body.awake = body.body->IsAwake(); - body.enable = body.body->IsEnabled(); + body.enabled = body.body->IsEnabled(); } } diff --git a/engine/core/subsystem/PhysicsSystem.h b/engine/core/subsystem/PhysicsSystem.h index 1313b2a6..8acd3e3c 100644 --- a/engine/core/subsystem/PhysicsSystem.h +++ b/engine/core/subsystem/PhysicsSystem.h @@ -7,8 +7,10 @@ #include "SubSystem.h" #include "component/Body2DComponent.h" +#include "component/Joint2DComponent.h" class b2World; +class b2Body; namespace Supernova{ @@ -26,9 +28,14 @@ namespace Supernova{ void removeBody2D(Entity entity); int addRectShape2D(Entity entity, float width, float height); + b2Body* getBody(Entity entity); + bool loadBody2D(Body2DComponent& body); void destroyBody2D(Body2DComponent& body); + bool loadJoint2D(Joint2DComponent& joint); + void destroyJoint2D(Joint2DComponent& joint); + virtual void load(); virtual void destroy(); virtual void update(double dt);