Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6919 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
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 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "ArtificialController.h"
30
31#include "core/CoreIncludes.h"
32#include "core/XMLPort.h"
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"
38#include "controllers/DroneController.h"
39#include "util/Math.h"
40
41namespace orxonox
42{
43
44    static const unsigned int MAX_FORMATION_SIZE = 7;
45    static const int FORMATION_LENGTH =  10;
46    static const int FORMATION_WIDTH =  110;
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
53    ArtificialController::ArtificialController(BaseObject* creator) : Controller(creator)
54    {
55        RegisterObject(ArtificialController);
56
57        this->target_ = 0;
58        this->formationFlight_  =  true;
59        this->myMaster_ = 0;
60        this->freedomCount_ = 0;
61        this->team_ = -1;
62        this->state_ = FREE;
63        this->specificMasterAction_ = NONE;
64        this->specificMasterActionHoldCount_  = 0;
65        this->bShooting_ = false;
66        this->bHasTargetPosition_ = false;
67        this->targetPosition_ = Vector3::ZERO;
68
69        this->target_.setCallback(createFunctor(&ArtificialController::targetDied, this));
70    }
71
72    ArtificialController::~ArtificialController()
73    {
74    }
75
76    void ArtificialController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
77    {
78        SUPER(ArtificialController, XMLPort, xmlelement, mode);
79
80        XMLPortParam(ArtificialController, "team", setTeam, getTeam, xmlelement, mode).defaultValues(-1);
81//         XMLPortParam(ArtificialController, "formation", setFormationFlight, getFormationFlight, xmlelement, mode).defaultValues(true);
82    }
83
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;
93
94        }
95    }
96
97    void ArtificialController::moveToPosition(const Vector3& target)
98    {
99        if (!this->getControllableEntity())
100            return;
101
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();
104
105
106        if(this->state_ == FREE)
107        {
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            }
114
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        }
120
121
122
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);
136        }
137
138
139
140        if(this->state_ == SLAVE)
141        {
142
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);
145
146
147
148
149
150            if (distance < 300)
151            {
152                if (distance < 40)
153                {
154                    this->getControllableEntity()->moveFrontBack(0.8f*SPEED_MASTER);
155                } else this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER);
156
157            } else {
158                this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER + distance/300.0f);
159            }
160        }
161    }
162
163    void ArtificialController::moveToTargetPosition()
164    {
165        this->moveToPosition(this->targetPosition_);
166    }
167
168    int ArtificialController::getState()
169    {
170        return this->state_;
171    }
172
173    void ArtificialController::unregisterSlave() {
174        if(myMaster_)
175        {
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);
179// COUT(0) << "~unregister slave" << std::endl;
180        }
181    }
182
183    void ArtificialController::searchNewMaster()
184    {
185
186        if (!this->getControllableEntity())
187            return;
188
189        this->targetPosition_ = this->getControllableEntity()->getPosition();
190        this->forgetTarget();
191        int teamSize = 0;
192        //go through all pawns
193        for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it; ++it)
194        {
195
196            //same team?
197            if (!ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
198                continue;
199
200            //has it an ArtificialController?
201            if (!it->getController())
202                continue;
203
204            //is pawn oneself?
205            if (static_cast<ControllableEntity*>(*it) == this->getControllableEntity())
206                continue;
207
208            teamSize++;
209
210            ArtificialController *newMaster = static_cast<ArtificialController*>(it->getController());
211
212            //is it a master?
213            if (!newMaster || newMaster->getState() != MASTER)
214                continue;
215
216            float distance = (it->getPosition() - this->getControllableEntity()->getPosition()).length();
217
218            // is pawn in range?
219            if (distance < 5000)
220            {
221                if(newMaster->slaves_.size() > MAX_FORMATION_SIZE) continue;
222
223                for(std::vector<ArtificialController*>::iterator itSlave = this->slaves_.begin(); itSlave != this->slaves_.end(); itSlave++)
224                {
225                    (*itSlave)->myMaster_ = newMaster;
226                    newMaster->slaves_.push_back(*itSlave);
227                }
228                this->slaves_.clear();
229                this->state_ = SLAVE;
230
231                this->myMaster_ = newMaster;
232                newMaster->slaves_.push_back(this);
233
234                break;
235            }
236        }//for
237        //hasn't encountered any masters in range? -> become a master
238        if (state_ != SLAVE  && teamSize != 0) state_ = MASTER;//master encounters master? ->done
239
240    }
241
242    void ArtificialController::commandSlaves() {
243
244        Quaternion orient = this->getControllableEntity()->getOrientation();
245        Vector3 dest = this->getControllableEntity()->getPosition();
246
247        // 1 slave: follow
248        if (this->slaves_.size() == 1)
249        {
250            dest += 4*orient*WorldEntity::BACK;
251            this->slaves_.front()->setTargetPosition(dest);
252        }
253        else 
254        {
255            dest += 1.0f*orient*WorldEntity::BACK;
256            Vector3 pos = Vector3::ZERO;
257            int i = 1;
258
259            for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
260            {
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);
275            }
276        }
277    }
278
279    // binds slaves to new Master within formation
280    void ArtificialController::setNewMasterWithinFormation()
281    {
282
283        if (this->slaves_.empty())
284            return;
285
286        ArtificialController *newMaster = this->slaves_.back();
287        this->slaves_.pop_back();
288
289        if(!newMaster) return;
290        newMaster->state_ = MASTER;
291        newMaster->slaves_ = this->slaves_;
292
293        this->slaves_.clear();
294        this->state_ = SLAVE;
295        this->myMaster_ = newMaster;
296
297        for(std::vector<ArtificialController*>::iterator it = newMaster->slaves_.begin(); it != newMaster->slaves_.end(); it++)
298        {
299            (*it)->myMaster_ = newMaster;
300        }
301
302    }
303
304    void ArtificialController::freeSlaves()
305    {
306        for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
307        {
308            (*it)->state_ = FREE;
309        }
310        this->slaves_.clear();
311    }
312
313    void ArtificialController::forceFreeSlaves()
314    {
315        for(std::vector<ArtificialController*>::iterator it = slaves_.begin(); it != slaves_.end(); it++)
316        {
317            (*it)->state_ = FREE;
318            (*it)->forceFreedom();
319            (*it)->targetPosition_ = this->targetPosition_;
320            (*it)->bShooting_ = true;
321            (*it)->getControllableEntity()->fire(0);// fire once for fun
322        }
323    }
324
325    void ArtificialController::loseMasterState()
326    {
327        this->freeSlaves();
328        this->state_ = FREE;
329    }
330
331    void ArtificialController::forceFreedom()
332    {
333        this->freedomCount_ = FREEDOM_COUNT;
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
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
362    void ArtificialController::setTargetPosition(const Vector3& target)
363    {
364        this->targetPosition_ = target;
365        this->bHasTargetPosition_ = true;
366    }
367
368    void ArtificialController::searchRandomTargetPosition()
369    {
370        this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));
371        this->bHasTargetPosition_ = true;
372    }
373
374    void ArtificialController::setTarget(Pawn* target)
375    {
376        this->target_ = target;
377
378        if (target)
379            this->targetPosition_ = target->getPosition();
380    }
381
382    void ArtificialController::searchNewTarget()
383    {
384COUT(0) << "search new target - start" << std::endl;
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        {
393            if (ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(*it), this->getGametype()))
394                continue;
395
396            if (static_cast<ControllableEntity*>(*it) != this->getControllableEntity())
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        }
409COUT(0) << "search new target - end: " << this->target_ << std::endl;
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
423        static const float hardcoded_projectile_speed = 1250;
424
425        this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getPosition(), hardcoded_projectile_speed, this->target_->getPosition(), this->target_->getVelocity());
426        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
427
428        Pawn* pawn = dynamic_cast<Pawn*>(this->getControllableEntity());
429        if (pawn)
430            pawn->setAimPosition(this->targetPosition_);
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
452    void ArtificialController::abandonTarget(Pawn* target)
453    {
454        if (target == this->target_)
455            this->targetDied();
456    }
457
458    void ArtificialController::targetDied()
459    {
460        this->forgetTarget();
461        this->searchRandomTargetPosition();
462    }
463
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
472        Controller* controller = 0;
473        if (entity1->getController())
474            controller = entity1->getController();
475        else
476            controller = entity1->getXMLController();
477        if (controller)
478        {
479            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
480            if (ac)
481                team1 = ac->getTeam();
482        }
483
484        if (entity1->getController())
485            controller = entity1->getController();
486        else
487            controller = entity1->getXMLController();
488        if (controller)
489        {
490            ArtificialController* ac = orxonox_cast<ArtificialController*>(controller);
491            if (ac)
492                team2 = ac->getTeam();
493        }
494
495        TeamDeathmatch* tdm = orxonox_cast<TeamDeathmatch*>(gametype);
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
505        TeamBaseMatchBase* base = 0;
506        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
507        if (base)
508        {
509            switch (base->getState())
510            {
511                case BaseState::ControlTeam1:
512                    team1 = 0;
513                    break;
514                case BaseState::ControlTeam2:
515                    team1 = 1;
516                    break;
517                case BaseState::Uncontrolled:
518                default:
519                    team1 = -1;
520            }
521        }
522        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
523        if (base)
524        {
525            switch (base->getState())
526            {
527                case BaseState::ControlTeam1:
528                    team2 = 0;
529                    break;
530                case BaseState::ControlTeam2:
531                    team2 = 1;
532                    break;
533                case BaseState::Uncontrolled:
534                default:
535                    team2 = -1;
536            }
537        }
538
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           
547        return (team1 == team2 && team1 != -1);
548    }
549}
Note: See TracBrowser for help on using the repository browser.