// // Created by Adniklastrator on 2015-09-09. // #include "PrecompiledHeader.h" #include "Game/LevelSystem.h" void dd::Systems::LevelSystem::Initialize() { EVENT_SUBSCRIBE_MEMBER(m_EContact, &LevelSystem::OnContact); EVENT_SUBSCRIBE_MEMBER(m_EScoreEvent, &LevelSystem::OnScoreEvent); EVENT_SUBSCRIBE_MEMBER(m_EMultiBall, &LevelSystem::OnMultiBall); EVENT_SUBSCRIBE_MEMBER(m_ECreatePowerUp, &LevelSystem::OnCreatePowerUp); EVENT_SUBSCRIBE_MEMBER(m_EMultiBallLost, &LevelSystem::OnMultiBallLost); EVENT_SUBSCRIBE_MEMBER(m_EPowerUpTaken, &LevelSystem::OnPowerUpTaken); EVENT_SUBSCRIBE_MEMBER(m_EStageCleared, &LevelSystem::OnStageCleared); EVENT_SUBSCRIBE_MEMBER(m_EPause, &LevelSystem::OnPause); EVENT_SUBSCRIBE_MEMBER(m_EHitPad, &LevelSystem::OnHitPad); m_BrickTemplate = m_World->CreateEntity(); std::shared_ptr transform = m_World->AddComponent(m_BrickTemplate); auto model = m_World->AddComponent(m_BrickTemplate); std::shared_ptr cBrick = m_World->AddComponent(m_BrickTemplate); std::shared_ptr cRec = m_World->AddComponent(m_BrickTemplate); cRec->Dimensions = glm::vec2(0.9f, 0.35f); std::shared_ptr cPhys = m_World->AddComponent(m_BrickTemplate); std::shared_ptr cTemplate = m_World->AddComponent(m_BrickTemplate); cPhys->CollisionType = CollisionType::Type::Static; cPhys->GravityScale = 0.f; cPhys->Category = CollisionLayer::Type::Brick; cPhys->Mask = CollisionLayer::Type::Ball; transform->Sticky = false; model->ModelFile = "Models/Brick/WhiteBrick.obj"; transform->Position = glm::vec3(50, 50, -10); //sound auto collisionSound = m_World->AddComponent(m_BrickTemplate); collisionSound->FilePath = "Sounds/Brick/shortbrickbreak.wav"; m_World->CommitEntity(m_BrickTemplate); return; } void dd::Systems::LevelSystem::Update(double dt) { if (!m_Initialized) { GetNextLevel(); CreateLevel(0); m_Initialized = true; } } void dd::Systems::LevelSystem::UpdateEntity(double dt, EntityID entity, EntityID parent) { if (IsPaused()) { return; } auto templateCheck = m_World->GetComponent(entity); if (templateCheck != nullptr){ return; } // Check the background. auto model = m_World->GetComponent(entity); if (model != nullptr) { if (model->ModelFile == "Models/Test/halfpipe/Halfpipe.obj") { auto transform = m_World->GetComponent(entity); if (transform->Position.y <= -34.6) { transform->Position.y = 34.6; } } } auto brick = m_World->GetComponent(entity); if (brick != nullptr) { auto transform = m_World->GetComponent(entity); //Removes bricks that falls out of the stage. if (transform->Position.y < -10) { if (brick->Type == StandardBrick) { } else if (brick->Type == MultiBallBrick) { Events::MultiBall e; e.padTransform = transform; EventBroker->Publish(e); } else if (brick->Type == LifebuoyBrick) { Events::Lifebuoy e; e.Transform = transform; EventBroker->Publish(e); } m_LooseBricks--; m_World->RemoveEntity(entity); } } auto ball = m_World->GetComponent(entity); if (NumberOfBricks() <= 0 && m_LooseBricks <= 0 && !Restarting()) { if (MultiBalls() <= 0 && PowerUps() <= 0) { Events::StageCleared ec; ec.ClearedStage = m_CurrentLevel; ec.StageCluster = m_CurrentCluster; EventBroker->Publish(ec); } else { if (ball != nullptr && MultiBalls() > 0) { Events::MultiBallLost e; EventBroker->Publish(e); m_World->RemoveEntity(entity); } else { auto powerUp = m_World->GetComponent(entity); if (powerUp != nullptr) { SetPowerUps(PowerUps() - 1); m_World->RemoveEntity(entity); } else { if (brick != nullptr) { m_LooseBricks--; m_World->RemoveEntity(entity); } } } } } } bool dd::Systems::LevelSystem::OnPause(const dd::Events::Pause &event) { if (event.Type != "LevelSystem" && event.Type != "All") { return false; } if (IsPaused()) { SetPause(false); } else { SetPause(true); } return true; } void dd::Systems::LevelSystem::CreateBasicLevel(int rows, int lines, glm::vec2 spacesBetweenBricks, float spaceToEdge) { SetNumberOfBricks(rows * lines); //std::cout << "You're only doing this once, right?" << std::endl; int num = Lines(); for (int i = 0; i < rows; i++) { num--; for (int j = 0; j < Lines(); j++) { CreateBrick(i, j, spacesBetweenBricks, spaceToEdge, 0, num, 1); } if (num == 1) num = Lines(); } SetNumberOfBricks(rows * lines); SetRestarting(false); return; } void dd::Systems::LevelSystem::CreateLevel(int aboveBasicLevel) { std::cout << "Loading level: " << m_CurrentLevel << std::endl; SetNumberOfBricks(Rows() * Lines()); int num = Lines(); int getter = 0; for (int i = 0; i < Rows(); i++) { num--; for (int j = 0; j < Lines(); j++) { CreateBrick(i, j, SpaceBetweenBricks(), SpaceToEdge(), aboveBasicLevel, num, m_Bricks[getter]); getter++; } if (num == 1) { num = Lines(); } } m_LooseBricks = NumberOfBricks(); SetRestarting(false); } void dd::Systems::LevelSystem::CreateBrick(int row, int line, glm::vec2 spacesBetweenBricks, float spaceToEdge, int aboveLevel, int num, int typeInt) { if (typeInt == EmptyBrickSpace) { SetNumberOfBricks(NumberOfBricks() - 1); return; } auto brick = m_World->CloneEntity(m_BrickTemplate); m_World->RemoveComponent(brick); auto transform = m_World->GetComponent(brick); auto cBrick = m_World->GetComponent(brick); if (typeInt == StandardBrick) { } else if (typeInt == MultiBallBrick) { cBrick->Type = MultiBallBrick; auto model = m_World->GetComponent(brick); model->ModelFile = "Models/Brick/IceBrick.obj"; } else if (typeInt == LifebuoyBrick) { cBrick->Type = LifebuoyBrick; } float x = line * spacesBetweenBricks.x; float y = row * spacesBetweenBricks.y; transform->Position = glm::vec3(x - 3, 5 - spaceToEdge - y + aboveLevel, -10.f); cBrick->Score = 10 * num; return; } void dd::Systems::LevelSystem::OnEntityRemoved(EntityID entity) { } bool dd::Systems::LevelSystem::OnContact(const dd::Events::Contact &event) { EntityID entityBrick; EntityID entityBall; auto ball = m_World->GetComponent(event.Entity2); auto brick = m_World->GetComponent(event.Entity1); if (brick != nullptr) { entityBrick = event.Entity1; } else { brick = m_World->GetComponent(event.Entity2); if (brick != nullptr) { entityBrick = event.Entity2; } else { return false; } } if (ball != nullptr) { entityBall = event.Entity2; } else { ball = m_World->GetComponent(event.Entity1); if (ball != nullptr) { entityBall = event.Entity1; } else { return false; } } brick = m_World->GetComponent(entityBrick); if (brick == nullptr) { return false; } /*auto power = m_World->GetComponent(entityBrick); if (power != nullptr && NumberOfBricks() > 1) { Events::CreatePowerUp e; auto transform = m_World->GetComponent(entityBrick); e.Position = transform->Position; EventBroker->Publish(e); }*/ if (!Restarting() && !brick->Removed) { brick->Removed = true; // Hit brick with ball code. ball->Combo += 1; Events::ComboEvent ec; ec.Combo = ball->Combo; ec.Ball = entityBall; EventBroker->Publish(ec); auto ballTransform = m_World->GetComponent(entityBall); auto physicsComponent = m_World->GetComponent(entityBrick); physicsComponent->GravityScale = 1.f; physicsComponent->Mask = static_cast(CollisionLayer::Water | CollisionLayer::Wall); auto transformComponentBrick = m_World->GetComponent(entityBrick); auto transformComponentBall = m_World->GetComponent(entityBall); Events::SetImpulse e; e.Entity = entityBrick; glm::vec2 point = glm::vec2(transformComponentBrick->Position.x + ((transformComponentBall->Position.x - transformComponentBrick->Position.x )/4), transformComponentBrick->Position.y + ((transformComponentBall->Position.y - transformComponentBrick->Position.y)/4)); e.Impulse = glm::normalize(point)*5.f;///2.f; e.Point = point; EventBroker->Publish(e); //TODO: Bricks dont collide with walls D= SetNumberOfBricks(NumberOfBricks() - 1); Events::ScoreEvent es; es.Score = brick->Score * ball->Combo; EventBroker->Publish(es); //std::cout << "Combo: " << ball->Combo << std::endl; //std::cout << NumberOfBricks() << std::endl; //std::cout << "Brick Score: " << brick->Score << std::endl; //std::cout << "Score: " << Score() << std::endl; } return true; } bool dd::Systems::LevelSystem::OnScoreEvent(const dd::Events::ScoreEvent &event) { SetScore(Score() += event.Score); return true; } bool dd::Systems::LevelSystem::OnMultiBall(const dd::Events::MultiBall &event) { SetMultiBalls(MultiBalls()+2); return true; } bool dd::Systems::LevelSystem::OnMultiBallLost(const dd::Events::MultiBallLost &event) { SetMultiBalls(MultiBalls()-1); if (MultiBalls() < 0) { SetMultiBalls(0); } return true; } bool dd::Systems::LevelSystem::OnCreatePowerUp(const dd::Events::CreatePowerUp &event) { SetPowerUps(PowerUps() + 1); auto powerUp = m_World->CreateEntity(); std::shared_ptr transform = m_World->AddComponent(powerUp); auto model = m_World->AddComponent(powerUp); std::shared_ptr cRec = m_World->AddComponent(powerUp); std::shared_ptr cPhys = m_World->AddComponent(powerUp); cPhys->CollisionType = CollisionType::Type::Dynamic; cPhys->Category = CollisionLayer::Type::PowerUp; cPhys->Mask = CollisionLayer::Type::Pad; transform->Sticky = false; std::shared_ptr cPow = m_World->AddComponent(powerUp); transform->Position = event.Position; transform->Scale = glm::vec3(0.2, 0.2, 0.2); transform->Velocity = glm::vec3(0, -4, 0); model->ModelFile = "Models/Test/Ball/Ballopus.obj"; m_World->CommitEntity(powerUp); return true; } bool dd::Systems::LevelSystem::OnPowerUpTaken(const dd::Events::PowerUpTaken &event) { SetPowerUps(PowerUps() - 1); return true; } bool dd::Systems::LevelSystem::OnStageCleared(const dd::Events::StageCleared &event) { if (!m_Cleared) { m_Cleared = true; SetRestarting(true); Events::ResetBall e; EventBroker->Publish(e); Events::ScoreEvent es; es.Score = 500; EventBroker->Publish(es); m_CurrentLevel++; if (m_CurrentLevel < 6) { GetNextLevel(); CreateLevel(12); } } return true; } void dd::Systems::LevelSystem::GetNextLevel() { std::array level; // 0 is empty space. // 1 is standard brick. // 2 is multiball brick. if (m_CurrentCluster == 1) { if (m_CurrentLevel == 1) { level = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; } else if (m_CurrentLevel == 2) { level = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; } else if (m_CurrentLevel == 3) { level = {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; } else if (m_CurrentLevel == 4) { level = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}; } else if (m_CurrentLevel == 5) { level = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; } } else if (m_CurrentCluster == 2) { if (m_CurrentLevel == 1) { level = {1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 3, 0, 0, 1}; } else if (m_CurrentLevel == 2) { level = {1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; } else if (m_CurrentLevel == 3) { level = {2, 0, 0, 0, 0, 0, 2, 0, 1, 0, 0, 0, 1, 0, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1}; } else if (m_CurrentLevel == 4) { level = {1, 2, 1, 1, 1, 2, 1, 1, 0, 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0}; } else if (m_CurrentLevel == 5) { level = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 1, 0, 1, 0, 2, 0, 1, 0, 2, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}; } } else if (m_CurrentCluster == 3) { } std::copy(std::begin(level), std::end(level), std::begin(m_Bricks)); } bool dd::Systems::LevelSystem::OnHitPad(const dd::Events::HitPad &event) { m_Cleared = false; return true; }