Skip to content

Commit

Permalink
Added basic Box2D integration
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardodoria committed Aug 16, 2023
1 parent 3de9a59 commit 4fa64f4
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 9 deletions.
12 changes: 7 additions & 5 deletions engine/core/component/Body2DComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
#include "Supernova.h"

#define MAX_SHAPES 10
#define MAX_SHAPE_VERTICES 30

class b2Body;
class b2Shape;
class b2Fixture;

namespace Supernova{

Expand All @@ -19,15 +20,16 @@ namespace Supernova{

struct CollisionShape2D{
CollisionShape2DType type = CollisionShape2DType::POLYGON;
float radius = 0;
float center = 0;
Vector2 vertices[MAX_SHAPE_VERTICES];

b2Shape* shape = NULL;
b2Fixture* fixture = NULL;
};

struct Body2DComponent{
b2Body* groundBody = NULL;
b2Body* body = NULL;

CollisionShape2D shapes[MAX_SHAPES];
int numShapes = 0;
};

}
Expand Down
6 changes: 6 additions & 0 deletions engine/core/object/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "Object.h"

#include "subsystem/RenderSystem.h"
#include "subsystem/PhysicsSystem.h"

using namespace Supernova;

Expand Down Expand Up @@ -199,3 +200,8 @@ void Object::updateTransform(){

scene->getSystem<RenderSystem>()->updateTransform(transform);
}

void Object::createRectangularBody(float width, float height){
scene->getSystem<PhysicsSystem>()->createBody2D(entity);
scene->getSystem<PhysicsSystem>()->addRectangleShape2D(entity, width, height);
}
2 changes: 2 additions & 0 deletions engine/core/object/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ namespace Supernova{
void setModelMatrix(Matrix4 modelMatrix);

void updateTransform();

void createRectangularBody(float width, float height);
};

}
Expand Down
2 changes: 1 addition & 1 deletion engine/core/script/binding/CoreClassesLua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ void LuaBinding::registerCoreClasses(lua_State *L){
.beginClass<System>("System")
.addStaticFunction("getScreenWidth", [] () { return System::instance().getScreenWidth(); })
.addStaticFunction("getScreenHeight", [] () { return System::instance().getScreenHeight(); })
.addStaticFunction("showVirtualKeyboard", [] () { System::instance().showVirtualKeyboard(); })
.addStaticFunction("showVirtualKeyboard", [] (std::wstring text) { System::instance().showVirtualKeyboard(text); })
.addStaticFunction("hideVirtualKeyboard", [] () { System::instance().hideVirtualKeyboard(); })
.addStaticFunction("isFullscreen", [] () { return System::instance().isFullscreen(); })
.addStaticFunction("requestFullscreen", [] () { System::instance().requestFullscreen(); })
Expand Down
136 changes: 133 additions & 3 deletions engine/core/subsystem/PhysicsSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "PhysicsSystem.h"
#include "Scene.h"
#include "util/Angle.h"

#include "box2d.h"

Expand All @@ -15,29 +16,158 @@ PhysicsSystem::PhysicsSystem(Scene* scene): SubSystem(scene){
signature.set(scene->getComponentType<Transform>());

this->scene = scene;

this->world2D = NULL;
}

PhysicsSystem::~PhysicsSystem(){
if (world2D){
delete world2D;
world2D = NULL;
}
}

void PhysicsSystem::createBody2D(Entity entity){
Signature signature = scene->getSignature(entity);

if (!signature.test(scene->getComponentType<Body2DComponent>())){
scene->addComponent<Body2DComponent>(entity, {});
}
}

void PhysicsSystem::addRectangleShape2D(Entity entity, float width, float height){
Body2DComponent* body = scene->findComponent<Body2DComponent>(entity);

if (body){
if (body->numShapes < MAX_SHAPES){
body->shapes[body->numShapes].shape = new b2PolygonShape();
body->shapes[body->numShapes].type = CollisionShape2DType::POLYGON;

((b2PolygonShape*)body->shapes[body->numShapes].shape)->SetAsBox(width, height);

body->numShapes++;
}else{
Log::error("Cannot add more shapes in this body, please increase value MAX_SHAPES");
}
}
}

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;

body.body = world2D->CreateBody(&bodyDef);

for (int i = 0; i < body.numShapes; i++){
body.shapes[i].fixture = body.body->CreateFixture(body.shapes[i].shape, 1.0f);
}

return true;
}

return false;
}

void PhysicsSystem::destroyBody2D(Body2DComponent& body){
// When a world leaves scope or is deleted by calling delete on a pointer
// all the memory reserved for bodies, fixtures, and joints is freed
if (world2D && body.body){
for (int i = 0; i < body.numShapes; i++){
body.body->DestroyFixture(body.shapes[i].fixture);

body.shapes[i].shape = NULL;
body.shapes[i].fixture = NULL;
}

world2D->DestroyBody(body.body);

body.body = NULL;
}
}

void PhysicsSystem::load(){
b2Vec2 gravity(0.0f, -10.0f);
b2World world(gravity);
if (!world2D){
b2Vec2 gravity(0.0f, -10.0f);
world2D = new b2World(gravity);
}
}

void PhysicsSystem::destroy(){

if (world2D){
delete world2D;
world2D = NULL;
}
}

void PhysicsSystem::update(double dt){
auto bodies2d = scene->getComponentArray<Body2DComponent>();
for (int i = 0; i < bodies2d->size(); i++){
Body2DComponent& body = bodies2d->getComponentFromIndex(i);
Entity entity = bodies2d->getEntity(i);
Signature signature = scene->getSignature(entity);

bool isNewBody = loadBody2D(body);

if (signature.test(scene->getComponentType<Transform>())){
Transform& transform = scene->getComponent<Transform>(entity);

if (isNewBody || transform.needUpdate){
float scale = 1.0;

b2Vec2 bPosition(transform.worldPosition.x / scale, transform.worldPosition.y / scale);
body.body->SetTransform(bPosition, transform.worldRotation.getRoll());
}
}
}

if (bodies2d->size() > 0){
int32 velocityIterations = 6;
int32 positionIterations = 2;

world2D->Step(dt, velocityIterations, positionIterations);
}

for (int i = 0; i < bodies2d->size(); i++){
Body2DComponent& body = bodies2d->getComponentFromIndex(i);
Entity entity = bodies2d->getEntity(i);
Signature signature = scene->getSignature(entity);

b2Vec2 position = body.body->GetPosition();
float angle = body.body->GetAngle();
if (signature.test(scene->getComponentType<Transform>())){
Transform& transform = scene->getComponent<Transform>(entity);

float scale = 1.0;

Vector3 nPosition = Vector3(position.x * scale, position.y * scale, transform.worldPosition.z);
if (transform.position != nPosition){
transform.position = nPosition;
transform.needUpdate = true;
}

if (transform.worldRotation.getRoll() != angle){
Quaternion rotation;
rotation.fromAngle(Angle::radToDefault(angle));

transform.rotation = rotation;
transform.needUpdate = true;
}

}
}
}

void PhysicsSystem::draw(){

}

void PhysicsSystem::entityDestroyed(Entity entity){
Signature signature = scene->getSignature(entity);

if (signature.test(scene->getComponentType<Body2DComponent>())){
destroyBody2D(scene->getComponent<Body2DComponent>(entity));
}
}
12 changes: 12 additions & 0 deletions engine/core/subsystem/PhysicsSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,27 @@
#define PHYSICSSYSTEM_H

#include "SubSystem.h"
#include "component/Body2DComponent.h"

class b2World;

namespace Supernova{

class PhysicsSystem : public SubSystem {

private:
b2World* world2D;

public:
PhysicsSystem(Scene* scene);
virtual ~PhysicsSystem();

void createBody2D(Entity entity);
void addRectangleShape2D(Entity entity, float width, float height);

bool loadBody2D(Body2DComponent& body);
void destroyBody2D(Body2DComponent& body);

virtual void load();
virtual void destroy();
virtual void update(double dt);
Expand Down

0 comments on commit 4fa64f4

Please sign in to comment.