Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/towerdefenseFabien/src/modules/towerdefense/TowerDefense.cc @ 10588

Last change on this file since 10588 was 10588, checked in by landauf, 10 years ago

use the new entity as waypoint (each WaypointController will destroy its waypoints when it is destroyed → each controller must have its own waypoints)

  • Property svn:eol-style set to native
File size: 15.5 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *  Author:
23 *
24 *   Co-authors:
25 *      ...
26 *
27 *NACHRICHT:
28 *
29 * Hier empfehle ich euch die gesamte Spielogik unter zu bringen. Viele Funktionen werden automatisch
30 * bei gewissen Ereignissen aufgerufen bzw. lösen Ereignisse aus
31 *
32 *Z.B:
33 * start() //wird aufgerufen, bevor das Spiel losgeht
34 * end() //wenn man diese Funktion aufruft wird
35 * pawnKilled() // wird aufgerufen, wenn ein Pawn stirbt (z.B: wenn )
36 * playerScored() // kann man aufrufen um dem Spieler Punkte zu vergeben.
37 *
38 *
39 *TIPP: Eclipse hilft euch schnell auf bereits vorhanden Funktionen zuzugreifen:
40 * einfach "this->" eingeben und kurz warten. Dann tauch eine Liste mit Vorschlägen auf. Wenn ihr jetzt weiter
41 * tippt, werden die Vorschläge entsprechend gefiltert.
42 *
43 *
44 *TIPP: schaut euch mal Tetris::createStone() an. Dort wird ein TetrisStone-Objekt (ControllableEntity) erzeugt,
45 * ihm ein Template zugewiesen (welches vorher im Level definiert wurde und dem CenterPoint übergeben wurde)
46 * Ähnlich könnt ihr vorgehen, um einen Turm zu erzeugen. (Zusätzlich braucht ein Turm noch einen Controller)
47 * z.B: WaypointPatrolController. Wenn kein Team zugewiesen wurde bekämpft ein WaypointPatrolController alles,
48 * was in seiner Reichweite liegt.
49 *
50 *
51 *HUD:
52 * Ein Gametype kann ein HUD (Head up Display haben.) Z.B: hat Pong eine Anzeige welcher Spieler wieviele Punkte hat.
53 * Generell kann man a) Grafiken oder b) Zeichen in einer HUD anzeigen.
54 * Fuer den ersten Schritt reicht reiner Text.
55 *
56 * a)
57 * PongScore.cc uebernehmen und eigene Klasse draus machen.
58 * Wenn ihr bloss anzeigen wollt wieviele Punkte der Spieler bereits erspielt hat (Punkte = Kapital fuer neue Tuerme) dann orientiert ihr euch an
59 * TetrisScore.cc (im pCuts branch): http://www.orxonox.net/browser/code/branches/pCuts/src/modules/tetris/TetrisScore.cc
60 * Ich habe TetrisScore lediglich dazu gebraucht, um eine Variable auf dem HUD auszugeben. Ein Objekt fuer statischen Text gibt es bereits.
61 *
62 * b)
63 * Im naesten Schritt erstellt man die Vorlage fuer das HUD-Objekt: siehe /data/overlays/pongHUD
64 * OverlayText ist eine Vorlage fuer statischen text zb: "Points Scored:". Aus mir nicht erklaerlichen Gruenden sollte man die OverlayText
65 * Objekte immer erst nach dem PongScore anlegen.
66 *
67 * c)  Im TowerDefense gamtype muss im Constructor noch das HUD-Template gesetzt werden.
68 *
69 * d) in CMakeLists.txt noch das Module includen das fuer die Overlays zustaendig ist. Siehe das gleiche File im Pong module.
70 *
71 *
72 *
73 */
74#include "TowerDefense.h"
75#include "TowerDefenseTower.h"
76#include "TowerDefenseCenterpoint.h"
77#include "worldentities/SpawnPoint.h"
78#include "controllers/WaypointController.h"
79#include "graphics/Model.h"
80#include "infos/PlayerInfo.h"
81#include "chat/ChatManager.h"
82#include "core/CoreIncludes.h"
83/* Part of a temporary hack to allow the player to add towers */
84#include "core/command/ConsoleCommand.h"
85
86
87namespace orxonox
88{
89    static const std::string __CC_addTower_name  = "addTower";
90    static const std::string __CC_upgradeTower_name = "upgradeTower";
91
92    SetConsoleCommand("TowerDefense", __CC_addTower_name,  &TowerDefense::addTower ).addShortcut().defaultValues(1);
93    SetConsoleCommand("TowerDefense", __CC_upgradeTower_name, &TowerDefense::upgradeTower).addShortcut().defaultValues(0);
94
95    RegisterUnloadableClass(TowerDefense);
96
97    TowerDefense::TowerDefense(Context* context) : TeamDeathmatch(context)
98    {
99        RegisterObject(TowerDefense);
100
101        selecter = NULL;
102        this->player_ = NULL;       
103        this->setHUDTemplate("TowerDefenseHUD");
104        this->nextwaveTimer_.setTimer(10, false, createExecutor(createFunctor(&TowerDefense::nextwave, this)));
105        this->nextwaveTimer_.stopTimer();
106        this->waves_ = 0;
107        this->time = 0;
108        this->credit_ = 0;
109        this->lifes_ = 0;
110
111        //this->stats_ = new TowerDefensePlayerStats();
112
113        ModifyConsoleCommand(__CC_addTower_name).setObject(this);
114        ModifyConsoleCommand(__CC_upgradeTower_name).setObject(this);
115    }
116
117    TowerDefense::~TowerDefense()
118    {        /* Part of a temporary hack to allow the player to add towers */
119        if (this->isInitialized())
120        {
121            ModifyConsoleCommand(__CC_addTower_name).setObject(NULL);
122            ModifyConsoleCommand(__CC_upgradeTower_name).setObject(NULL);
123        }
124    }
125
126    void TowerDefense::setCenterpoint(TowerDefenseCenterpoint *centerpoint)
127    {
128        this->center_ = centerpoint;
129    }
130
131    void TowerDefense::start()
132    {       
133        if (center_ != NULL) // There needs to be a TowerDefenseCenterpoint, i.e. the area the game takes place.
134        {
135            if (selecter == NULL)
136            {
137                selecter = new TowerDefenseSelecter(this->center_->getContext());               
138            }
139            selecter->addTemplate(center_->getSelecterTemplate());
140            center_->attach(selecter);
141        }
142        else // If no centerpoint was specified, an error is thrown and the level is exited.
143        {
144            orxout(internal_error) << "Jump: No Centerpoint specified." << endl;
145            return;
146        }
147
148        enemies_.clear();
149
150        createFields();
151
152        TeamDeathmatch::start();
153
154        // Waypoints: [1,3] [10,3] [10,11] [13,11] -> add the points to a matrix so the player cant place towers on the path
155       
156
157        //set initial credits, lifes and WaveNumber
158        this->setCredit(1000);
159        this->setLifes(100);
160        this->setWaveNumber(0);
161        time = 0.0;
162    }
163
164    // Generates a TowerDefenseEnemy. Uses Template "enemytowerdefense". Sets position at first waypoint of path.
165    void TowerDefense::addTowerDefenseEnemy(int templatenr)
166    {
167        orxout() << "addTowerDefenseEnemy" << endl;
168
169        TowerDefenseEnemy* en1 = new TowerDefenseEnemy(this->center_->getContext());
170       
171        switch(templatenr)
172        {
173        case 1 :
174            en1->addTemplate("enemytowerdefense1");
175            en1->setScale(3);
176            en1->setHealth(en1->getHealth() + this->getWaveNumber()*4);
177            break;
178
179        case 2 :
180            en1->addTemplate("enemytowerdefense2");
181            en1->setScale(2);
182            en1->setHealth(en1->getHealth() + this->getWaveNumber()*4);
183            break;
184
185        case 3 :
186            en1->addTemplate("enemytowerdefense3");
187            en1->setScale(1);
188            en1->setHealth(en1->getHealth() + this->getWaveNumber()*4);
189            break;
190        }       
191
192        en1->setTeam(2);
193
194        //orxonox::WeakPtr<WaypointController> controller = new WaypointController(this->center_->getContext());
195        //controller->setControllableEntity(en1);
196        //en1->setController(controller);
197
198        WaypointController* controller = (WaypointController*)(en1->getXMLController());
199
200        if (controller != NULL && waypoints_.size() > 1)
201        {
202            en1->setPosition(waypoints_.at(0)->getPosition());
203            en1->setOrientation(Vector3(0,0,10), Degree(0));
204            en1->setDirection(Vector3(0,1,0));
205            en1->lookAt(waypoints_.at(1)->getPosition());
206
207            for (unsigned int i = 0; i < waypoints_.size(); ++ i)
208            {
209                orxonox::WeakPtr<MovableEntity> waypoint = new MovableEntity(this->center_->getContext());
210                waypoint->setPosition(waypoints_.at(i)->getPosition());
211                controller->addWaypoint(waypoint);
212            }
213        }
214
215        enemies_.push_back(en1);
216    }
217
218
219    void TowerDefense::end()
220    {
221
222        TeamDeathmatch::end();
223        ChatManager::message("Match is over! Gameover!");
224
225    }
226
227    void TowerDefense::spawnPlayer(PlayerInfo* player)
228    {
229        assert(player);
230        player_ = player;
231
232        orxout() << "spawnPlayer" << endl;
233
234        if (selecter->getPlayer() == NULL)
235        {
236            player_->startControl(selecter);
237            players_[player].state_ = PlayerState::Alive;
238        } 
239    }
240
241    /**
242    @brief
243        Get the player.
244    @return
245        Returns a pointer to the player. If there is no player, NULL is returned.
246    */
247    PlayerInfo* TowerDefense::getPlayer(void) const
248    {
249        return this->player_;
250    }
251
252    //not working yet
253    void TowerDefense::addTower(int x,int y)
254    {
255        TDCoordinate* coord = new TDCoordinate(x,y);
256        x = coord->GetX();
257        y = coord->GetY();
258
259        int cost = center_->getTowerCost(1);
260
261        if (fields_[x][y]->isFree() == true && getCredit() >= cost)
262        {
263            payCredit(cost);
264            fields_[x][y]->createTower(1);
265        }
266    }
267
268    /*adds Tower at Position (x,y) and reduces credit and adds the point to the towermatrix. template ("towerturret")
269    so towers have ability if the turrets
270    */
271
272    void TowerDefense::upgradeTower(int x, int y)
273    {   
274        TDCoordinate* coord = new TDCoordinate(x,y);
275        x = coord->GetX();
276        y = coord->GetY();     
277
278        int cost = center_->getTowerCost(fields_[x][y]->getUpgrade() + 1);
279
280        if (fields_[x][y]->isFree() == false && fields_[x][y]->canUpgrade() == true && getCredit() >= cost)
281        {
282            payCredit(cost);
283            fields_[x][y]->upgrade();
284        }
285    }   
286
287    void TowerDefense::tick(float dt)
288    {
289        //orxout() << "tick1" << endl;
290        SUPER(TowerDefense, tick, dt);
291        //orxout() << "tick2" << endl;
292
293        if (hasStarted() == false || player_ == NULL)
294        {
295            return;
296        }
297        time += dt;       
298
299        //build/upgrade tower at selecter position
300        if (selecter != NULL && selecter->buildTower_ == true)
301        {
302            selecter->buildTower_ = false;
303
304            if (getField(selecter->selectedPos_)->canUpgrade() == true)
305            {
306                upgradeTower(selecter->selectedPos_->GetX(), selecter->selectedPos_->GetY());
307            }
308            else
309            {
310                addTower(selecter->selectedPos_->GetX(), selecter->selectedPos_->GetY());
311            }           
312        }
313
314        if (time >= 1.3 * enemies_.size() && enemies_.size() < 10)
315        {
316            //adds different types of enemys depending on the WaveNumber
317            addTowerDefenseEnemy(this->getWaveNumber() % 3 +1 );
318        }
319
320        //if ships are at the end they get destroyed
321
322        for (std::list<WeakPtr<TowerDefenseEnemy> >::iterator it = enemies_.begin(); it != enemies_.end(); )
323        {
324            //destroys enemys at the end of the path and reduces the life by 1. No credits gifted
325            Vector3 ship = (*it)->getRVWorldPosition();
326            float distance = ship.distance(endpoint_);
327            if(distance < 50)
328            {
329                orxout() << "enemy deleted" << endl;               
330                (*it)->destroy();
331                enemies_.erase(it++);
332                this->reduceLifes(1);
333                if (this->getLifes() == 0)
334                {
335                    this->end();
336                }
337            }
338            else
339            {
340                ++ it;
341            }
342        }       
343
344        if (enemies_.size() == 0 && !this->nextwaveTimer_.isActive())
345        {
346            this->nextwaveTimer_.startTimer();
347        }
348    }
349
350    void TowerDefense::createFields()
351    {
352        assert(center_);
353        TDCoordinate coord(0,0);
354        TDCoordinate startCoord(0,0);
355
356        std::string fields = center_->getFields();
357        int pos = 0;
358        for (int j = 15; j >= 0; --j)
359        {
360            for (int i = 0; i < 16; ++i)
361            {
362                coord.Set(i,j);
363                fields_[i][j] = new TowerDefenseField(center_->getContext());
364                fields_[i][j]->setCenterpoint(center_);
365                center_->attach(fields_[i][j]);
366                fields_[i][j]->setPosition(coord.get3dcoordinate());               
367                fields_[i][j]->create(fields.at(pos), fields.at(pos+1));           
368                pos += 2;
369                if (fields_[i][j]->getType() == START)
370                {
371                    startCoord.Set(i,j);
372                    waypoints_.push_back(fields_[i][j]);
373                }
374            }
375        }
376
377        //Place waypoints along the street for the waypoint controllers of the enemies
378        TDCoordinate* thisCoord = &startCoord;
379        TDCoordinate* nextCoord;
380        while ((nextCoord = getNextStreetCoord(thisCoord)) != NULL)
381        {
382            waypoints_.push_back(fields_[nextCoord->GetX()][nextCoord->GetY()]);           
383            thisCoord = nextCoord;
384            endpoint_ = nextCoord->get3dcoordinate();
385        }
386
387    }
388
389    TDCoordinate* TowerDefense::getNextStreetCoord(TDCoordinate* thisCoord)
390    {       
391        TowerDefenseField* thisField = fields_[thisCoord->GetX()][thisCoord->GetY()];
392        TDCoordinate* nextCoord = new TDCoordinate(0,0);
393
394        if (thisField->getType() != STREET && thisField->getType() != START)
395        {
396            return NULL;
397        }
398
399        if (thisField->getAngle() == 0)
400        {
401            nextCoord->Set(thisCoord->GetX(), thisCoord->GetY() - 1);
402        }
403        else if (thisField->getAngle() == 1)
404        {
405            nextCoord->Set(thisCoord->GetX() + 1, thisCoord->GetY());
406        }
407        else if (thisField->getAngle() == 2)
408        {
409            nextCoord->Set(thisCoord->GetX(), thisCoord->GetY() + 1);
410        }
411        else if (thisField->getAngle() == 3)
412        {
413            nextCoord->Set(thisCoord->GetX() - 1, thisCoord->GetY());
414        }
415
416        if (thisCoord->GetX() != nextCoord->GetX() || thisCoord->GetY() != nextCoord->GetY())
417        {
418            return nextCoord;
419        }
420
421        return NULL;
422    }
423
424    /*
425    void TowerDefense::playerEntered(PlayerInfo* player)
426    {
427        TeamDeathmatch::playerEntered(player);
428
429        const std::string& message = player->getName() + " entered the game";
430        ChatManager::message(message);
431    }
432
433    bool TowerDefense::playerLeft(PlayerInfo* player)
434    {
435        bool valid_player = TeamDeathmatch::playerLeft(player);
436
437        if (valid_player)
438        {
439            const std::string& message = player->getName() + " left the game";
440            ChatManager::message(message);
441        }
442
443        return valid_player;
444    }
445
446
447    void TowerDefense::pawnKilled(Pawn* victim, Pawn* killer)
448    {
449        if (victim && victim->getPlayer())
450        {
451            std::string message;
452            if (killer)
453            {
454                if (killer->getPlayer())
455                    message = victim->getPlayer()->getName() + " was killed by " + killer->getPlayer()->getName();
456                else
457                    message = victim->getPlayer()->getName() + " was killed";
458            }
459            else
460                message = victim->getPlayer()->getName() + " died";
461
462            ChatManager::message(message);
463        }
464
465        TeamDeathmatch::pawnKilled(victim, killer);
466    }
467
468    void TowerDefense::playerScored(PlayerInfo* player, int score)
469    {
470        Gametype::playerScored(player, score);
471    }*/
472}
Note: See TracBrowser for help on using the repository browser.