Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/AI_HS15/src/orxonox/controllers/CommonController.cc @ 10762

Last change on this file since 10762 was 10762, checked in by gania, 8 years ago

added a canFire() function

File size: 9.8 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 *      Dominik Solenicki
26 *
27 */
28#include "controllers/CommonController.h"
29#include "core/XMLPort.h"
30
31#include "weaponsystem/WeaponMode.h"
32#include "weaponsystem/WeaponPack.h"
33#include "weaponsystem/Weapon.h"
34#include "weaponsystem/WeaponSlot.h"
35#include "weaponsystem/WeaponSlot.h"
36#include "worldentities/pawns/SpaceShip.h"
37
38
39namespace orxonox
40{
41
42    RegisterClass(CommonController);
43    float SPEED = 0.7f;
44    float ROTATEFACTOR = 0.3f;
45
46    CommonController::CommonController(Context* context) : Controller(context)
47    {
48        this->bSetupWorked = false;
49
50        RegisterObject(CommonController);
51    }
52
53
54    CommonController::~CommonController()
55    {
56    }
57
58    void CommonController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
59    {
60        SUPER(CommonController, XMLPort, xmlelement, mode);
61        XMLPortParam(CommonController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode);
62
63    }
64    void CommonController::setFormationModeXML(std::string val)
65    {
66        const std::string valUpper = getUppercase(val);
67        FormationMode::Value value;
68        if (valUpper == "VEE")
69            value = FormationMode::VEE;
70        else if (valUpper == "WALL")
71            value = FormationMode::WALL;
72        else if (valUpper == "FINGER4")
73            value = FormationMode::FINGER4;
74        else if (valUpper == "DIAMOND")
75            value = FormationMode::DIAMOND;
76        else
77            ThrowException(ParseError, std::string("Attempting to set an unknown FormationMode: '") + val + "'.");
78        this->setFormationMode(value);
79       
80    }
81    std::string CommonController::getFormationModeXML()
82    {
83        switch (this->formationMode_)
84        {
85            case FormationMode::VEE:
86            {
87                return "VEE";
88                break;
89            }
90            case FormationMode::WALL:
91            {
92                return "WALL";
93                break;
94            }
95            case FormationMode::FINGER4:
96            {
97                return "FINGER4";
98                break;
99            }
100            case FormationMode::DIAMOND:
101            {
102                return "DIAMOND";
103                break;
104            }
105            default:
106                return "DIAMOND";
107                break;
108
109        }
110    }
111
112    bool CommonController::setWingman (CommonController* wingman)
113    {
114        return false;
115    }
116   
117    bool CommonController::hasWingman()
118    {
119        return true;
120    }
121    void CommonController::setTarget(ControllableEntity* target)
122    {
123        this->target_ = target;
124        orxout (internal_error) << " TARGET SET " << endl;
125        if (target)
126            this->targetPosition_ = target->getPosition();
127    }
128
129
130
131    void CommonController::setTargetPosition(const Vector3& target)
132    {
133        this->targetPosition_ = target;
134        this->bHasTargetPosition_ = true;
135    }
136
137    void CommonController::setTargetOrientation(const Quaternion& orient)
138    {
139        this->targetOrientation_=orient;
140        this->bHasTargetOrientation_=true;
141    }
142
143    void CommonController::setTargetOrientation(ControllableEntity* target)
144    {
145        if (target)
146            setTargetOrientation(target->getOrientation());
147    }
148
149    /*void CommonController::spin()
150    {
151        this->moveToTargetPosition();
152        this->getControllableEntity()->rotateRoll(8.0f);
153    }
154    void CommonController::turn180()
155    {
156        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
157
158        this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);
159        this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);
160
161        this->getControllableEntity()->moveFrontBack(SPEED);
162    }*/
163
164
165
166    //copy the Roll orientation of given Quaternion.
167    void CommonController::copyOrientation(const Quaternion& orient)
168    {
169        //roll angle difference in radian
170        float diff=orient.getRoll(false).valueRadians()-(this->getControllableEntity()->getOrientation().getRoll(false).valueRadians());
171        while(diff>math::twoPi) diff-=math::twoPi;
172        while(diff<-math::twoPi) diff+=math::twoPi;
173        this->getControllableEntity()->rotateRoll(diff*ROTATEFACTOR);
174    }
175    void CommonController::copyTargetOrientation()
176    {
177        if (bHasTargetOrientation_)
178        {   
179            copyOrientation(targetOrientation_);
180        }
181    }
182
183
184
185
186    void CommonController::moveToTargetPosition()
187    {
188        this->moveToPosition(this->targetPosition_);
189    }
190    void CommonController::moveToPosition(const Vector3& target)
191    {
192        if (!this->getControllableEntity())
193            return;
194        if (this->rank_ == Rank::DIVISIONLEADER)
195            SPEED *= 0.8;
196        if (this->rank_ == Rank::SECTIONLEADER)
197            SPEED *= 0.9;
198       
199        //100 is (so far) the smallest tolerance (empirically found) that can be reached,
200        //with smaller distance spaceships can't reach position and go circles around it instead
201        int tolerance = 60;
202
203        ControllableEntity* entity = this->getControllableEntity();
204        Vector2 coord = get2DViewCoordinates
205            (entity->getPosition(), 
206            entity->getOrientation() * WorldEntity::FRONT, 
207            entity->getOrientation() * WorldEntity::UP, 
208            target);
209
210        float distance = (target - this->getControllableEntity()->getPosition()).length();
211
212        //rotates should be in range [-1,+1], clamp cuts off all that is not
213        float rotateX = clamp(coord.x * 10, -1.0f, 1.0f);
214        float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
215
216       
217        if (distance > tolerance)
218        {
219            //Yaw and Pitch are enough to start facing the target
220            this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR * rotateX);
221            this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR * rotateY);
222
223            //300 works, maybe less is better
224            if (distance < 400)
225            {
226                //Change roll when close. When Spaceship faces target, roll doesn't affect it's trajectory
227                //It's important that roll is not changed in the process of changing yaw and pitch
228                //Wingmen won't face same direction as Leaders, but when Leaders start moving
229                //Yaw and Pitch will adapt.
230                if (bHasTargetOrientation_)
231                {
232                    copyTargetOrientation();
233                }
234            }
235            this->getControllableEntity()->moveFrontBack(1.2f*SPEED);
236        }
237        else
238        {     
239            bHasTargetPosition_ = false;
240            bHasTargetOrientation_ = false;
241        }
242    }
243
244    bool CommonController::isCloseAtTarget(float distance) const
245    {
246        if (!this->getControllableEntity())
247            return false;
248
249        if (!this->target_)
250            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
251        else
252            return (this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
253    }
254   
255
256    bool CommonController::canFire()
257    {
258        //check pointers
259        if (!this->getControllableEntity() || !this->target_ || !this->target_->getControllableEntity())
260            return false;
261       
262        //check if this points in the direction of target_
263
264        Vector3 myPosition = this->getControllableEntity()->getWorldPosition();
265        Vector3 targetPosition = this->target_->getControllableEntity()->getWorldPosition();
266        Vector3 differenceVector = targetPosition - myPosition;
267        float scalarProduct = differenceVector * WorldEntity::FRONT;
268        Vector3 projection = scalarProduct * WorldEntity::FRONT;
269        if ((differenceVector - projection).length() > 50)
270            return false;
271       
272
273        //check if there are allies on the way
274        Vector3 allyPosition, allyDifference, allyProjection;
275        float allyScalarProduct;
276        for (ObjectList<CommonController>::iterator it = ObjectList<CommonController>::begin(); it; ++it)
277        {
278            if (!it->getControllableEntity())
279                continue;
280            if ((this->getControllableEntity()->getTeam() == (it)->getControllableEntity()->getTeam()))
281            {
282                allyPosition = it->getControllableEntity()->getWorldPosition();
283                allyDifference = allyPosition - myPosition;
284                allyScalarProduct = allyDifference * WorldEntity::FRONT;
285                allyProjection = allyScalarProduct * WorldEntity::FRONT;
286                if (allyScalarProduct < 0 || allyScalarProduct > scalarProduct)
287                    continue;
288                if ((allyDifference - allyProjection).length() < 50)
289                    return false;
290            } 
291        }
292
293        return true;
294
295    }
296    void CommonController::doFire()
297    {
298        this->getControllableEntity()->fire(0);
299    }
300   
301
302}
Note: See TracBrowser for help on using the repository browser.