#pragma once #include "../Engine_Messaging_System/MessageSystemEvent.h" #include "../Engine_Physics/EnginePhysicsSystem.h" #include "../Engine_Json_System/json.h" #include "../Engine_Common/Common.h" #include "Box2D/Box2D/Dynamics/b2Body.h" #include "Box2D/Box2D/Collision/Shapes/b2PolygonShape.h" #include "Box2D/Box2D/Dynamics/b2Fixture.h" #include <stdarg.h> // Rigid Body Physics class RigidBodyPhysics : public MessageFromJsonSystemEvent<RigidBodyPhysics> { public: static const MessageSystemEventType messageTypeID = MessageSystemEventType::RIGID_BODY_PHYSICS_TYPE; MessageSystemEventType getType() override { return messageTypeID; } int getTypeValue() override { return static_cast<int>(messageTypeID); } static RigidBodyPhysics* messageBuildFromJson(Json::Value Engine_PhysicsystemSource, ...); // Rigid Body Physics using enginePhysicsSystem, and Box2D physics - Create Body explicit RigidBodyPhysics(EnginePhysicsSystem* enginePhysicsSystem, SpriteRectangle* spriteRectangle, b2BodyType bodyType) : fixedSizes() { b2BodyDef bodyDefinition; bodyDefinition.position = b2Vec2( (spriteRectangle->getPosition().x + spriteRectangle->getOrigin().x) / SCALE_PIXELS_TO_UNITS, (spriteRectangle->getPosition().y + spriteRectangle->getOrigin().y) / SCALE_PIXELS_TO_UNITS); bodyDefinition.type = bodyType; physicsBody = enginePhysicsSystem->createBody(bodyDefinition); physicsBody->SetUserData(this); }; b2Body* getBody() const { return physicsBody; } // Add Box Collider - necessary for collision detection void addBoxCollider(b2FixtureDef& fixturedef, float width, float height) { b2PolygonShape polygonShape; polygonShape.SetAsBox((width / 2) / SCALE_PIXELS_TO_UNITS, (height / 2) / SCALE_PIXELS_TO_UNITS); fixturedef.shape = &polygonShape; physicsBody->CreateFixture(&fixturedef); fixedSizes.push_back(std::make_pair(width, height)); } // Convert to Json format for parsing messages between the Game Engine and Level (.json files) Json::Value convertToJson() override; protected: b2Body* physicsBody; std::vector<std::pair<float, float>> fixedSizes; }; // Build Physics Data inline RigidBodyPhysics* RigidBodyPhysics::messageBuildFromJson(Json::Value Engine_PhysicsystemSource, ...) { // Take in variable lists va_list variable_list; va_start(variable_list, Engine_PhysicsystemSource); EnginePhysicsSystem* physics = va_arg(variable_list, EnginePhysicsSystem*); SpriteRectangle* sprite = va_arg(variable_list, SpriteRectangle*); va_end(variable_list); if (physics == nullptr) { throw "Engine Physics System is invalid"; } if (sprite == nullptr) { throw "Sprite is invalid"; } // Default to 2 (Dynamic body) on failure b2BodyType bodyType = b2BodyType(Engine_PhysicsystemSource.get("BodyType", 2).asInt()); auto rigidBody = new RigidBodyPhysics(physics, sprite, bodyType); rigidBody->getBody()->SetFixedRotation(Engine_PhysicsystemSource.get("FixedRotation", false).asBool()); auto fixed = Engine_PhysicsystemSource.get("Fixtures", ""); for(auto fixedBody : fixed) { b2FixtureDef bodyDefinition; bodyDefinition.density = fixedBody.get("Density", 1).asFloat(); bodyDefinition.friction = fixedBody.get("Friction", 0.5).asFloat(); bodyDefinition.restitution = fixedBody.get("Restitution", 0.0).asFloat(); auto width = fixedBody.get("Width", 1).asFloat(); auto height = fixedBody.get("Height", 1).asFloat(); rigidBody->addBoxCollider(bodyDefinition, width, height); } return rigidBody; } // Convert to Json format for parsing messages between the Game Engine and Level (.json files) inline Json::Value RigidBodyPhysics::convertToJson() { Json::Value engineSystemSource; engineSystemSource["EventType"] = static_cast<int>(this->getType()); engineSystemSource["BodyType"] = physicsBody->GetType(); engineSystemSource["FixedRotation"] = physicsBody->IsFixedRotation(); auto count = 0; for (b2Fixture* fixedBody = physicsBody->GetFixtureList(); fixedBody; fixedBody = fixedBody->GetNext()) { Json::Value rigidBodyPhysicsData; rigidBodyPhysicsData["Density"] = fixedBody->GetDensity(); rigidBodyPhysicsData["Friction"] = fixedBody->GetFriction(); rigidBodyPhysicsData["Restitution"] = fixedBody->GetRestitution(); rigidBodyPhysicsData["Width"] = fixedSizes.at(count).first; rigidBodyPhysicsData["Height"] = fixedSizes.at(count).second; engineSystemSource["Fixtures"].append(rigidBodyPhysicsData); ++count; } return engineSystemSource; }