CSC3224_Computer_Games_Development / GameEngine / Engine_Physics / RigidBodyPhysics.h
RigidBodyPhysics.h
Raw
#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;
}