Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ai/src/orxonox/controllers/ArtificialController.cc @ 6926

Last change on this file since 6926 was 6919, checked in by solex, 15 years ago

finally some decent formation flying!

  • Property svn:eol-style set to native
File size: 18.5 KB
RevLine 
[2362]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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "ArtificialController.h"
30
31#include "core/CoreIncludes.h"
[6601]32#include "core/XMLPort.h"
[5735]33#include "worldentities/ControllableEntity.h"
34#include "worldentities/pawns/Pawn.h"
35#include "worldentities/pawns/TeamBaseMatchBase.h"
36#include "gametypes/TeamDeathmatch.h"
37#include "controllers/WaypointPatrolController.h"
[6918]38#include "controllers/DroneController.h"
[6888]39#include "util/Math.h"
[3049]40
[2362]41namespace orxonox
42{
[6888]43
[6919]44    static const unsigned int MAX_FORMATION_SIZE = 7;
45    static const int FORMATION_LENGTH =  10;
46    static const int FORMATION_WIDTH =  110;
[6888]47    static const int FREEDOM_COUNT = 4; //seconds the slaves in a formation will be set free when master attacks an enemy
48    static const float SPEED_MASTER = 0.6f;
49    static const float ROTATEFACTOR_MASTER = 0.2f;
50    static const float SPEED_FREE = 0.8f;
51    static const float ROTATEFACTOR_FREE = 0.8f;
52
[2362]53    ArtificialController::ArtificialController(BaseObject* creator) : Controller(creator)
54    {
55        RegisterObject(ArtificialController);
56
57        this->target_ = 0;
[6919]58        this->formationFlight_  =  true;
[6695]59        this->myMaster_ = 0;
[6850]60        this->freedomCount_ = 0;
61        this->team_ = -1;
62        this->state_ = FREE;
[6919]63        this->specificMasterAction_ = NONE;
64        this->specificMasterActionHoldCount_  = 0;
[2362]65        this->bShooting_ = false;
66        this->bHasTargetPosition_ = false;
67        this->targetPosition_ = Vector3::ZERO;
[6417]68
[5929]69        this->target_.setCallback(createFunctor(&ArtificialController::targetDied, this));
[2362]70    }
71
72    ArtificialController::~ArtificialController()
73    {
74    }
75
[6601]76    void ArtificialController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
77    {
78        SUPER(ArtificialController, XMLPort, xmlelement, mode);
79
[6919]80        XMLPortParam(ArtificialController, "team", setTeam, getTeam, xmlelement, mode).defaultValues(-1);
81//         XMLPortParam(ArtificialController, "formation", setFormationFlight, getFormationFlight, xmlelement, mode).defaultValues(true);
[6601]82    }
83
[6850]84// gets called when Bot dies
85    void ArtificialController::changedControllableEntity()
86    {
87        if(!getControllableEntity()) 
88        {
89        if (this->state_ == SLAVE) unregisterSlave();
90         if (this->state_ == MASTER) setNewMasterWithinFormation();
91        this->slaves_.clear();
92        this->state_ = FREE;
[6888]93
[6850]94        }
95    }
96
[3049]97    void ArtificialController::moveToPosition(const Vector3& target)
[2362]98    {
99        if (!this->getControllableEntity())
100            return;
101
[3049]102        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
103        float distance = (target - this->getControllableEntity()->getPosition()).length();
[2362]104
[6888]105
106        if(this->state_ == FREE)
[2362]107        {
[6888]108            if (this->target_ || distance > 10)
109            {
110                // Multiply with 0.8 to make them a bit slower
111                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_FREE * sgn(coord.x) * coord.x*coord.x);
112                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_FREE * sgn(coord.y) * coord.y*coord.y);
113            }
[6850]114
[6888]115            if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
116            {
117              this->getControllableEntity()->moveFrontBack(-0.05f); // They don't brake with full power to give the player a chance
118            } else this->getControllableEntity()->moveFrontBack(SPEED_FREE);
119        }
[6850]120
121
122
[6888]123        if(this->state_ == MASTER)
124        {
125            if (this->target_ || distance > 10)
126            {
127                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_MASTER * sgn(coord.x) * coord.x*coord.x);
128                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_MASTER * sgn(coord.y) * coord.y*coord.y);
129
130            }
131
132            if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
133            {
134                this->getControllableEntity()->moveFrontBack(-0.05f);
135            } else this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
[2362]136        }
137
[6888]138
139
140        if(this->state_ == SLAVE)
[6850]141        {
[6888]142
[6919]143           this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR_MASTER * sgn(coord.x) * coord.x*coord.x);
144           this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR_MASTER * sgn(coord.y) * coord.y*coord.y);
[6888]145
146
147
148
149
[6919]150            if (distance < 300)
[6888]151            {
[6919]152                if (distance < 40)
[6888]153                {
[6919]154                    this->getControllableEntity()->moveFrontBack(0.8f*SPEED_MASTER);
155                } else this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER);
[6888]156
157            } else {
[6919]158                this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER + distance/300.0f);
[6888]159            }
[6850]160        }
[2362]161    }
162
[3049]163    void ArtificialController::moveToTargetPosition()
164    {
165        this->moveToPosition(this->targetPosition_);
166    }
167
[6640]168    int ArtificialController::getState()
169    {
170        return this->state_;
171    }
172
[6695]173    void ArtificialController::unregisterSlave() {
174        if(myMaster_)
175        {
[6888]176            std::vector<ArtificialController*>::iterator it = std::find(myMaster_->slaves_.begin(), myMaster_->slaves_.end(), this);
177            if( it != myMaster_->slaves_.end() )
178                myMaster_->slaves_.erase(it);
[6919]179// COUT(0) << "~unregister slave" << std::endl;
[6695]180        }
181    }
182
[6640]183    void ArtificialController::searchNewMaster()
184    {
[6695]185
[6640]186        if (!this->getControllableEntity())
187            return;
188
189        this->targetPosition_ = this->getControllableEntity()->getPosition();
190        this->forgetTarget();
[6919]191        int teamSize = 0;
[6640]192        //go through all pawns
193        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
194        {
[6695]195
196            //same team?
[6640]197            if (!ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
198                continue;
199
[6919]200            //has it an ArtificialController?
[6695]201            if (!it->getController())
202                continue;
[6640]203
[6919]204            //is pawn oneself?
205            if (static_cast<ControllableEntity*>(*it) == this->getControllableEntity())
206                continue;
207
208            teamSize++;
209
[6850]210            ArtificialController *newMaster = static_cast<ArtificialController*>(it->getController());
211
[6919]212            //is it a master?
[6850]213            if (!newMaster || newMaster->getState() != MASTER)
[6640]214                continue;
215
[6888]216            float distance = (it->getPosition() - this->getControllableEntity()->getPosition()).length();
217
[6919]218            // is pawn in range?
219            if (distance < 5000)
[6640]220            {
[6888]221                if(newMaster->slaves_.size() > MAX_FORMATION_SIZE) continue;
[6696]222
[6888]223                for(std::vector<ArtificialController*>::iterator itSlave = this->slaves_.begin(); itSlave != this->slaves_.end(); itSlave++)
[6850]224                {
225                    (*itSlave)->myMaster_ = newMaster;
226                    newMaster->slaves_.push_back(*itSlave);
227                }
[6795]228                this->slaves_.clear();
[6683]229                this->state_ = SLAVE;
[6696]230
[6850]231                this->myMaster_ = newMaster;
232                newMaster->slaves_.push_back(this);
[6696]233
[6695]234                break;
[6640]235            }
236        }//for
[6919]237        //hasn't encountered any masters in range? -> become a master
238        if (state_ != SLAVE  && teamSize != 0) state_ = MASTER;//master encounters master? ->done
[6640]239
240    }
241
[6683]242    void ArtificialController::commandSlaves() {
243
[6888]244        Quaternion orient = this->getControllableEntity()->getOrientation();
245        Vector3 dest = this->getControllableEntity()->getPosition();
246
247        // 1 slave: follow
248        if (this->slaves_.size() == 1)
[6695]249        {
[6888]250            dest += 4*orient*WorldEntity::BACK;
251            this->slaves_.front()->setTargetPosition(dest);
[6695]252        }
[6919]253        else 
[6888]254        {
[6919]255            dest += 1.0f*orient*WorldEntity::BACK;
256            Vector3 pos = Vector3::ZERO;
257            int i = 1;
[6888]258
259            for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
260            {
[6919]261                pos = Vector3::ZERO;
262                if (i <= 1) pos += dest  + FORMATION_WIDTH*WorldEntity::LEFT;
263                if (i == 2) pos += dest  + FORMATION_WIDTH*WorldEntity::RIGHT;
264                if (i == 3) pos += dest  + FORMATION_WIDTH*WorldEntity::UP;
265                if (i >= 4)
266                {
267                    pos += dest  + FORMATION_WIDTH*WorldEntity::DOWN;
268                    i = 1;
269                    dest += FORMATION_LENGTH*orient*WorldEntity::BACK;
270                    (*it)->setTargetPosition(pos);
271                    continue;
272                }
273                i++;
274                (*it)->setTargetPosition(pos);
[6888]275            }
276        }
[6683]277    }
278
[6795]279    // binds slaves to new Master within formation
280    void ArtificialController::setNewMasterWithinFormation()
281    {
[6888]282
[6795]283        if (this->slaves_.empty())
284            return;
285
286        ArtificialController *newMaster = this->slaves_.back();
287        this->slaves_.pop_back();
[6888]288
[6795]289        if(!newMaster) return;
290        newMaster->state_ = MASTER;
291        newMaster->slaves_ = this->slaves_;
[6888]292
[6850]293        this->slaves_.clear();
[6795]294        this->state_ = SLAVE;
295        this->myMaster_ = newMaster;
296
[6888]297        for(std::vector<ArtificialController*>::iterator it = newMaster->slaves_.begin(); it != newMaster->slaves_.end(); it++)
[6795]298        {
299            (*it)->myMaster_ = newMaster;
300        }
301
302    }
303
[6850]304    void ArtificialController::freeSlaves()
[6683]305    {
[6888]306        for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
[6696]307        {
308            (*it)->state_ = FREE;
309        }
[6850]310        this->slaves_.clear();
311    }
312
313    void ArtificialController::forceFreeSlaves()
314    {
[6888]315        for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
[6683]316        {
[6850]317            (*it)->state_ = FREE;
318            (*it)->forceFreedom();
319            (*it)->targetPosition_ = this->targetPosition_;
320            (*it)->bShooting_ = true;
[6888]321            (*it)->getControllableEntity()->fire(0);// fire once for fun
[6683]322        }
[6696]323    }
[6683]324
[6696]325    void ArtificialController::loseMasterState()
326    {
[6850]327        this->freeSlaves();
[6696]328        this->state_ = FREE;
[6683]329    }
330
[6850]331    void ArtificialController::forceFreedom()
332    {
[6888]333        this->freedomCount_ = FREEDOM_COUNT;
[6850]334    }
335
336    bool ArtificialController::forcedFree()
337    {
338        if(this->freedomCount_ > 0) 
339        {
340            this->freedomCount_--;
341            return true;
342        } else return false;
343    }
344
[6919]345    void ArtificialController::specificMasterActionHold()
346    {
347        if (specificMasterActionHoldCount_ == 0) this->specificMasterAction_ = NONE;
348        else specificMasterActionHoldCount_--;
349    }
350
351    void ArtificialController::turn180()
352    {
353        this->specificMasterAction_  =  NONE;
354    }
355
356    void ArtificialController::spin()
357    {
358        this->specificMasterAction_  =  NONE;
359    }
360
361
[3049]362    void ArtificialController::setTargetPosition(const Vector3& target)
363    {
364        this->targetPosition_ = target;
365        this->bHasTargetPosition_ = true;
366    }
367
[2362]368    void ArtificialController::searchRandomTargetPosition()
369    {
[2493]370        this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));
[2362]371        this->bHasTargetPosition_ = true;
372    }
373
[3049]374    void ArtificialController::setTarget(Pawn* target)
375    {
376        this->target_ = target;
377
378        if (target)
379            this->targetPosition_ = target->getPosition();
380    }
381
[2362]382    void ArtificialController::searchNewTarget()
383    {
[6918]384COUT(0) << "search new target - start" << std::endl;
[2362]385        if (!this->getControllableEntity())
386            return;
387
388        this->targetPosition_ = this->getControllableEntity()->getPosition();
389        this->forgetTarget();
390
391        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
392        {
[3049]393            if (ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
394                continue;
395
[2506]396            if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity())
[2362]397            {
398                float speed = this->getControllableEntity()->getVelocity().length();
399                Vector3 distanceCurrent = this->targetPosition_ - this->getControllableEntity()->getPosition();
400                Vector3 distanceNew = it->getPosition() - this->getControllableEntity()->getPosition();
401                if (!this->target_ || it->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceNew) / speed / distanceNew.length()) / (2 * Ogre::Math::PI))
402                        < this->targetPosition_.squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / (2 * Ogre::Math::PI)) + rnd(-250, 250))
403                {
404                    this->target_ = (*it);
405                    this->targetPosition_ = it->getPosition();
406                }
407            }
408        }
[6918]409COUT(0) << "search new target - end: " << this->target_ << std::endl;
[2362]410    }
411
412    void ArtificialController::forgetTarget()
413    {
414        this->target_ = 0;
415        this->bShooting_ = false;
416    }
417
418    void ArtificialController::aimAtTarget()
419    {
420        if (!this->target_ || !this->getControllableEntity())
421            return;
422
[2493]423        static const float hardcoded_projectile_speed = 1250;
[2362]424
[2493]425        this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getPosition(), hardcoded_projectile_speed, this->target_->getPosition(), this->target_->getVelocity());
[2362]426        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
[6417]427
428        Pawn* pawn = dynamic_cast<Pawn*>(this->getControllableEntity());
429        if (pawn)
430            pawn->setAimPosition(this->targetPosition_);
[2362]431    }
432
433    bool ArtificialController::isCloseAtTarget(float distance) const
434    {
435        if (!this->getControllableEntity())
436            return false;
437
438        if (!this->target_)
439            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
440        else
441            return (this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
442    }
443
444    bool ArtificialController::isLookingAtTarget(float angle) const
445    {
446        if (!this->getControllableEntity())
447            return false;
448
449        return (getAngle(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->targetPosition_) < angle);
450    }
451
[5929]452    void ArtificialController::abandonTarget(Pawn* target)
[2362]453    {
[5929]454        if (target == this->target_)
455            this->targetDied();
[2362]456    }
[3049]457
[5929]458    void ArtificialController::targetDied()
459    {
460        this->forgetTarget();
461        this->searchRandomTargetPosition();
462    }
463
[3049]464    bool ArtificialController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
465    {
466        if (entity1 == entity2)
467            return true;
468
469        int team1 = -1;
470        int team2 = -1;
471
[6601]472        Controller* controller = 0;
473        if (entity1->getController())
474            controller = entity1->getController();
475        else
476            controller = entity1->getXMLController();
477        if (controller)
[3049]478        {
[6601]479            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
480            if (ac)
481                team1 = ac->getTeam();
[3049]482        }
[6601]483
484        if (entity1->getController())
485            controller = entity1->getController();
486        else
487            controller = entity1->getXMLController();
488        if (controller)
[3049]489        {
[6601]490            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
491            if (ac)
492                team2 = ac->getTeam();
[3049]493        }
494
[3325]495        TeamDeathmatch* tdm = orxonox_cast<TeamDeathmatch*>(gametype);
[3049]496        if (tdm)
497        {
498            if (entity1->getPlayer())
499                team1 = tdm->getTeam(entity1->getPlayer());
500
501            if (entity2->getPlayer())
502                team2 = tdm->getTeam(entity2->getPlayer());
503        }
504
[3086]505        TeamBaseMatchBase* base = 0;
[3325]506        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
[3086]507        if (base)
508        {
509            switch (base->getState())
510            {
[3280]511                case BaseState::ControlTeam1:
[3086]512                    team1 = 0;
513                    break;
[3280]514                case BaseState::ControlTeam2:
[3086]515                    team1 = 1;
516                    break;
[3280]517                case BaseState::Uncontrolled:
[3086]518                default:
519                    team1 = -1;
520            }
521        }
[3325]522        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
[3086]523        if (base)
524        {
525            switch (base->getState())
526            {
[3280]527                case BaseState::ControlTeam1:
[3086]528                    team2 = 0;
529                    break;
[3280]530                case BaseState::ControlTeam2:
[3086]531                    team2 = 1;
532                    break;
[3280]533                case BaseState::Uncontrolled:
[3086]534                default:
535                    team2 = -1;
536            }
537        }
538
[6891]539        DroneController* droneController = 0;
540        droneController = orxonox_cast<DroneController*>(entity1->getController());
541        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
542            return true;
543        droneController = orxonox_cast<DroneController*>(entity2->getController());
544        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
545            return true;
546           
[3049]547        return (team1 == team2 && team1 != -1);
548    }
[2362]549}
Note: See TracBrowser for help on using the repository browser.