// // Created by jovian on 17/08/17. // #include #include "Universe.h" Universe::Universe() {} Universe::~Universe() { // Planets while (!m_planets.empty()) { if (m_planets.back() != nullptr) delete m_planets.back(); m_planets.pop_back(); } // Ships m_travellingShips.clear(); while (!m_ships.empty()) { if (m_ships.back() != nullptr) delete m_ships.back(); m_ships.pop_back(); } // Rules while (!m_rules.empty()) { if (m_rules.back() != nullptr) delete m_rules.back(); m_rules.pop_back(); } } void Universe::collectVisuals(std::vector &scope) { // Sun scope.push_back(new Visual(13, b2Vec2(0.0f, 0.0f), 0.0f)); // Planets for (auto it(m_planets.begin()); it != m_planets.end(); it++) scope.push_back((*it)->makeVisual()); // Ships for (auto it(m_travellingShips.begin()); it != m_travellingShips.end(); it++) scope.push_back((*it)->makeVisual()); } void Universe::update() { // Apply rules on planets for (auto it_r(m_rules.begin()); it_r != m_rules.end(); it_r++) { for (auto it_p(m_planets.begin()); it_p != m_planets.end(); it_p++) { (*it_p)->applyRule(*it_r); } } // Move ships for (auto it(m_travellingShips.begin()); it != m_travellingShips.end(); it++) (*it)->update(); } void Universe::routeShips() { // Check ready ships bool ready(false); auto it1(m_planets.begin()); while (it1 != m_planets.end() && !ready) { ready = (*it1)->readyShip(); it1++; } // Compute needs if (ready) { // Compute average Stock avrg; for (auto it(m_planets.begin()); it != m_planets.end(); it++) avrg += (*it)->getDef().stock; avrg /= m_planets.size(); // Send ships StarShip *ship(nullptr); Resource majRes; for (auto it(m_planets.begin()); it != m_planets.end(); it++) { if ((*it)->readyShip()) { // Get ship and most resource ship = (*it)->launchShip(avrg); b2Vec2 from(ship->getDef().pos); majRes = ship->getDef().stock.mostResource(); // Seek a ideal planet auto spottedPlanet(m_planets.begin()); bool notFound(true); if (ship->getDef().stock.get(majRes) == 0) { // Seek a master planet for (auto itp(m_planets.begin()++); itp != m_planets.end(); itp++) { if (!(*itp)->need(PEOPLE, avrg) && (*itp)->getId() != (*it)->getId() && (notFound || b2Distance((*spottedPlanet)->getDef().pos, from) > b2Distance((*itp)->getDef().pos, from))) { spottedPlanet = itp; notFound = false; } } } else { // Seek a needed planet for (auto itp(m_planets.begin()++); itp != m_planets.end(); itp++) { if ((*itp)->need(majRes, avrg) && (*itp)->getId() != (*it)->getId() && (notFound || b2Distance((*spottedPlanet)->getDef().pos, from) > b2Distance((*itp)->getDef().pos, from))) { spottedPlanet = itp; notFound = false; } } } // Go toward this planet ship->travelTo((*spottedPlanet)->getId(), (*spottedPlanet)->getDef().pos); m_travellingShips.insert(ship); } } } // Check arrived ships auto it2(m_travellingShips.begin()); while (it2 != m_travellingShips.end()) { if ((*it2)->isArrived()) { m_planets[(*it2)->getTargetPlanet()]->landShip(*it2); it2 = m_travellingShips.erase(it2); } else { it2++; } } } void Universe::createRandomUniverse() { // todo better Universe::createRandomUniverse() // Hand crafted universe PlanetDef def; for (int k(0); k < 12; k++) { def.pos.Set((float)rand() / RAND_MAX * 8.0f - 4.0f, (float)rand() / RAND_MAX * 8.0f - 4.0f); def.size = 0.2f + (float)rand() / RAND_MAX * 2.0f; m_planets.push_back(new Planet(def)); } def.pos.Set(1.0f, 1.0f); def.stock.set(PEOPLE, 2); def.name = "Earth"; def.size = 1.2f; m_planets.push_back(new Planet(def)); // Debug ship StarShipDef s_def; s_def.stock.set(PEOPLE, 10); s_def.pos = b2Vec2(5.0f, 1.3f); // m_planets[2]->getDef().pos StarShip *myShip(new StarShip(s_def)); myShip->travelTo(m_planets[2]->getId(), m_planets[2]->getDef().pos); m_ships.push_back(myShip); m_travellingShips.insert(myShip); } void Universe::addRule(PlanetStep *rule) { m_rules.push_back(rule); } const PlanetDef Universe::getNearestPlanetInfo(b2Vec2 from) { // Void system if (m_planets.empty()) return PlanetDef(); // Search minimum auto spottedPlanet(m_planets.begin()); for (auto it(m_planets.begin()++); it != m_planets.end(); it++) { if (b2Distance((*spottedPlanet)->getDef().pos, from) > b2Distance((*it)->getDef().pos, from)) spottedPlanet = it; } // Return def return (*spottedPlanet)->getDef(); }