From 94cac38cc6288293ef2c0820ddecf448fa6500ab Mon Sep 17 00:00:00 2001 From: Stiffly Date: Tue, 13 Oct 2015 15:22:11 +0200 Subject: [PATCH 1/6] "Lightening" particle bugg fixed. Scale and alpha interpolation implemented through ScalarInterpolation-funtion --- include/Physics/CParticle.h | 4 +- include/Physics/CParticleEmitter.h | 4 + include/Physics/ECreateParticleSequence.h | 5 +- include/Physics/PhysicsSystem.h | 65 +- src/game/Game/LevelSystem.cpp | 10 +- src/game/Physics/PhysicsSystem.cpp | 1528 +++++++++++---------- 6 files changed, 835 insertions(+), 781 deletions(-) diff --git a/include/Physics/CParticle.h b/include/Physics/CParticle.h index faa8267..c0247f1 100755 --- a/include/Physics/CParticle.h +++ b/include/Physics/CParticle.h @@ -33,8 +33,10 @@ namespace Components struct Particle : public Component { + EntityID ParticleSystem; float Radius = 0.5f; - float LifeTime = 5.0f; + double TimeLived = 0; + double LifeTime = 5; ParticleFlags::Type Flags = static_cast( ParticleFlags::Water diff --git a/include/Physics/CParticleEmitter.h b/include/Physics/CParticleEmitter.h index 8b6029f..507114c 100755 --- a/include/Physics/CParticleEmitter.h +++ b/include/Physics/CParticleEmitter.h @@ -22,6 +22,10 @@ struct ParticleEmitter : public Component float Speed = 2.f; double LifeTime = 100; + //values to interpolate between. + std::vector RadiusValues; + std::vector AlphaValues; + //System variables float GravityScale = 1.0f; }; diff --git a/include/Physics/ECreateParticleSequence.h b/include/Physics/ECreateParticleSequence.h index 82731bc..8f27fcb 100644 --- a/include/Physics/ECreateParticleSequence.h +++ b/include/Physics/ECreateParticleSequence.h @@ -24,12 +24,15 @@ struct CreateParticleSequence : public Event float MaxCount = 0; glm::vec4 Color = glm::vec4(0); EntityID parent = 0; + // values to interpolate between. + std::vector RadiusValues; + std::vector AlphaValues; //Particle std::string SpriteFile = ""; double ParticleLifeTime = 3.f; ParticleFlags::Type Flags = static_cast(ParticleFlags::Powder | ParticleFlags::ParticleContactFilter | ParticleFlags::FixtureContactFilter); - float Radius = 1.f; + }; } diff --git a/include/Physics/PhysicsSystem.h b/include/Physics/PhysicsSystem.h index ec5b618..237ebe1 100755 --- a/include/Physics/PhysicsSystem.h +++ b/include/Physics/PhysicsSystem.h @@ -49,7 +49,7 @@ namespace dd class PhysicsSystem : public System { friend class ContractListener; - friend class DestructionListener; + //friend class DestructionListener; public: PhysicsSystem(World* world, std::shared_ptr eventBroker) @@ -107,6 +107,7 @@ namespace dd b2ParticleSystem* CreateParticleSystem(float radius, float gravityScale, int maxCount); void CreateParticleEmitter(EntityID entity); void UpdateParticleEmitters(double dt); //TODO: Remove them and particles if needed. + float ScalarInterpolation(float timeProgress, std::vector spectrum); EventRelay m_SetImpulse; bool SetImpulse(const Events::SetImpulse &event); @@ -131,36 +132,36 @@ namespace dd std::list m_Impulses; - class DestructionListener : public b2DestructionListener - { - public: - DestructionListener(PhysicsSystem* physicsSystem) - : m_PhysicsSystem(physicsSystem) { } - - void SayGoodbye(b2Joint*) {LOG_INFO("joint körs");}; - void SayGoodbye(b2Fixture*) {/*LOG_INFO("Fixture körs");*/}; - - void SayGoodbye(b2ParticleSystem* particleSystem, int32 index) override - { - LOG_INFO("Particle ded"); - - - const b2ParticleHandle* handle = particleSystem->GetParticleHandleFromIndex(index); - for (int i = 0; i < m_PhysicsSystem->m_ParticleEmitters.ParticleSystem.size(); i++) { - if(m_PhysicsSystem->m_ParticleEmitters.ParticleSystem[i] == particleSystem) { - std::unordered_map::iterator it = m_PhysicsSystem->m_ParticleHandleToEntities[i].find(handle); - if(it != m_PhysicsSystem->m_ParticleHandleToEntities[i].end()) { - EntityID id = it->second; - m_PhysicsSystem->m_World->RemoveEntity(id); - m_PhysicsSystem->m_ParticleHandleToEntities[i].erase(it); - LOG_INFO("Removing from list"); - } - } - } - } - private: - PhysicsSystem* m_PhysicsSystem; - }; +// class DestructionListener : public b2DestructionListener +// { +// public: +// DestructionListener(PhysicsSystem* physicsSystem) +// : m_PhysicsSystem(physicsSystem) { } +// +// void SayGoodbye(b2Joint*) {LOG_INFO("joint körs");}; +// void SayGoodbye(b2Fixture*) {/*LOG_INFO("Fixture körs");*/}; +// +// void SayGoodbye(b2ParticleSystem* particleSystem, int32 index) override +// { +// // LOG_INFO("Particle ded"); +// // +// // +// // const b2ParticleHandle* handle = particleSystem->GetParticleHandleFromIndex(index); +// // for (int i = 0; i < m_PhysicsSystem->m_ParticleEmitters.ParticleSystem.size(); i++) { +// // if(m_PhysicsSystem->m_ParticleEmitters.ParticleSystem[i] == particleSystem) { +// // std::unordered_map::iterator it = m_PhysicsSystem->m_ParticleHandleToEntities[i].find(handle); +// // if(it != m_PhysicsSystem->m_ParticleHandleToEntities[i].end()) { +// // EntityID id = it->second; +// // m_PhysicsSystem->m_World->RemoveEntity(id); +// // m_PhysicsSystem->m_ParticleHandleToEntities[i].erase(it); +// // LOG_INFO("Removing from list"); +// // } +// // } +// // } +// } +// private: +// PhysicsSystem* m_PhysicsSystem; +// }; class ParticleContactDisabler : public b2ContactFilter { @@ -198,7 +199,7 @@ namespace dd PhysicsSystem* m_PhysicsSystem; }; - DestructionListener* m_DestructionListener; + //DestructionListener* m_DestructionListener; ParticleContactDisabler* m_ParticleContactDisabler; ContactListener* m_ContactListener; }; diff --git a/src/game/Game/LevelSystem.cpp b/src/game/Game/LevelSystem.cpp index 6a6f1fd..9624d22 100755 --- a/src/game/Game/LevelSystem.cpp +++ b/src/game/Game/LevelSystem.cpp @@ -314,9 +314,12 @@ bool dd::Systems::LevelSystem::OnContact(const dd::Events::Contact &event) ep.EmittingAngle = glm::half_pi(); ep.Spread = 1.5f; ep.Position = transformComponentBrick->Position; - ep.Radius = 0.05; + //ep.Radius = 0.05; ep.SpriteFile = "Textures/Particles/FadeBall.png"; ep.Color = brickModel->Color + glm::vec4(0.3f); + ep.AlphaValues.push_back(1.f); + ep.AlphaValues.push_back(0.f); + ep.RadiusValues.push_back(0.05); ep.Speed = 50; EventBroker->Publish(ep); @@ -369,9 +372,12 @@ bool dd::Systems::LevelSystem::OnContact(const dd::Events::Contact &event) ep.EmittingAngle = glm::half_pi(); ep.Spread = 1.5f; ep.Position = transformComponentBrick->Position; - ep.Radius = 0.05; + //ep.Radius = 0.05; ep.SpriteFile = "Textures/Particles/FadeBall.png"; ep.Color = brickModel->Color + glm::vec4(0.3f); + ep.AlphaValues.push_back(1.f); + ep.AlphaValues.push_back(0.f); + ep.RadiusValues.push_back(0.05f); ep.Speed = 50; EventBroker->Publish(ep); diff --git a/src/game/Physics/PhysicsSystem.cpp b/src/game/Physics/PhysicsSystem.cpp index 94778d1..6eaa68a 100755 --- a/src/game/Physics/PhysicsSystem.cpp +++ b/src/game/Physics/PhysicsSystem.cpp @@ -1,745 +1,783 @@ -#include "PrecompiledHeader.h" -#include "Physics/PhysicsSystem.h" - - -void dd::Systems::PhysicsSystem::RegisterComponents(ComponentFactory* cf) -{ - cf->Register(); - //TODO: REGISTER PHYSICS COMPONENTS HERE -} - -void dd::Systems::PhysicsSystem::Initialize() -{ - std::random_device rd; - gen = std::mt19937(rd()); - m_DestructionListener = new DestructionListener(this); - m_ContactListener = new ContactListener(this); - m_PhysicsWorld = new b2World(m_Gravity); - m_ParticleContactDisabler = new ParticleContactDisabler(); - m_PhysicsWorld->SetContactListener(m_ContactListener); - m_PhysicsWorld->SetContactFilter(m_ParticleContactDisabler); - m_PhysicsWorld->SetDestructionListener(m_DestructionListener); - - InitializeWater(); - EVENT_SUBSCRIBE_MEMBER(m_SetImpulse, &PhysicsSystem::SetImpulse); - EVENT_SUBSCRIBE_MEMBER(m_EPause, &PhysicsSystem::OnPause); - EVENT_SUBSCRIBE_MEMBER(m_EStageCleared, &PhysicsSystem::OnStageCleared); - EVENT_SUBSCRIBE_MEMBER(m_ECreateParticleSequence, &PhysicsSystem::CreateParticleSequence); - EVENT_SUBSCRIBE_MEMBER(m_EContact, &PhysicsSystem::OnContact); -} - -void dd::Systems::PhysicsSystem::InitializeWater() -{ - float radius = 0.13f; - float gravityScale = 1.0f; - - b2ParticleSystemDef m_ParticleSystemDef; - m_ParticleSystemDef.radius = radius; - m_ParticleSystemDef.gravityScale = gravityScale; - m_ParticleSystemDef.density = 4.f; - - m_WaterParticleSystem = m_PhysicsWorld->CreateParticleSystem(&m_ParticleSystemDef); -} - -bool dd::Systems::PhysicsSystem::SetImpulse(const Events::SetImpulse &event) -{ - auto it = m_EntitiesToBodies.find(event.Entity); - if(it == m_EntitiesToBodies.end()) { - LOG_ERROR("Entity: %i, Tried to set an impulse on a body that does not exsist", event.Entity); - return false; - } - - b2Vec2 impulse; - impulse.x = event.Impulse.x; - impulse.y = event.Impulse.y; - - b2Vec2 point; - point.x = event.Point.x; - point.y = event.Point.y; - - Impulse i; - i.Body = it->second; - i.Vector = impulse; - i.Point = point; - - m_Impulses.push_back(i); - return true; -} - -void dd::Systems::PhysicsSystem::SyncEntitiesWithBodies() -{ - - for (auto i : m_EntitiesToBodies) { - EntityID entity = i.first; - b2Body* body = i.second; - - if (body == nullptr) { - LOG_ERROR("This body should not exist, please fix this"); - continue; - } - - auto transformComponent = m_World->GetComponent(entity); - if (! transformComponent) { - continue; - LOG_ERROR("RigidBody with no TransformComponent"); - } - - auto physicsComponent = m_World->GetComponent(entity); - if (! physicsComponent) { - continue; - LOG_ERROR("RigidBody with no PhysicsComponent"); - } - - - - if (m_World->GetEntityParent(entity) == 0) { //TODO: Make this work with childs too - b2Vec2 position; - position.x = transformComponent->Position.x; - position.y = transformComponent->Position.y; - float angle = glm::eulerAngles(transformComponent->Orientation).z; - body->SetTransform(position, angle); - body->SetLinearVelocity(b2Vec2(transformComponent->Velocity.x, transformComponent->Velocity.y)); - body->SetGravityScale(physicsComponent->GravityScale); - - b2Filter filter; - filter.categoryBits = physicsComponent->Category; - filter.maskBits = physicsComponent->Mask; - body->GetFixtureList()->SetFilterData(filter); - - if (physicsComponent->CollisionType == CollisionType::Type::Static) { - body->SetType(b2_staticBody); - } - else if (physicsComponent->CollisionType == CollisionType::Type::Dynamic) { - body->SetType(b2_dynamicBody); - } - else if (physicsComponent->CollisionType == CollisionType::Type::Kinematic) { - body->SetType(b2_dynamicBody); - } - } - } -} - -void dd::Systems::PhysicsSystem::SyncBodiesWithEntities() -{ - for (auto i : m_BodiesToEntities) { - b2Body* body = i.first; - EntityID entity = i.second; - - if (body == nullptr) { - LOG_ERROR("This body should not exist, please fix this"); - continue; - } - - auto transformComponent = m_World->GetComponent(entity); - if (! transformComponent) { - continue; - LOG_ERROR("RigidBody with no TransformComponent"); - } - - auto physicsComponent = m_World->GetComponent(entity); - if (! physicsComponent) { - continue; - LOG_ERROR("RigidBody with no PhysicsComponent"); - } - - auto parent = m_World->GetEntityParent(entity); - if (parent == 0) { - auto physicsComponent = m_World->GetComponent(entity); - - if (physicsComponent->Calculate) { //TODO: REPLACE THIS WITH PARTICLE COLLISION FILTERS - transformComponent->Position.x = transformComponent->Position.x + (transformComponent->Velocity.x * m_TimeStep); - transformComponent->Position.y = transformComponent->Position.y + (transformComponent->Velocity.y * m_TimeStep); - } else { - b2Vec2 position = body->GetPosition(); - transformComponent->Position.x = position.x; - transformComponent->Position.y = position.y; - - float angle = body->GetAngle(); - transformComponent->Orientation = glm::quat(glm::vec3(0, 0, angle)); - - b2Vec2 velocity = body->GetLinearVelocity(); - transformComponent->Velocity.x = velocity.x; - transformComponent->Velocity.y = velocity.y; - } - } - } -} - -void dd::Systems::PhysicsSystem::Update(double dt) -{ - if (m_Pause) { - return; - } - - if (m_Travelling) { - if (m_DistanceTravelled > 12.f) { - m_DistanceTravelled = 0; - m_Travelling = false; - } - - m_DistanceTravelled += 6.0f * dt; - } - m_Accumulator += dt; - - while(m_Accumulator >= m_TimeStep) - { - - UpdateParticleEmitters(dt); - SyncEntitiesWithBodies(); - - //Apply Impulses Must be done after SyncEntitiesWithBodies - for (auto i : m_Impulses) { - i.Body->ApplyLinearImpulse(i.Vector, i.Point, true); - } - m_Impulses.clear(); - - - //Update the PhysicsWorld - m_PhysicsWorld->Step(m_TimeStep, m_VelocityIterations, m_PositionIterations); - - SyncBodiesWithEntities(); - - - //water - b2Vec2 *positionBuffer = m_WaterParticleSystem->GetPositionBuffer(); - for (auto i : m_EntitiesToWaterParticleHandle){ - EntityID entity = i.first; - const b2ParticleHandle *particleH = i.second; - - - b2Vec2 positionB2 = positionBuffer[particleH->GetIndex()]; - glm::vec2 position = glm::vec2(positionB2.x, positionB2.y); - - EntityID entityParent = m_World->GetEntityParent(entity); - glm::vec3 parentTransform = glm::vec3(0.f); - if(entityParent) { - auto tp = m_World->GetComponent(entityParent); - parentTransform = tp->Position; - } - auto transform = m_World->GetComponent(entity); - - transform->Position = glm::vec3(position.x - parentTransform.x, position.y - parentTransform.y, 0); - } - - //Normal particles - for ( int e = 0; e < m_EntitiesToParticleHandle.size(); e++) { - b2Vec2 *positionBuffer = m_ParticleEmitters.ParticleSystem[e]->GetPositionBuffer(); - if(!positionBuffer) { - break; - } - for (auto i : m_EntitiesToParticleHandle[e]){ - EntityID entity = i.first; - const b2ParticleHandle *particleH = i.second; - - b2Vec2 positionB2 = positionBuffer[particleH->GetIndex()]; - glm::vec2 position = glm::vec2(positionB2.x, positionB2.y); - - EntityID entityParent = m_World->GetEntityParent(entity); - glm::vec3 parentTransform = glm::vec3(0.f); - if(entityParent) { - auto tp = m_World->GetComponent(entityParent); - parentTransform = tp->Position; - } - auto transform = m_World->GetComponent(entity); - - transform->Position = glm::vec3(position.x, position.y, transform->Position.z); - } - } - - m_Accumulator -= dt; - } -} - -void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) -{ - if (m_Travelling) { - auto transform = m_World->GetComponent(entity); - if (transform != nullptr) { - if (!transform->Sticky) { - transform->Position.y -= 6.0f * dt; - } - } else { - transform->Position.y -= 6.0f * dt; - } - } - auto particle = m_World->GetComponent(entity); - auto pTemplate = m_World->GetComponent(entity); - - - - if (particle && !pTemplate) { - particle->LifeTime -= dt; - if (particle->LifeTime <= 0) { - for (int i = 0; i < m_EntitiesToParticleHandle.size(); i++) { - const b2ParticleHandle* handle = m_EntitiesToParticleHandle[i][entity]; - std::unordered_map::iterator iter1; - std::unordered_map::iterator iter2; - iter1 = m_EntitiesToParticleHandle[i].find(entity); - iter2 = m_ParticleHandleToEntities[i].find(handle); - if (iter1 != m_EntitiesToParticleHandle[i].end()) { - m_EntitiesToParticleHandle[i].erase(iter1); - } - if (iter2 != m_ParticleHandleToEntities[i].end()) { - m_ParticleHandleToEntities[i].erase(iter2); - } - m_World->RemoveEntity(entity); - } - } - auto sprite = m_World->GetComponent(entity); - sprite->Color.w = particle->LifeTime; - } - - auto emitter = m_World->GetComponent(entity); - if (emitter) { - EntityID emitterParent = emitter->Parent; - if (emitterParent != 0) { - auto emitterTransform = m_World->GetComponent(entity); - auto parentTransform = m_World->GetComponent(emitterParent); - if (emitterTransform && parentTransform) { - emitterTransform->Position = parentTransform->Position; - } - } - } -} - -bool dd::Systems::PhysicsSystem::OnPause(const dd::Events::Pause &event) -{ - if (event.Type != "PhysicsSystem" && event.Type != "All") { - return false; - } - - if (m_Pause) { - m_Pause = false; - } else { - m_Pause = true; - } - return true; -} - -void dd::Systems::PhysicsSystem::OnEntityCommit(EntityID entity) -{ - auto physicsComponent = m_World->GetComponent(entity); - auto waterComponent = m_World->GetComponent(entity); - auto particleEmitterComponent = m_World->GetComponent(entity); - - if (physicsComponent && waterComponent) { - LOG_ERROR("Entity has both water and physics component, this is illegal. The police has been alerted."); - return; - } - if (physicsComponent && particleEmitterComponent) { - LOG_ERROR("Entity has both particle and physics component, this is illegal. The police has been alerted."); - return; - } - - if (physicsComponent) { - auto it = m_EntitiesToBodies.find(entity); - if(it == m_EntitiesToBodies.end()) { - CreateBody(entity); - } else { - LOG_ERROR("Tried to commit a body that already exists"); - } - } else if (waterComponent) { - CreateParticleGroup(entity); - } else if (particleEmitterComponent) { - CreateParticleEmitter(entity); - } -} - - -void dd::Systems::PhysicsSystem::OnEntityRemoved(EntityID entity) -{ - auto it = m_EntitiesToBodies.find(entity); - if(it != m_EntitiesToBodies.end()) { - it->second->GetWorld()->DestroyBody(it->second); - m_BodiesToEntities.erase(it->second); - m_EntitiesToBodies.erase(entity); - } - -} - - -bool dd::Systems::PhysicsSystem::OnStageCleared(const dd::Events::StageCleared &event) -{ - if (event.ClearedStage < 5) { - m_Travelling = true; - } - return true; -} - - -void dd::Systems::PhysicsSystem::CreateBody(EntityID entity) -{ - auto physicsComponent = m_World->GetComponent(entity); - if(!physicsComponent){ - LOG_ERROR("No PhysicsComponent in CreateBody"); - return; - } - - auto transformComponent = m_World->GetComponent(entity); - if(!transformComponent) { - LOG_ERROR("No TransformComponent in CreateBody"); - return; - } - - auto absoluteTransform = m_World->GetSystem()->AbsoluteTransform(entity); - - b2BodyDef bodyDef; - bodyDef.position.Set(absoluteTransform.Position.x, absoluteTransform.Position.y); - bodyDef.angle = -glm::eulerAngles(absoluteTransform.Orientation).z; - - if (physicsComponent->CollisionType == CollisionType::Type::Static) { - bodyDef.type = b2_staticBody; - } else if (physicsComponent->CollisionType == CollisionType::Type::Dynamic) { - bodyDef.type = b2_dynamicBody; - } else if (physicsComponent->CollisionType == CollisionType::Type::Kinematic) { - bodyDef.type = b2_dynamicBody; - } - - b2Body* body = m_PhysicsWorld->CreateBody(&bodyDef); - - b2Shape* pShape; - - auto rectangleComponent = m_World->GetComponent(entity); - if (rectangleComponent) { - b2PolygonShape* bShape = new b2PolygonShape(); - bShape->SetAsBox(rectangleComponent->Dimensions.x/2.f, rectangleComponent->Dimensions.y/2.f); - pShape = bShape; - } else { - auto circleComponent = m_World->GetComponent(entity); - if (circleComponent) { - pShape = new b2CircleShape(); - pShape->m_radius = circleComponent->Radius; - } - } - - b2FixtureDef fixtureDef; - fixtureDef.shape = pShape; - fixtureDef.filter.categoryBits = physicsComponent->Category; - fixtureDef.filter.maskBits = physicsComponent->Mask; - - - - fixtureDef.shape = pShape; - fixtureDef.density = physicsComponent->Density; - fixtureDef.restitution = 1.0f; - fixtureDef.friction = 0.0f; - body->CreateFixture(&fixtureDef); - - - delete pShape; - - body->SetGravityScale(physicsComponent->GravityScale); - m_EntitiesToBodies.insert(std::make_pair(entity, body)); - m_BodiesToEntities.insert(std::make_pair(body, entity)); -} - - -void dd::Systems::PhysicsSystem::CreateParticleGroup(EntityID e) -{ - auto transform = m_World->GetComponent(e); - if (!transform) { - LOG_ERROR("No Transform component in CreateParticleGroup"); - } - b2ParticleGroupDef pd; - b2PolygonShape shape; - auto water = m_World->GetComponent(e); - if (water) { - - shape.SetAsBox(transform->Scale.x/2.f, transform->Scale.y/2.f); - pd.shape = &shape; - pd.flags = b2_tensileParticle; - pd.position.Set(transform->Position.x, transform->Position.y); - t_ParticleGroup.push_back(m_WaterParticleSystem->CreateParticleGroup(pd)); - b2Vec2* t_ParticlePositions = m_WaterParticleSystem->GetPositionBuffer(); - for(int i = 0; i < m_WaterParticleSystem->GetParticleCount(); i++){ - { - auto t_waterparticle = m_World->CreateEntity(e); - auto transformChild = m_World->AddComponent(t_waterparticle); - - transformChild->Position = glm::vec3(t_ParticlePositions[i].x - transform->Position.x, t_ParticlePositions[i].y - transform->Position.y, -9.5f); - transformChild->Scale = glm::vec3(m_WaterParticleSystem->GetRadius())/transform->Scale; - m_World->CommitEntity(t_waterparticle); - - m_EntitiesToWaterParticleHandle.insert(std::make_pair(t_waterparticle, m_WaterParticleSystem->GetParticleHandleFromIndex(i))); - m_WaterParticleHandleToEntities.insert(std::make_pair(m_WaterParticleSystem->GetParticleHandleFromIndex(i), t_waterparticle)); - } - - } - - } -} - - -void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) -{ - std::vector emittersToDelete; - int pSizeTest = 0; //For debugging, delete this - int psListSize = 0; - for (int i = 0; i < m_ParticleEmitters.ParticleSystem.size(); i++) { - auto e = m_ParticleEmitters.ParticleEmitter[i]; - auto pt = m_ParticleEmitters.ParticleTemplate[i]; - auto ps = m_ParticleEmitters.ParticleSystem[i]; - pSizeTest += ps->GetParticleCount(); - psListSize++; - auto emitter = m_World->GetComponent(e); - auto particleTemplate = m_World->GetComponent(pt); - if(!emitter) { - LOG_INFO("ParticleEmitter Component is nil"); - continue; - } - if(!particleTemplate) { - LOG_INFO("ParticleTemplate Component is nil."); - continue; - } - auto emitterTransform = m_World->GetComponent(e); - emitterTransform->Orientation = glm::rotate(glm::quat(), 3.f, glm::vec3(0.f, 0.f, -1.f)); - - emitter->TimeSinceLastSpawn += dt; - emitter->LifeTime -= dt; - - if (emitter->LifeTime <= 0 || emitter->NumberOfTicks <= 0) { - emittersToDelete.push_back(e); - continue; - } - if(emitter->TimeSinceLastSpawn < emitter->SpawnRate || emitter->NumberOfTicks < 1) { - continue; - } - emitter->NumberOfTicks--; - emitter->TimeSinceLastSpawn -= emitter->SpawnRate; - auto templateTransform = m_World->GetComponent(pt); - b2ParticleDef particleDef; - for ( int j = 0; j < emitter->ParticlesPerTick; j++) { - particleDef.flags = particleTemplate->Flags; - //particleDef.color TODO: Implement this if we want color mixing and shit. - particleDef.lifetime = particleTemplate->LifeTime; - float eAngle = emitter->EmittingAngle; - float halfSpread = emitter->Spread / 2; - - std::uniform_real_distribution dis(eAngle - halfSpread, eAngle + halfSpread); - float pAngle = dis(gen); - std::uniform_real_distribution dis2(0.3, 1.5); - float speedMultiplier = dis2(gen); - glm::vec2 unitVec = glm::normalize(glm::vec2(glm::cos(pAngle), glm::sin(pAngle))); - glm::vec2 vel = unitVec * emitter->Speed * (float)dt * speedMultiplier * 0.5f; - particleDef.velocity = b2Vec2(vel.x, vel.y); - particleDef.position = b2Vec2(emitterTransform->Position.x, emitterTransform->Position.y); - - - auto particle = m_World->CloneEntity(pt, 0); - m_World->RemoveComponent(particle); - auto transform2 = m_World->GetComponent(particle); - - std::uniform_real_distribution dist(0, 1); - float zDistribution = dist(gen); - transform2->Position = glm::vec3(emitterTransform->Position.x, emitterTransform->Position.y, -9.5f + zDistribution); - transform2->Scale = glm::vec3(particleTemplate->Radius * 2.f / speedMultiplier, particleTemplate->Radius * 2.f / speedMultiplier, 1); - - - auto b2Particle = ps->CreateParticle(particleDef); - - auto b2ParticleHandle = ps->GetParticleHandleFromIndex(b2Particle); - m_EntitiesToParticleHandle[i].insert(std::make_pair(particle, b2ParticleHandle)); - m_ParticleHandleToEntities[i].insert(std::make_pair(b2ParticleHandle, particle)); - - - } - - } -// system("cls"); -// std::cout << "Particles living: " << pSizeTest << std::endl; -// std::cout << "particle systems: " << psListSize << std::endl; -// int entHandles = 0; -// for (int i = 0; i < m_EntitiesToParticleHandle.size(); i++) -// entHandles += m_EntitiesToParticleHandle[i].size(); -// std::cout << "Entities and handles: " << entHandles << std::endl; -// LOG_INFO("Particles living: %i", pSizeTest); -// LOG_INFO("Particle systems: %i", psListSize); -// int entHandles = 0; -// for (int i = 0; i < m_EntitiesToParticleHandle.size(); i++) -// entHandles += m_EntitiesToParticleHandle[i].size(); -// LOG_INFO("Entities and handles: %i", entHandles); - - - for (int i = 0; i < emittersToDelete.size(); i++) - { - EntityID ent = emittersToDelete[i]; - int key; - for(key = 0; key < m_ParticleEmitters.ParticleEmitter.size(); key++) { - if (m_ParticleEmitters.ParticleEmitter[key] == ent) { - break; - } - } - - if (m_ParticleEmitters.ParticleSystem[key]->GetParticleCount() == 0 && key <= m_ParticleEmitters.ParticleSystem.size()) { - m_World->RemoveEntity(ent); - m_PhysicsWorld->DestroyParticleSystem(m_ParticleEmitters.ParticleSystem[key]); - m_ParticleEmitters.ParticleSystem.erase(m_ParticleEmitters.ParticleSystem.begin() + key); - m_ParticleEmitters.ParticleEmitter.erase(m_ParticleEmitters.ParticleEmitter.begin() + key); - m_ParticleEmitters.ParticleTemplate.erase(m_ParticleEmitters.ParticleTemplate.begin() + key); - m_EntitiesToParticleHandle.erase(m_EntitiesToParticleHandle.begin() + key); - m_ParticleHandleToEntities.erase(m_ParticleHandleToEntities.begin() + key); - } - } - - - - int stp = 0; - for (auto ts : m_EntitiesToParticleHandle) - { - stp += ts.size(); - } -} - -bool dd::Systems::PhysicsSystem::CreateParticleSequence(const Events::CreateParticleSequence &event) -{ - //Creating Emitter - EntityID emitter = m_World->CreateEntity(); - - auto emitterTransform = m_World->AddComponent(emitter); - auto particleEmitter= m_World->AddComponent(emitter); - - if (event.parent != 0) { - particleEmitter->Parent = event.parent; - } - - emitterTransform->Position = event.Position; - particleEmitter->GravityScale = event.GravityScale; - particleEmitter->SpawnRate = event.SpawnRate; - particleEmitter->NumberOfTicks = event.NumberOfTicks; - particleEmitter->Speed = event.Speed; - particleEmitter->ParticlesPerTick = event.ParticlesPerTick; - particleEmitter->Spread = event.Spread; - particleEmitter->EmittingAngle = event.EmittingAngle; - particleEmitter->LifeTime = event.EmitterLifeTime; - - { - //Creating Particle Template - auto particle = m_World->CreateEntity(emitter); - auto particleTransform = m_World->AddComponent(particle); - auto sprite = m_World->AddComponent(particle); - auto particleComponent = m_World->AddComponent(particle); - m_World->AddComponent(particle); - - particleTransform->Position = emitterTransform->Position; - sprite->SpriteFile = event.SpriteFile; - sprite->Color = event.Color; - particleComponent->LifeTime = event.ParticleLifeTime; - particleComponent->Flags = event.Flags; - particleComponent->Radius = event.Radius; - } - m_World->CommitEntity(emitter); - return true; -} - -void dd::Systems::PhysicsSystem::CreateParticleEmitter(EntityID entity) -{ - auto childEntities = m_World->GetEntityChildren(entity); - if (childEntities.empty()) { - LOG_ERROR("Particle Emitter does not have any child. Please adopt one or this will not work."); - return; - } - int pf = 0; - dd::Components::Particle* particle; - EntityID childEntity; - for ( auto c : childEntities ) { - auto p = m_World->GetComponent(c); - auto particleTemplate = m_World->GetComponent(c); - if (!p) { - continue; - LOG_WARNING("ParticleEmitter's Child is not a particle."); - } - if(!particleTemplate) { - LOG_ERROR("ParticleEmitter's particleChild is not a template."); - continue; - } - if (pf != 0) { - LOG_WARNING("ParticleEmitter has more than one child that is a particleTemplate, only the first one is used."); - break; - } - childEntity = c; - particle = p; - pf++; - } - //TODO: Skicka med fler flaggor till particlesystemet; - - m_ParticleEmitters.ParticleSystem.push_back(CreateParticleSystem(particle->Radius, 0.f, 0)); - m_ParticleEmitters.ParticleEmitter.push_back(entity); - m_ParticleEmitters.ParticleTemplate.push_back(childEntity); -} - - -b2ParticleSystem* dd::Systems::PhysicsSystem::CreateParticleSystem(float radius, float gravityScale, int maxCount) -{ - std::unordered_map m1; - std::unordered_map m2; - m_EntitiesToParticleHandle.push_back(m1); - m_ParticleHandleToEntities.push_back(m2); - - b2ParticleSystemDef m_ParticleSystemDef; - m_ParticleSystemDef.maxCount = maxCount; - m_ParticleSystemDef.radius = radius; - m_ParticleSystemDef.gravityScale = gravityScale; - m_ParticleSystemDef.destroyByAge = true; - - return m_PhysicsWorld->CreateParticleSystem(&m_ParticleSystemDef); -} - -bool dd::Systems::PhysicsSystem::OnContact(const dd::Events::Contact &event) -{ - //Check if it is a brick colliding - auto brick = m_World->GetComponent(event.Entity1); - Components::Model* model; - - if (!brick) { - brick = m_World->GetComponent(event.Entity2); - if (!brick) { - return false; - } - else { - model = m_World->GetComponent(event.Entity2); - } - } - else { - model = m_World->GetComponent(event.Entity1); - } - Events::CreateParticleSequence e; - e.EmitterLifeTime = 4; - //- glm::atan(event.Normal.x, event.Normal.y - e.EmittingAngle = glm::half_pi(); - e.Spread = 0.5f; - e.NumberOfTicks = 1; - e.ParticleLifeTime = 1.f; - e.ParticlesPerTick = 15; - e.Position = glm::vec3(event.IntersectionPoint.x, event.IntersectionPoint.y, -10); - e.Radius = 0.2f; - e.SpriteFile = "Textures/Particles/Cloud_Particle.png"; - e.Color = model->Color + glm::vec4(0.5f); - e.Speed = 100; - EventBroker->Publish(e); - return true; -} - - -dd::Systems::PhysicsSystem::~PhysicsSystem() -{ - for (auto i = m_BodiesToEntities.begin(); i != m_BodiesToEntities.end(); i++) { - b2Body* body = i->first; - body->GetWorld()->DestroyBody(body); - //delete body; - } - m_BodiesToEntities.clear(); - m_EntitiesToBodies.clear(); - m_Impulses.clear(); - - //TODO:REMOVE PARTICLE SYSTEMS - - if (m_ContactListener != nullptr) { - delete m_ContactListener; - m_ContactListener = nullptr; - } - - if (m_PhysicsWorld != nullptr) { - delete m_PhysicsWorld; - m_PhysicsWorld = nullptr; - } -} +#include "PrecompiledHeader.h" +#include "Physics/PhysicsSystem.h" + + +void dd::Systems::PhysicsSystem::RegisterComponents(ComponentFactory* cf) +{ + cf->Register(); + //TODO: REGISTER PHYSICS COMPONENTS HERE +} + +void dd::Systems::PhysicsSystem::Initialize() +{ + std::random_device rd; + gen = std::mt19937(rd()); +// m_DestructionListener = new DestructionListener(this); + m_ContactListener = new ContactListener(this); + m_PhysicsWorld = new b2World(m_Gravity); + m_ParticleContactDisabler = new ParticleContactDisabler(); + m_PhysicsWorld->SetContactListener(m_ContactListener); + m_PhysicsWorld->SetContactFilter(m_ParticleContactDisabler); +// m_PhysicsWorld->SetDestructionListener(m_DestructionListener); + + InitializeWater(); + EVENT_SUBSCRIBE_MEMBER(m_SetImpulse, &PhysicsSystem::SetImpulse); + EVENT_SUBSCRIBE_MEMBER(m_EPause, &PhysicsSystem::OnPause); + EVENT_SUBSCRIBE_MEMBER(m_EStageCleared, &PhysicsSystem::OnStageCleared); + EVENT_SUBSCRIBE_MEMBER(m_ECreateParticleSequence, &PhysicsSystem::CreateParticleSequence); + EVENT_SUBSCRIBE_MEMBER(m_EContact, &PhysicsSystem::OnContact); +} + +void dd::Systems::PhysicsSystem::InitializeWater() +{ + float radius = 0.13f; + float gravityScale = 1.0f; + + b2ParticleSystemDef m_ParticleSystemDef; + m_ParticleSystemDef.radius = radius; + m_ParticleSystemDef.gravityScale = gravityScale; + m_ParticleSystemDef.density = 4.f; + + m_WaterParticleSystem = m_PhysicsWorld->CreateParticleSystem(&m_ParticleSystemDef); +} + +bool dd::Systems::PhysicsSystem::SetImpulse(const Events::SetImpulse &event) +{ + auto it = m_EntitiesToBodies.find(event.Entity); + if(it == m_EntitiesToBodies.end()) { + LOG_ERROR("Entity: %i, Tried to set an impulse on a body that does not exsist", event.Entity); + return false; + } + + b2Vec2 impulse; + impulse.x = event.Impulse.x; + impulse.y = event.Impulse.y; + + b2Vec2 point; + point.x = event.Point.x; + point.y = event.Point.y; + + Impulse i; + i.Body = it->second; + i.Vector = impulse; + i.Point = point; + + m_Impulses.push_back(i); + return true; +} + +void dd::Systems::PhysicsSystem::SyncEntitiesWithBodies() +{ + + for (auto i : m_EntitiesToBodies) { + EntityID entity = i.first; + b2Body* body = i.second; + + if (body == nullptr) { + LOG_ERROR("This body should not exist, please fix this"); + continue; + } + + auto transformComponent = m_World->GetComponent(entity); + if (! transformComponent) { + continue; + LOG_ERROR("RigidBody with no TransformComponent"); + } + + auto physicsComponent = m_World->GetComponent(entity); + if (! physicsComponent) { + continue; + LOG_ERROR("RigidBody with no PhysicsComponent"); + } + + + + if (m_World->GetEntityParent(entity) == 0) { //TODO: Make this work with childs too + b2Vec2 position; + position.x = transformComponent->Position.x; + position.y = transformComponent->Position.y; + float angle = glm::eulerAngles(transformComponent->Orientation).z; + body->SetTransform(position, angle); + body->SetLinearVelocity(b2Vec2(transformComponent->Velocity.x, transformComponent->Velocity.y)); + body->SetGravityScale(physicsComponent->GravityScale); + + b2Filter filter; + filter.categoryBits = physicsComponent->Category; + filter.maskBits = physicsComponent->Mask; + body->GetFixtureList()->SetFilterData(filter); + + if (physicsComponent->CollisionType == CollisionType::Type::Static) { + body->SetType(b2_staticBody); + } + else if (physicsComponent->CollisionType == CollisionType::Type::Dynamic) { + body->SetType(b2_dynamicBody); + } + else if (physicsComponent->CollisionType == CollisionType::Type::Kinematic) { + body->SetType(b2_dynamicBody); + } + } + } +} + +void dd::Systems::PhysicsSystem::SyncBodiesWithEntities() +{ + for (auto i : m_BodiesToEntities) { + b2Body* body = i.first; + EntityID entity = i.second; + + if (body == nullptr) { + LOG_ERROR("This body should not exist, please fix this"); + continue; + } + + auto transformComponent = m_World->GetComponent(entity); + if (! transformComponent) { + continue; + LOG_ERROR("RigidBody with no TransformComponent"); + } + + auto physicsComponent = m_World->GetComponent(entity); + if (! physicsComponent) { + continue; + LOG_ERROR("RigidBody with no PhysicsComponent"); + } + + auto parent = m_World->GetEntityParent(entity); + if (parent == 0) { + auto physicsComponent = m_World->GetComponent(entity); + + if (physicsComponent->Calculate) { //TODO: REPLACE THIS WITH PARTICLE COLLISION FILTERS + transformComponent->Position.x = transformComponent->Position.x + (transformComponent->Velocity.x * m_TimeStep); + transformComponent->Position.y = transformComponent->Position.y + (transformComponent->Velocity.y * m_TimeStep); + } else { + b2Vec2 position = body->GetPosition(); + transformComponent->Position.x = position.x; + transformComponent->Position.y = position.y; + + float angle = body->GetAngle(); + transformComponent->Orientation = glm::quat(glm::vec3(0, 0, angle)); + + b2Vec2 velocity = body->GetLinearVelocity(); + transformComponent->Velocity.x = velocity.x; + transformComponent->Velocity.y = velocity.y; + } + } + } +} + +void dd::Systems::PhysicsSystem::Update(double dt) +{ + if (m_Pause) { + return; + } + + if (m_Travelling) { + if (m_DistanceTravelled > 12.f) { + m_DistanceTravelled = 0; + m_Travelling = false; + } + + m_DistanceTravelled += 6.0f * dt; + } + m_Accumulator += dt; + + while(m_Accumulator >= m_TimeStep) + { + + UpdateParticleEmitters(dt); + SyncEntitiesWithBodies(); + + //Apply Impulses Must be done after SyncEntitiesWithBodies + for (auto i : m_Impulses) { + i.Body->ApplyLinearImpulse(i.Vector, i.Point, true); + } + m_Impulses.clear(); + + + //Update the PhysicsWorld + m_PhysicsWorld->Step(m_TimeStep, m_VelocityIterations, m_PositionIterations); + + SyncBodiesWithEntities(); + + + //water + b2Vec2 *positionBuffer = m_WaterParticleSystem->GetPositionBuffer(); + for (auto i : m_EntitiesToWaterParticleHandle){ + EntityID entity = i.first; + const b2ParticleHandle *particleH = i.second; + + + b2Vec2 positionB2 = positionBuffer[particleH->GetIndex()]; + glm::vec2 position = glm::vec2(positionB2.x, positionB2.y); + + EntityID entityParent = m_World->GetEntityParent(entity); + glm::vec3 parentTransform = glm::vec3(0.f); + if(entityParent) { + auto tp = m_World->GetComponent(entityParent); + parentTransform = tp->Position; + } + auto transform = m_World->GetComponent(entity); + + transform->Position = glm::vec3(position.x - parentTransform.x, position.y - parentTransform.y, 0); + } + + //Normal particles + for ( int e = 0; e < m_EntitiesToParticleHandle.size(); e++) { + b2Vec2 *positionBuffer = m_ParticleEmitters.ParticleSystem[e]->GetPositionBuffer(); + if(!positionBuffer) { + break; + } + for (auto i : m_EntitiesToParticleHandle[e]){ + EntityID entity = i.first; + const b2ParticleHandle *particleH = i.second; + + b2Vec2 positionB2 = positionBuffer[particleH->GetIndex()]; + glm::vec2 position = glm::vec2(positionB2.x, positionB2.y); + + EntityID entityParent = m_World->GetEntityParent(entity); + glm::vec3 parentTransform = glm::vec3(0.f); + if(entityParent) { + auto tp = m_World->GetComponent(entityParent); + parentTransform = tp->Position; + } + auto transform = m_World->GetComponent(entity); + auto particle = m_World->GetComponent(entity); + + transform->Position = glm::vec3(position.x, position.y, transform->Position.z); + transform->Scale = glm::vec3(particle->Radius * 2.f, particle->Radius * 2.f, 1); + } + } + + m_Accumulator -= m_TimeStep; + } +} + +void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) +{ + if (m_Travelling) { + auto transform = m_World->GetComponent(entity); + if (transform != nullptr) { + if (!transform->Sticky) { + transform->Position.y -= 6.0f * dt; + } + } else { + transform->Position.y -= 6.0f * dt; + } + } + auto particle = m_World->GetComponent(entity); + auto pTemplate = m_World->GetComponent(entity); + + + + if (particle && !pTemplate) { + particle->TimeLived += dt; + //Delete particles + if (particle->TimeLived >= particle->LifeTime - 0.1) { + for (int i = 0; i < m_EntitiesToParticleHandle.size(); i++) { + const b2ParticleHandle* handle = m_EntitiesToParticleHandle[i][entity]; + std::unordered_map::iterator iter1; + std::unordered_map::iterator iter2; + iter1 = m_EntitiesToParticleHandle[i].find(entity); + iter2 = m_ParticleHandleToEntities[i].find(handle); + if (iter1 != m_EntitiesToParticleHandle[i].end()) { + m_EntitiesToParticleHandle[i].erase(iter1); + } + if (iter2 != m_ParticleHandleToEntities[i].end()) { + m_ParticleHandleToEntities[i].erase(iter2); + } + m_World->RemoveEntity(entity); + } + } + //Update alpha + auto sprite = m_World->GetComponent(entity); + float timeProgress = particle->TimeLived / particle->LifeTime; + if (timeProgress > particle->LifeTime) { + timeProgress = particle->LifeTime; + } + auto emitter = m_World->GetComponent(particle->ParticleSystem); + if (emitter) { + sprite->Color.w = ScalarInterpolation(timeProgress, emitter->AlphaValues); + particle->Radius = ScalarInterpolation(timeProgress, emitter->RadiusValues); + } + } + + //Particlesystem relative to parent + auto emitter = m_World->GetComponent(entity); + if (emitter) { + EntityID emitterParent = emitter->Parent; + if (emitterParent != 0) { + auto emitterTransform = m_World->GetComponent(entity); + auto parentTransform = m_World->GetComponent(emitterParent); + if (emitterTransform && parentTransform) { + emitterTransform->Position = parentTransform->Position; + } + } + } +} + +float dd::Systems::PhysicsSystem::ScalarInterpolation(float timeProgress, std::vector spectrum) +{ + int alphaVecSize = spectrum.size(); + if (alphaVecSize == 0) { + return 0.01f; + } + if (alphaVecSize == 1) { + return spectrum[0]; + } + + float dValue = glm::abs(spectrum[0] - spectrum[1]); + if (spectrum[0] > spectrum[1]) { + dValue *= -1; + } + + float scalar = spectrum[0] + dValue * timeProgress; + + return scalar; +} + +bool dd::Systems::PhysicsSystem::OnPause(const dd::Events::Pause &event) +{ + if (event.Type != "PhysicsSystem" && event.Type != "All") { + return false; + } + + if (m_Pause) { + m_Pause = false; + } else { + m_Pause = true; + } + return true; +} + +void dd::Systems::PhysicsSystem::OnEntityCommit(EntityID entity) +{ + auto physicsComponent = m_World->GetComponent(entity); + auto waterComponent = m_World->GetComponent(entity); + auto particleEmitterComponent = m_World->GetComponent(entity); + + if (physicsComponent && waterComponent) { + LOG_ERROR("Entity has both water and physics component, this is illegal. The police has been alerted."); + return; + } + if (physicsComponent && particleEmitterComponent) { + LOG_ERROR("Entity has both particle and physics component, this is illegal. The police has been alerted."); + return; + } + + if (physicsComponent) { + auto it = m_EntitiesToBodies.find(entity); + if(it == m_EntitiesToBodies.end()) { + CreateBody(entity); + } else { + LOG_ERROR("Tried to commit a body that already exists"); + } + } else if (waterComponent) { + CreateParticleGroup(entity); + } else if (particleEmitterComponent) { + CreateParticleEmitter(entity); + } +} + + +void dd::Systems::PhysicsSystem::OnEntityRemoved(EntityID entity) +{ + auto it = m_EntitiesToBodies.find(entity); + if(it != m_EntitiesToBodies.end()) { + it->second->GetWorld()->DestroyBody(it->second); + m_BodiesToEntities.erase(it->second); + m_EntitiesToBodies.erase(entity); + } +} + + +bool dd::Systems::PhysicsSystem::OnStageCleared(const dd::Events::StageCleared &event) +{ + if (event.ClearedStage < 5) { + m_Travelling = true; + } + return true; +} + + +void dd::Systems::PhysicsSystem::CreateBody(EntityID entity) +{ + auto physicsComponent = m_World->GetComponent(entity); + if(!physicsComponent){ + LOG_ERROR("No PhysicsComponent in CreateBody"); + return; + } + + auto transformComponent = m_World->GetComponent(entity); + if(!transformComponent) { + LOG_ERROR("No TransformComponent in CreateBody"); + return; + } + + auto absoluteTransform = m_World->GetSystem()->AbsoluteTransform(entity); + + b2BodyDef bodyDef; + bodyDef.position.Set(absoluteTransform.Position.x, absoluteTransform.Position.y); + bodyDef.angle = -glm::eulerAngles(absoluteTransform.Orientation).z; + + if (physicsComponent->CollisionType == CollisionType::Type::Static) { + bodyDef.type = b2_staticBody; + } else if (physicsComponent->CollisionType == CollisionType::Type::Dynamic) { + bodyDef.type = b2_dynamicBody; + } else if (physicsComponent->CollisionType == CollisionType::Type::Kinematic) { + bodyDef.type = b2_dynamicBody; + } + + b2Body* body = m_PhysicsWorld->CreateBody(&bodyDef); + + b2Shape* pShape; + + auto rectangleComponent = m_World->GetComponent(entity); + if (rectangleComponent) { + b2PolygonShape* bShape = new b2PolygonShape(); + bShape->SetAsBox(rectangleComponent->Dimensions.x/2.f, rectangleComponent->Dimensions.y/2.f); + pShape = bShape; + } else { + auto circleComponent = m_World->GetComponent(entity); + if (circleComponent) { + pShape = new b2CircleShape(); + pShape->m_radius = circleComponent->Radius; + } + } + + b2FixtureDef fixtureDef; + fixtureDef.shape = pShape; + fixtureDef.filter.categoryBits = physicsComponent->Category; + fixtureDef.filter.maskBits = physicsComponent->Mask; + + + + fixtureDef.shape = pShape; + fixtureDef.density = physicsComponent->Density; + fixtureDef.restitution = 1.0f; + fixtureDef.friction = 0.0f; + body->CreateFixture(&fixtureDef); + + + delete pShape; + + body->SetGravityScale(physicsComponent->GravityScale); + m_EntitiesToBodies.insert(std::make_pair(entity, body)); + m_BodiesToEntities.insert(std::make_pair(body, entity)); +} + + +void dd::Systems::PhysicsSystem::CreateParticleGroup(EntityID e) +{ + auto transform = m_World->GetComponent(e); + if (!transform) { + LOG_ERROR("No Transform component in CreateParticleGroup"); + } + b2ParticleGroupDef pd; + b2PolygonShape shape; + auto water = m_World->GetComponent(e); + if (water) { + + shape.SetAsBox(transform->Scale.x/2.f, transform->Scale.y/2.f); + pd.shape = &shape; + pd.flags = b2_tensileParticle; + pd.position.Set(transform->Position.x, transform->Position.y); + t_ParticleGroup.push_back(m_WaterParticleSystem->CreateParticleGroup(pd)); + b2Vec2* t_ParticlePositions = m_WaterParticleSystem->GetPositionBuffer(); + for(int i = 0; i < m_WaterParticleSystem->GetParticleCount(); i++){ + { + auto t_waterparticle = m_World->CreateEntity(e); + auto transformChild = m_World->AddComponent(t_waterparticle); + + transformChild->Position = glm::vec3(t_ParticlePositions[i].x - transform->Position.x, t_ParticlePositions[i].y - transform->Position.y, -9.5f); + transformChild->Scale = glm::vec3(m_WaterParticleSystem->GetRadius())/transform->Scale; + m_World->CommitEntity(t_waterparticle); + + m_EntitiesToWaterParticleHandle.insert(std::make_pair(t_waterparticle, m_WaterParticleSystem->GetParticleHandleFromIndex(i))); + m_WaterParticleHandleToEntities.insert(std::make_pair(m_WaterParticleSystem->GetParticleHandleFromIndex(i), t_waterparticle)); + } + + } + + } +} + + +void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) +{ + std::vector emittersToDelete; + int pSizeTest = 0; //For debugging, delete this + int psListSize = 0; + for (int i = 0; i < m_ParticleEmitters.ParticleSystem.size(); i++) { + auto e = m_ParticleEmitters.ParticleEmitter[i]; + auto pt = m_ParticleEmitters.ParticleTemplate[i]; + auto ps = m_ParticleEmitters.ParticleSystem[i]; + pSizeTest += ps->GetParticleCount(); + psListSize++; + auto emitter = m_World->GetComponent(e); + auto particleTemplate = m_World->GetComponent(pt); + if(!emitter) { + LOG_INFO("ParticleEmitter Component is nil"); + continue; + } + if(!particleTemplate) { + LOG_INFO("ParticleTemplate Component is nil."); + continue; + } + auto emitterTransform = m_World->GetComponent(e); + emitterTransform->Orientation = glm::rotate(glm::quat(), 3.f, glm::vec3(0.f, 0.f, -1.f)); + + emitter->TimeSinceLastSpawn += dt; + emitter->LifeTime -= dt; + + if (emitter->LifeTime <= 0 || emitter->NumberOfTicks <= 0) { + emittersToDelete.push_back(e); + continue; + } + if(emitter->TimeSinceLastSpawn < emitter->SpawnRate || emitter->NumberOfTicks < 1) { + continue; + } + //Create new particle + emitter->NumberOfTicks--; + emitter->TimeSinceLastSpawn -= emitter->SpawnRate; + auto templateTransform = m_World->GetComponent(pt); + + for ( int j = 0; j < emitter->ParticlesPerTick; j++) { + b2ParticleDef particleDef; + particleDef.flags = particleTemplate->Flags; + //particleDef.color TODO: Implement this if we want color mixing and shit. + particleDef.lifetime = particleTemplate->LifeTime; + float eAngle = emitter->EmittingAngle; + float halfSpread = emitter->Spread / 2; + + std::uniform_real_distribution dis(eAngle - halfSpread, eAngle + halfSpread); + float pAngle = dis(gen); + std::uniform_real_distribution dis2(0.3, 1.5); + float speedMultiplier = dis2(gen); + glm::vec2 unitVec = glm::normalize(glm::vec2(glm::cos(pAngle), glm::sin(pAngle))); + glm::vec2 vel = unitVec * emitter->Speed * (float)dt * speedMultiplier * 0.5f; + particleDef.velocity = b2Vec2(vel.x, vel.y); + particleDef.position = b2Vec2(emitterTransform->Position.x, emitterTransform->Position.y); + + + auto particle = m_World->CloneEntity(pt, 0); + m_World->RemoveComponent(particle); + auto particleTransform = m_World->GetComponent(particle); + + + std::uniform_real_distribution dist(0, 1); + float zDistribution = dist(gen); + particleTransform->Position = glm::vec3(emitterTransform->Position.x, emitterTransform->Position.y, -9.5f + zDistribution); + particleTransform->Scale = glm::vec3(particleTemplate->Radius * 2.f / speedMultiplier, particleTemplate->Radius * 2.f / speedMultiplier, 1); + particleTransform->Velocity = glm::vec3(vel.x, vel.y, 0); + + + auto b2ParticleIndex = ps->CreateParticle(particleDef); + auto b2ParticleHandle = ps->GetParticleHandleFromIndex(b2ParticleIndex); + + m_EntitiesToParticleHandle[i].insert(std::make_pair(particle, b2ParticleHandle)); + m_ParticleHandleToEntities[i].insert(std::make_pair(b2ParticleHandle, particle)); + } + + } +// system("cls"); +// std::cout << "Particles living: " << pSizeTest << std::endl; +// std::cout << "particle systems: " << psListSize << std::endl; +// int entHandles = 0; +// for (int i = 0; i < m_EntitiesToParticleHandle.size(); i++) +// entHandles += m_EntitiesToParticleHandle[i].size(); +// std::cout << "Entities and handles: " << entHandles << std::endl; +// LOG_INFO("Particles living: %i", pSizeTest); +// LOG_INFO("Particle systems: %i", psListSize); +// //int entHandles = 0; +// for (int i = 0; i < m_EntitiesToParticleHandle.size(); i++) +// entHandles += m_EntitiesToParticleHandle[i].size(); +// LOG_INFO("Entities and handles: %i", entHandles); + + + for (int i = 0; i < emittersToDelete.size(); i++) + { + EntityID ent = emittersToDelete[i]; + int key; + for(key = 0; key < m_ParticleEmitters.ParticleEmitter.size(); key++) { + if (m_ParticleEmitters.ParticleEmitter[key] == ent) { + break; + } + } + + if (m_ParticleEmitters.ParticleSystem[key]->GetParticleCount() == 0 && key <= m_ParticleEmitters.ParticleSystem.size() - 1) { + m_World->RemoveEntity(ent); + m_PhysicsWorld->DestroyParticleSystem(m_ParticleEmitters.ParticleSystem[key]); + m_ParticleEmitters.ParticleSystem.erase(m_ParticleEmitters.ParticleSystem.begin() + key); + m_ParticleEmitters.ParticleEmitter.erase(m_ParticleEmitters.ParticleEmitter.begin() + key); + m_ParticleEmitters.ParticleTemplate.erase(m_ParticleEmitters.ParticleTemplate.begin() + key); + m_EntitiesToParticleHandle.erase(m_EntitiesToParticleHandle.begin() + key); + m_ParticleHandleToEntities.erase(m_ParticleHandleToEntities.begin() + key); + emittersToDelete.clear(); + } + } +} + +bool dd::Systems::PhysicsSystem::CreateParticleSequence(const Events::CreateParticleSequence &event) +{ + //Creating Emitter + EntityID emitter = m_World->CreateEntity(); + + auto emitterTransform = m_World->AddComponent(emitter); + auto particleEmitter= m_World->AddComponent(emitter); + + if (event.parent != 0) { + particleEmitter->Parent = event.parent; + } + + emitterTransform->Position = event.Position; + particleEmitter->GravityScale = event.GravityScale; + particleEmitter->SpawnRate = event.SpawnRate; + particleEmitter->NumberOfTicks = event.NumberOfTicks; + particleEmitter->Speed = event.Speed; + particleEmitter->ParticlesPerTick = event.ParticlesPerTick; + particleEmitter->Spread = event.Spread; + particleEmitter->EmittingAngle = event.EmittingAngle; + particleEmitter->LifeTime = event.EmitterLifeTime; + particleEmitter->AlphaValues = event.AlphaValues; + particleEmitter->RadiusValues = event.RadiusValues; + { + //Creating Particle Template + auto particle = m_World->CreateEntity(emitter); + auto particleTransform = m_World->AddComponent(particle); + auto sprite = m_World->AddComponent(particle); + auto particleComponent = m_World->AddComponent(particle); + m_World->AddComponent(particle); + particleTransform->Position = emitterTransform->Position; + sprite->SpriteFile = event.SpriteFile; + sprite->Color = event.Color; + particleComponent->LifeTime = event.ParticleLifeTime; + particleComponent->Flags = event.Flags; + particleComponent->Radius = event.RadiusValues[0]; + particleComponent->ParticleSystem = emitter; + } + m_World->CommitEntity(emitter); + return true; +} + +void dd::Systems::PhysicsSystem::CreateParticleEmitter(EntityID entity) +{ + auto childEntities = m_World->GetEntityChildren(entity); + if (childEntities.empty()) { + LOG_ERROR("Particle Emitter does not have any child. Please adopt one or this will not work."); + return; + } + int pf = 0; + dd::Components::Particle* particle; + EntityID childEntity; + for ( auto c : childEntities ) { + auto p = m_World->GetComponent(c); + auto particleTemplate = m_World->GetComponent(c); + if (!p) { + continue; + LOG_WARNING("ParticleEmitter's Child is not a particle."); + } + if(!particleTemplate) { + LOG_ERROR("ParticleEmitter's particleChild is not a template."); + continue; + } + if (pf != 0) { + LOG_WARNING("ParticleEmitter has more than one child that is a particleTemplate, only the first one is used."); + break; + } + childEntity = c; + particle = p; + pf++; + } + //TODO: Skicka med fler flaggor till particlesystemet; + + m_ParticleEmitters.ParticleSystem.push_back(CreateParticleSystem(particle->Radius, 0.f, 0)); + m_ParticleEmitters.ParticleEmitter.push_back(entity); + m_ParticleEmitters.ParticleTemplate.push_back(childEntity); +} + + +b2ParticleSystem* dd::Systems::PhysicsSystem::CreateParticleSystem(float radius, float gravityScale, int maxCount) +{ + std::unordered_map m1; + std::unordered_map m2; + m_EntitiesToParticleHandle.push_back(m1); + m_ParticleHandleToEntities.push_back(m2); + + b2ParticleSystemDef m_ParticleSystemDef; + m_ParticleSystemDef.maxCount = maxCount; + m_ParticleSystemDef.radius = radius; + m_ParticleSystemDef.gravityScale = gravityScale; + m_ParticleSystemDef.destroyByAge = false; + + return m_PhysicsWorld->CreateParticleSystem(&m_ParticleSystemDef); +} + +bool dd::Systems::PhysicsSystem::OnContact(const dd::Events::Contact &event) +{ + //Check if it is a brick colliding with ball + auto brick = m_World->GetComponent(event.Entity1); + Components::Model* model; + auto ball = m_World->GetComponent(event.Entity2); + if (!brick) { + brick = m_World->GetComponent(event.Entity2); + if (!brick) { + return false; + } + else { + model = m_World->GetComponent(event.Entity2); + } + } + else if (!ball) { + ball = m_World->GetComponent(event.Entity1); + if (!ball) { + return false; + } + } + else { + + model = m_World->GetComponent(event.Entity1); + } + Events::CreateParticleSequence e; + e.EmitterLifeTime = 4; + //- glm::atan(event.Normal.x, event.Normal.y + e.EmittingAngle = glm::half_pi(); + e.Spread = 0.5f; + e.NumberOfTicks = 1; + e.ParticleLifeTime = 1.f; + e.ParticlesPerTick = 15; + e.Position = glm::vec3(event.IntersectionPoint.x, event.IntersectionPoint.y, -10); + e.RadiusValues.push_back(0.2); + e.RadiusValues.push_back(1); + e.SpriteFile = "Textures/Particles/Cloud_Particle.png"; + e.Color = model->Color + glm::vec4(0.5f); + e.AlphaValues.push_back(1.f); + e.AlphaValues.push_back(0.f); + e.Speed = 100; + EventBroker->Publish(e); + return true; +} + + +dd::Systems::PhysicsSystem::~PhysicsSystem() +{ + for (auto i = m_BodiesToEntities.begin(); i != m_BodiesToEntities.end(); i++) { + b2Body* body = i->first; + body->GetWorld()->DestroyBody(body); + //delete body; + } + m_BodiesToEntities.clear(); + m_EntitiesToBodies.clear(); + m_Impulses.clear(); + + //TODO:REMOVE PARTICLE SYSTEMS + + if (m_ContactListener != nullptr) { + delete m_ContactListener; + m_ContactListener = nullptr; + } + + if (m_PhysicsWorld != nullptr) { + delete m_PhysicsWorld; + m_PhysicsWorld = nullptr; + } +} From 5040ff46493301a376321fc19bc4568cb83ec2a0 Mon Sep 17 00:00:00 2001 From: Stiffly Date: Tue, 13 Oct 2015 17:39:40 +0200 Subject: [PATCH 2/6] added a radius distribution to randomize the scale. --- src/game/Game/LevelSystem.cpp | 2 +- src/game/Physics/PhysicsSystem.cpp | 37 +++++++++++++++++------------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/game/Game/LevelSystem.cpp b/src/game/Game/LevelSystem.cpp index ee434a7..34f80b9 100755 --- a/src/game/Game/LevelSystem.cpp +++ b/src/game/Game/LevelSystem.cpp @@ -396,7 +396,7 @@ void dd::Systems::LevelSystem::BrickHit(EntityID entityHitter, EntityID entityBr ep.AlphaValues.push_back(1.f); ep.AlphaValues.push_back(0.f); ep.RadiusValues.push_back(0.05f); - ep.RadiusDistribution = 0.05; + ep.RadiusDistribution = 0.05f; ep.Speed = 50; EventBroker->Publish(ep); } diff --git a/src/game/Physics/PhysicsSystem.cpp b/src/game/Physics/PhysicsSystem.cpp index 7f1e515..0cc4a3c 100755 --- a/src/game/Physics/PhysicsSystem.cpp +++ b/src/game/Physics/PhysicsSystem.cpp @@ -273,7 +273,7 @@ void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, Entity if (particle && !pTemplate) { particle->TimeLived += dt; - //Delete particles + //Delete particles if (particle->TimeLived >= particle->LifeTime - 0.1) { for (int i = 0; i < m_EntitiesToParticleHandle.size(); i++) { const b2ParticleHandle* handle = m_EntitiesToParticleHandle[i][entity]; @@ -299,7 +299,7 @@ void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, Entity auto emitter = m_World->GetComponent(particle->ParticleSystem); if (emitter) { sprite->Color.w = ScalarInterpolation(timeProgress, emitter->AlphaValues); - if (emitter->RadiusValues.size() >= 1) { + if (emitter->RadiusValues.size() > 1) { particle->Radius = ScalarInterpolation(timeProgress, emitter->RadiusValues); } } @@ -540,12 +540,18 @@ void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) if(emitter->TimeSinceLastSpawn < emitter->SpawnRate || emitter->NumberOfTicks < 1) { continue; } - //Create new particle + emitter->NumberOfTicks--; emitter->TimeSinceLastSpawn -= emitter->SpawnRate; auto templateTransform = m_World->GetComponent(pt); - + + //Create new particle for ( int j = 0; j < emitter->ParticlesPerTick; j++) { + auto particle = m_World->CloneEntity(pt, 0); + m_World->RemoveComponent(particle); + auto particleTransform = m_World->GetComponent(particle); + auto particleComponent = m_World->GetComponent(particle); + b2ParticleDef particleDef; particleDef.flags = particleTemplate->Flags; //particleDef.color TODO: Implement this if we want color mixing and shit. @@ -567,21 +573,18 @@ void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) //position particleDef.position = b2Vec2(emitterTransform->Position.x, emitterTransform->Position.y); - - auto particle = m_World->CloneEntity(pt, 0); - m_World->RemoveComponent(particle); - auto particleTransform = m_World->GetComponent(particle); - auto particleComponent = m_World->GetComponent(particle); - + //radius - currently not working :j float radius = emitter->RadiusValues[0]; - if (emitter->RadiusDistribution != 0) { - float halfRadius = emitter->RadiusDistribution / 2; + float newRadius = 0; + if (emitter->RadiusDistribution > 0) { + float halfRadius = radius / 2; std::uniform_real_distribution dis3(radius - halfRadius, radius + halfRadius); - radius = dis3(gen); - //emitter->RadiusValues[0] = radius; + newRadius = dis3(gen); } - //particleTransform->Scale = glm::vec3(radius * 2, radius * 2, 1); - particleComponent->Radius = radius; + else { + newRadius = radius; + } + particleComponent->Radius = newRadius; //Random z-value std::uniform_real_distribution dist(0, 1); @@ -773,6 +776,7 @@ bool dd::Systems::PhysicsSystem::OnContact(const dd::Events::Contact &event) e.Color = glm::vec4(1.f); e.AlphaValues.push_back(1.f); e.AlphaValues.push_back(0.f); + e.RadiusValues.push_back(1); e.Speed = 0; auto PowerFriend = m_World->GetComponent(entity); @@ -800,6 +804,7 @@ bool dd::Systems::PhysicsSystem::OnContact(const dd::Events::Contact &event) e.ParticleLifeTime = 1.f; e.ParticlesPerTick = 15; e.Position = glm::vec3(event.IntersectionPoint.x, event.IntersectionPoint.y, -10); + e.RadiusValues.clear(); e.RadiusValues.push_back(0.2); e.RadiusValues.push_back(1); e.SpriteFile = "Textures/Particles/Cloud_Particle.png"; From cbb6e7a04f7cf4cb0f719f8b94ccef1ad4382e3b Mon Sep 17 00:00:00 2001 From: Stiffly Date: Wed, 14 Oct 2015 17:40:24 +0200 Subject: [PATCH 3/6] Trail to individual brick debris. Counter the particle spawn bug. The bug occurs when the position is read as (0, 0) from the emitter. Similar particle removal bug appears when particles are deleted. Counterered by deleting particle entities a little time before b2particles. --- src/game/Game/LevelSystem.cpp | 19 +++++++++++++++++++ src/game/Physics/PhysicsSystem.cpp | 22 ++++++++++++++-------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/game/Game/LevelSystem.cpp b/src/game/Game/LevelSystem.cpp index cc1510e..6868b88 100755 --- a/src/game/Game/LevelSystem.cpp +++ b/src/game/Game/LevelSystem.cpp @@ -394,6 +394,25 @@ void dd::Systems::LevelSystem::BrickHit(EntityID entityHitter, EntityID entityBr m_World->RemoveComponent(b); m_World->SetEntityParent(b, 0); m_World->CommitEntity(b); + + //Particle trail + Events::CreateParticleSequence p; + p.parent = b; + p.AlphaValues.push_back(1.f); + p.AlphaValues.push_back(0.f); + p.RadiusValues.push_back(0.06f); + p.RadiusValues.push_back(0.f); + p.RadiusDistribution = 1; + p.EmitterLifeTime = 2.f; + p.ParticleLifeTime = 1.f; + p.ParticlesPerTick = 1; + p.SpawnRate = 0.1f; + p.Speed = 10.f; + p.EmittingAngle = glm::half_pi(); + p.SpriteFile = "Textures/Particles/FadeBall.png"; + p.Color = brickModel->Color; + //p.Spread = ... + EventBroker->Publish(p); } diff --git a/src/game/Physics/PhysicsSystem.cpp b/src/game/Physics/PhysicsSystem.cpp index 676c6b9..d2d0c63 100755 --- a/src/game/Physics/PhysicsSystem.cpp +++ b/src/game/Physics/PhysicsSystem.cpp @@ -268,7 +268,7 @@ void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, Entity } //Update alpha auto sprite = m_World->GetComponent(entity); - float timeProgress = particle->TimeLived / particle->LifeTime; + float timeProgress = particle->TimeLived / (particle->LifeTime - 0.1); if (timeProgress > particle->LifeTime) { timeProgress = particle->LifeTime; } @@ -305,10 +305,11 @@ float dd::Systems::PhysicsSystem::ScalarInterpolation(float timeProgress, std::v return spectrum[0]; } - float dValue = glm::abs(spectrum[0] - spectrum[1]); - if (spectrum[0] > spectrum[1]) { - dValue *= -1; - } + float dValue = spectrum[1] - spectrum[0]; +// glm::abs(spectrum[0] - spectrum[1]); +// if (spectrum[0] > spectrum[1]) { +// dValue *= -1; +// } float scalar = spectrum[0] + dValue * timeProgress; @@ -514,12 +515,18 @@ void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) //Create new particle for ( int j = 0; j < emitter->ParticlesPerTick; j++) { + b2ParticleDef particleDef; + //position + particleDef.position = b2Vec2(emitterTransform->Position.x, emitterTransform->Position.y); + if (particleDef.position.x == 0.f && particleDef.position.y == 0.f) { + continue; + } + auto particle = m_World->CloneEntity(pt, 0); m_World->RemoveComponent(particle); auto particleTransform = m_World->GetComponent(particle); auto particleComponent = m_World->GetComponent(particle); - b2ParticleDef particleDef; particleDef.flags = particleTemplate->Flags; //particleDef.color TODO: Implement this if we want color mixing and shit. particleDef.lifetime = particleTemplate->LifeTime; @@ -537,8 +544,7 @@ void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) glm::vec2 vel = unitVec * emitter->Speed * (float)dt * speedMultiplier; particleDef.velocity = b2Vec2(vel.x, vel.y); - //position - particleDef.position = b2Vec2(emitterTransform->Position.x, emitterTransform->Position.y); + //radius - currently not working :j float radius = emitter->RadiusValues[0]; From 46f3a9f72e87cb67398a428a8930405653d2eecf Mon Sep 17 00:00:00 2001 From: Stiffly Date: Wed, 14 Oct 2015 18:29:43 +0200 Subject: [PATCH 4/6] Refactored CParticle->Radius to CParticle->Scale. Reviewed by Tobias Dahl aka Tleety. --- include/Physics/CParticle.h | 2 +- include/Physics/CParticleEmitter.h | 2 +- include/Physics/ECreateParticleSequence.h | 2 +- src/game/Game/LevelSystem.cpp | 4 +-- src/game/Physics/PhysicsSystem.cpp | 36 +++++++++++++---------- 5 files changed, 25 insertions(+), 21 deletions(-) diff --git a/include/Physics/CParticle.h b/include/Physics/CParticle.h index c0247f1..e2d8391 100755 --- a/include/Physics/CParticle.h +++ b/include/Physics/CParticle.h @@ -34,7 +34,7 @@ namespace Components struct Particle : public Component { EntityID ParticleSystem; - float Radius = 0.5f; + glm::vec3 Scale = glm::vec3(1.f); double TimeLived = 0; double LifeTime = 5; diff --git a/include/Physics/CParticleEmitter.h b/include/Physics/CParticleEmitter.h index dc56d9d..9ba9212 100755 --- a/include/Physics/CParticleEmitter.h +++ b/include/Physics/CParticleEmitter.h @@ -24,7 +24,7 @@ struct ParticleEmitter : public Component float RadiusDistribution = 0; //values to interpolate between. - std::vector RadiusValues; + std::vector ScaleValues; std::vector AlphaValues; //System variables diff --git a/include/Physics/ECreateParticleSequence.h b/include/Physics/ECreateParticleSequence.h index 88f4ec5..d1f165d 100644 --- a/include/Physics/ECreateParticleSequence.h +++ b/include/Physics/ECreateParticleSequence.h @@ -26,7 +26,7 @@ struct CreateParticleSequence : public Event glm::vec4 Color = glm::vec4(0); EntityID parent = 0; // values to interpolate between. - std::vector RadiusValues; + std::vector ScaleValues; std::vector AlphaValues; //Particle diff --git a/src/game/Game/LevelSystem.cpp b/src/game/Game/LevelSystem.cpp index 6868b88..3183d9e 100755 --- a/src/game/Game/LevelSystem.cpp +++ b/src/game/Game/LevelSystem.cpp @@ -400,8 +400,8 @@ void dd::Systems::LevelSystem::BrickHit(EntityID entityHitter, EntityID entityBr p.parent = b; p.AlphaValues.push_back(1.f); p.AlphaValues.push_back(0.f); - p.RadiusValues.push_back(0.06f); - p.RadiusValues.push_back(0.f); + p.ScaleValues.push_back(glm::vec3(0.06f)); + p.ScaleValues.push_back(glm::vec3(0.f)); p.RadiusDistribution = 1; p.EmitterLifeTime = 2.f; p.ParticleLifeTime = 1.f; diff --git a/src/game/Physics/PhysicsSystem.cpp b/src/game/Physics/PhysicsSystem.cpp index d2d0c63..460d6bd 100755 --- a/src/game/Physics/PhysicsSystem.cpp +++ b/src/game/Physics/PhysicsSystem.cpp @@ -234,7 +234,7 @@ void dd::Systems::PhysicsSystem::Update(double dt) auto particle = m_World->GetComponent(entity); transform->Position = glm::vec3(position.x, position.y, transform->Position.z); - transform->Scale = glm::vec3(particle->Radius * 2.f, particle->Radius * 2.f, 1); + transform->Scale = particle->Scale;//glm::vec3(particle->Radius * 2.f, particle->Radius * 2.f, 1); } } @@ -275,8 +275,12 @@ void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, Entity auto emitter = m_World->GetComponent(particle->ParticleSystem); if (emitter) { sprite->Color.w = ScalarInterpolation(timeProgress, emitter->AlphaValues); - if (emitter->RadiusValues.size() > 1) { - particle->Radius = ScalarInterpolation(timeProgress, emitter->RadiusValues); + if (emitter->ScaleValues.size() > 1) { + //TODO: Implement vector interpolation function. Use scale from resourcemanager. Texture->Width... + std::vector spectrum; + spectrum.push_back(emitter->ScaleValues[0].x); + spectrum.push_back(emitter->ScaleValues[1].x); + particle->Scale = glm::vec3(ScalarInterpolation(timeProgress, spectrum)); } } } @@ -544,10 +548,8 @@ void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) glm::vec2 vel = unitVec * emitter->Speed * (float)dt * speedMultiplier; particleDef.velocity = b2Vec2(vel.x, vel.y); - - - //radius - currently not working :j - float radius = emitter->RadiusValues[0]; + //radius + float radius = emitter->ScaleValues[0].x; float newRadius = 0; if (emitter->RadiusDistribution > 0) { float halfRadius = radius / 2; @@ -557,13 +559,15 @@ void dd::Systems::PhysicsSystem::UpdateParticleEmitters(double dt) else { newRadius = radius; } - particleComponent->Radius = newRadius; + particleComponent->Scale = glm::vec3(newRadius); + //Random z-value std::uniform_real_distribution dist(0, 1); float zDistribution = dist(gen); particleTransform->Position = glm::vec3(emitterTransform->Position.x, emitterTransform->Position.y, -9.5f + zDistribution); - particleTransform->Scale = glm::vec3(particleTemplate->Radius * 2.f / speedMultiplier, particleTemplate->Radius * 2.f / speedMultiplier, 1); + particleTransform->Scale = particleTemplate->Scale; + //glm::vec3(particleTemplate->Radius * 2.f / speedMultiplier, particleTemplate->Radius * 2.f / speedMultiplier, 1); particleTransform->Velocity = glm::vec3(vel.x, vel.y, 0); @@ -694,7 +698,7 @@ bool dd::Systems::PhysicsSystem::CreateParticleSequence(const Events::CreatePart particleEmitter->EmittingAngle = event.EmittingAngle; particleEmitter->LifeTime = event.EmitterLifeTime; particleEmitter->AlphaValues = event.AlphaValues; - particleEmitter->RadiusValues = event.RadiusValues; + particleEmitter->ScaleValues = event.ScaleValues; particleEmitter->RadiusDistribution = event.RadiusDistribution; { //Creating Particle Template @@ -708,7 +712,7 @@ bool dd::Systems::PhysicsSystem::CreateParticleSequence(const Events::CreatePart sprite->Color = event.Color; particleComponent->LifeTime = event.ParticleLifeTime; particleComponent->Flags = event.Flags; - particleComponent->Radius = event.RadiusValues[0]; + particleComponent->Scale = event.ScaleValues[0]; particleComponent->ParticleSystem = emitter; } m_World->CommitEntity(emitter); @@ -746,7 +750,7 @@ void dd::Systems::PhysicsSystem::CreateParticleEmitter(EntityID entity) } //TODO: Skicka med fler flaggor till particlesystemet; - m_ParticleEmitters.ParticleSystem.push_back(CreateParticleSystem(particle->Radius, 0.f, 0)); + m_ParticleEmitters.ParticleSystem.push_back(CreateParticleSystem(particle->Scale.x, 0.f, 0)); m_ParticleEmitters.ParticleEmitter.push_back(entity); m_ParticleEmitters.ParticleTemplate.push_back(childEntity); } @@ -808,7 +812,7 @@ bool dd::Systems::PhysicsSystem::OnContact(const dd::Events::Contact &event) e.Color = glm::vec4(1.f); e.AlphaValues.push_back(1.f); e.AlphaValues.push_back(0.f); - e.RadiusValues.push_back(1); + e.ScaleValues.push_back(glm::vec3(1.f)); e.Speed = 0; auto PowerFriend = m_World->GetComponent(entity); @@ -836,9 +840,9 @@ bool dd::Systems::PhysicsSystem::OnContact(const dd::Events::Contact &event) e.ParticleLifeTime = 1.f; e.ParticlesPerTick = 15; e.Position = glm::vec3(event.IntersectionPoint.x, event.IntersectionPoint.y, -10); - e.RadiusValues.clear(); - e.RadiusValues.push_back(0.2); - e.RadiusValues.push_back(1); + e.ScaleValues.clear(); + e.ScaleValues.push_back(glm::vec3(0.2f)); + e.ScaleValues.push_back(glm::vec3(1.f)); e.SpriteFile = "Textures/Particles/Cloud_Particle.png"; e.Color = model->Color + glm::vec4(0.5f); e.AlphaValues.push_back(1.f); From bf82e549aad41b5f4a189d13d9ab87557c3609f5 Mon Sep 17 00:00:00 2001 From: Stiffly Date: Fri, 16 Oct 2015 12:43:40 +0200 Subject: [PATCH 5/6] Added VectorInterpolation function. Fixed time bug for particles. --- include/Physics/PhysicsSystem.h | 2 + src/game/Game/LevelSystem.cpp | 2 +- src/game/Physics/PhysicsSystem.cpp | 60 ++++++++++++++++++------------ 3 files changed, 39 insertions(+), 25 deletions(-) diff --git a/include/Physics/PhysicsSystem.h b/include/Physics/PhysicsSystem.h index fc5925e..bd37c74 100755 --- a/include/Physics/PhysicsSystem.h +++ b/include/Physics/PhysicsSystem.h @@ -107,6 +107,8 @@ namespace dd void CreateParticleEmitter(EntityID entity); void UpdateParticleEmitters(double dt); //TODO: Remove them and particles if needed. float ScalarInterpolation(float timeProgress, std::vector spectrum); + glm::vec3 VectorInterpolation(float timeProgress, std::vector spectrum); + EventRelay m_SetImpulse; bool SetImpulse(const Events::SetImpulse &event); diff --git a/src/game/Game/LevelSystem.cpp b/src/game/Game/LevelSystem.cpp index 3183d9e..f5b99a0 100755 --- a/src/game/Game/LevelSystem.cpp +++ b/src/game/Game/LevelSystem.cpp @@ -400,7 +400,7 @@ void dd::Systems::LevelSystem::BrickHit(EntityID entityHitter, EntityID entityBr p.parent = b; p.AlphaValues.push_back(1.f); p.AlphaValues.push_back(0.f); - p.ScaleValues.push_back(glm::vec3(0.06f)); + p.ScaleValues.push_back(glm::vec3(0.08f)); p.ScaleValues.push_back(glm::vec3(0.f)); p.RadiusDistribution = 1; p.EmitterLifeTime = 2.f; diff --git a/src/game/Physics/PhysicsSystem.cpp b/src/game/Physics/PhysicsSystem.cpp index 460d6bd..6c55530 100755 --- a/src/game/Physics/PhysicsSystem.cpp +++ b/src/game/Physics/PhysicsSystem.cpp @@ -269,19 +269,14 @@ void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, Entity //Update alpha auto sprite = m_World->GetComponent(entity); float timeProgress = particle->TimeLived / (particle->LifeTime - 0.1); - if (timeProgress > particle->LifeTime) { - timeProgress = particle->LifeTime; + if (timeProgress > 1) { + timeProgress = 1; } auto emitter = m_World->GetComponent(particle->ParticleSystem); if (emitter) { sprite->Color.w = ScalarInterpolation(timeProgress, emitter->AlphaValues); - if (emitter->ScaleValues.size() > 1) { - //TODO: Implement vector interpolation function. Use scale from resourcemanager. Texture->Width... - std::vector spectrum; - spectrum.push_back(emitter->ScaleValues[0].x); - spectrum.push_back(emitter->ScaleValues[1].x); - particle->Scale = glm::vec3(ScalarInterpolation(timeProgress, spectrum)); - } + particle->Scale = VectorInterpolation(timeProgress, emitter->ScaleValues); + } } @@ -301,25 +296,41 @@ void dd::Systems::PhysicsSystem::UpdateEntity(double dt, EntityID entity, Entity float dd::Systems::PhysicsSystem::ScalarInterpolation(float timeProgress, std::vector spectrum) { - int alphaVecSize = spectrum.size(); - if (alphaVecSize == 0) { - return 0.01f; + int spectrumSize = spectrum.size(); + if (spectrumSize == 0) { + return 1.f; } - if (alphaVecSize == 1) { + if (spectrumSize == 1) { return spectrum[0]; } float dValue = spectrum[1] - spectrum[0]; -// glm::abs(spectrum[0] - spectrum[1]); -// if (spectrum[0] > spectrum[1]) { -// dValue *= -1; -// } - float scalar = spectrum[0] + dValue * timeProgress; return scalar; } +glm::vec3 dd::Systems::PhysicsSystem::VectorInterpolation(float timeProgress, std::vector spectrum) +{ + int spectrumSize = spectrum.size(); + if (spectrumSize == 0) { + LOG_ERROR("You need to supply your particlesystem with scales in ScaleValues."); + return glm::vec3(1); + } + else if (spectrumSize == 1) { + return spectrum[0]; + } + + float dX = spectrum[1].x - spectrum[0].x; + float x = spectrum[0].x + dX * timeProgress; + float dY = spectrum[1].y - spectrum[0].y; + float y = spectrum[0].y + dY * timeProgress; + float dZ = spectrum[1].z - spectrum[0].z; + float z = spectrum[0].z + dZ * timeProgress; + + return glm::vec3(x, y, z); +} + bool dd::Systems::PhysicsSystem::OnPause(const dd::Events::Pause &event) { if (event.Type != "PhysicsSystem" && event.Type != "All") { @@ -837,17 +848,18 @@ bool dd::Systems::PhysicsSystem::OnContact(const dd::Events::Contact &event) e.EmittingAngle = glm::half_pi(); e.Spread = 0.5f; e.NumberOfTicks = 1; - e.ParticleLifeTime = 1.f; - e.ParticlesPerTick = 15; + e.ParticleLifeTime = 0.5f; + e.ParticlesPerTick = 1; e.Position = glm::vec3(event.IntersectionPoint.x, event.IntersectionPoint.y, -10); e.ScaleValues.clear(); - e.ScaleValues.push_back(glm::vec3(0.2f)); - e.ScaleValues.push_back(glm::vec3(1.f)); + e.ScaleValues.push_back(glm::vec3(0.5f)); + e.ScaleValues.push_back(glm::vec3(4.f, 4.f, 0.2f)); e.SpriteFile = "Textures/Particles/Cloud_Particle.png"; - e.Color = model->Color + glm::vec4(0.5f); + e.Color = model->Color; + e.AlphaValues.clear(); e.AlphaValues.push_back(1.f); e.AlphaValues.push_back(0.f); - e.Speed = 100; + //e.Speed = 0; } EventBroker->Publish(e); From 2c6ac49e15615c901aef681dab5deda00e4a9ea9 Mon Sep 17 00:00:00 2001 From: Stiffly Date: Fri, 16 Oct 2015 13:05:33 +0200 Subject: [PATCH 6/6] Added particle event for each brick debris. poof! --- src/game/Game/LevelSystem.cpp | 52 ++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/game/Game/LevelSystem.cpp b/src/game/Game/LevelSystem.cpp index f5b99a0..fdaf172 100755 --- a/src/game/Game/LevelSystem.cpp +++ b/src/game/Game/LevelSystem.cpp @@ -396,23 +396,43 @@ void dd::Systems::LevelSystem::BrickHit(EntityID entityHitter, EntityID entityBr m_World->CommitEntity(b); //Particle trail - Events::CreateParticleSequence p; - p.parent = b; - p.AlphaValues.push_back(1.f); - p.AlphaValues.push_back(0.f); - p.ScaleValues.push_back(glm::vec3(0.08f)); - p.ScaleValues.push_back(glm::vec3(0.f)); - p.RadiusDistribution = 1; - p.EmitterLifeTime = 2.f; - p.ParticleLifeTime = 1.f; - p.ParticlesPerTick = 1; - p.SpawnRate = 0.1f; - p.Speed = 10.f; - p.EmittingAngle = glm::half_pi(); - p.SpriteFile = "Textures/Particles/FadeBall.png"; - p.Color = brickModel->Color; + Events::CreateParticleSequence trail; + trail.parent = b; + trail.AlphaValues.push_back(1.f); + trail.AlphaValues.push_back(0.f); + trail.ScaleValues.push_back(glm::vec3(0.08f)); + trail.ScaleValues.push_back(glm::vec3(0.f)); + trail.RadiusDistribution = 1; + trail.EmitterLifeTime = 2.f; + trail.ParticleLifeTime = 1.f; + trail.ParticlesPerTick = 1; + trail.SpawnRate = 0.1f; + trail.Speed = 10.f; + trail.EmittingAngle = glm::half_pi(); + trail.SpriteFile = "Textures/Particles/FadeBall.png"; + trail.Color = brickModel->Color; //p.Spread = ... - EventBroker->Publish(p); + EventBroker->Publish(trail); + + //ParticlePoof + Events::CreateParticleSequence poof; + poof.EmitterLifeTime = 4; + poof.EmittingAngle = glm::half_pi(); + poof.Spread = 0.5f; + poof.NumberOfTicks = 1; + poof.ParticleLifeTime = 1.5f; + poof.ParticlesPerTick = 1; + poof.Position = cTransform->Position; + poof.ScaleValues.clear(); + poof.ScaleValues.push_back(glm::vec3(0.5f)); + poof.ScaleValues.push_back(glm::vec3(2.f, 2.f, 0.2f)); + poof.SpriteFile = "Textures/Particles/Cloud_Particle.png"; + poof.Color = brickModel->Color; + poof.AlphaValues.clear(); + poof.AlphaValues.push_back(1.f); + poof.AlphaValues.push_back(0.f); + poof.Speed = 10; + EventBroker->Publish(poof); }