/* * ORXONOX - the hottest 3D action shooter ever to exist * > www.orxonox.net < * * * License notice: * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Author: * Michael Baumgartner * Co-authors: * Fabian 'x3n' Landau * */ #include "TowerDefenseController.h" #include "core/CoreIncludes.h" #include "items/Engine.h" #include "worldentities/ControllableEntity.h" #include "worldentities/pawns/SpaceShip.h" #include "TowerDefense.h" #include "TowerDefenseTower.h" #include "TowerDefenseCenterpoint.h" #include "worldentities/SpawnPoint.h" #include "graphics/Model.h" #include "infos/PlayerInfo.h" #include "chat/ChatManager.h" #include "Highscore.h" #include namespace orxonox { RegisterClass(TowerDefenseController); //Offset fuer die Position der Entities auf der Map Vector3 offset_ = Vector3(0,0,10); TowerDefenseController::TowerDefenseController(Context* context) : ArtificialController(context) { RegisterObject(TowerDefenseController); } TowerDefenseController::~TowerDefenseController() //Destructor, ehrlich gesagt keine Ahnung was er genau loescht (nehme an den Controller, falls man am letzten Waypoint angekommen ist.) { } void TowerDefenseController::tick(float dt) { if (!this->isActive()) return; SpaceShip* ship = dynamic_cast(this->getControllableEntity()); if (this->waypoints_.size() == 0 || !ship) return; //Bewegung entlang der Verbindungslinie zweier Waypoints, bis die Distanz zwischen Ihnen zurueckgelegt //wurde, dann eine Drehung in Richtung des Verbindungsvektors zum naechsten Vektor, und Bewegung in diese Richtung. Iterationsfehler werden behoben, indem man zuweit zurueck- //gelegte Wege direkt in die neue Richtung uebernimmt. Dafuer wird in der while-Schleife zuerst berechnet, in welchem Abschnitt man sich befindet, und anschliessend, welche Distanz //man in diesem Abschnitt zurueckgelegt hat. Dann wird die Position des Schiffes einfach auf den entsprechenden Ort gelegt, und geschaut, dass es in die richtige Richtung zeigt. //Die Position kann iterativ bestimmt werden. this->waypoints ist der Array bestehend aus den Wegpunkten, sprich allen Ecken wobei an der Position 0 der SpawnPoint steht. // Geschwindigkeit auslesen float speed; Engine* engine = ship->getEngine(0); if(engine != nullptr) { speed = engine->getMaxSpeedFront(); //Geschwindigkeit sollte ausgelesen werden, wird momentan aber noch NICHT -> ein Fehler mit den Engines } else { speed = 200; //Momentan wird hiermit die Geschwindigkeit ALLER Schiffe gesetzt! } //Zurueckgelegte Gesamtdistanz aktualisieren. totalDistance += speed * dt; float currentDistance = 0; int waypointIdx = 0; bool atEnd = true; while (waypointIdx + 1 < this->waypoints_.size()) { Vector3 prevWaypoint = this->waypoints_[waypointIdx]->getWorldPosition(); Vector3 nextWaypoint = this->waypoints_[waypointIdx + 1]->getWorldPosition(); float waypointDistance = prevWaypoint.distance(nextWaypoint); if (currentDistance + waypointDistance < totalDistance) { currentDistance += waypointDistance; waypointIdx++; } else { atEnd = false; break; } } //Nun sollten wir wissen, zwischen welchen Waypoints sich unser Raumschiff befindet, uns welche Restdistanz wir haben. Wir koennen die Position unseres Raumschiffes nun setzten. //Der Offset ist glaube ich fuer alle Tiles und Objekte noetig, damits am richtigen Ort ist. //Berechnung des Richtungsvektors Vector3 newPosition; Vector3 newDirection; if (atEnd) { newPosition = this->waypoints_.back()->getWorldPosition(); } else { Vector3 prevWaypoint = this->waypoints_[waypointIdx]->getWorldPosition(); Vector3 nextWaypoint = this->waypoints_[waypointIdx + 1]->getWorldPosition(); Vector3 direction = (nextWaypoint - prevWaypoint).normalisedCopy(); newPosition = prevWaypoint + (totalDistance - currentDistance) * direction; newDirection = direction; } this->getControllableEntity()->setPosition(offset_ + newPosition); this->getControllableEntity()->lookAt(this->getControllableEntity()->getPosition() + newDirection); this->getControllableEntity()->setVelocity(speed * newDirection); } }