Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 10774 was 10764, checked in by gania, 9 years ago

fixed canFire() function

File size: 10.3 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        float factor = 1;
193        if (!this->getControllableEntity())
194            return;
195        if (this->rank_ == Rank::DIVISIONLEADER)
196            factor = 0.8;
197        if (this->rank_ == Rank::SECTIONLEADER)
198            factor = 0.9;
199       
200        //100 is (so far) the smallest tolerance (empirically found) that can be reached,
201        //with smaller distance spaceships can't reach position and go circles around it instead
202        int tolerance = 60;
203
204        ControllableEntity* entity = this->getControllableEntity();
205        Vector2 coord = get2DViewCoordinates
206            (entity->getPosition(), 
207            entity->getOrientation() * WorldEntity::FRONT, 
208            entity->getOrientation() * WorldEntity::UP, 
209            target);
210
211        float distance = (target - this->getControllableEntity()->getPosition()).length();
212
213        //rotates should be in range [-1,+1], clamp cuts off all that is not
214        float rotateX = clamp(coord.x * 10, -1.0f, 1.0f);
215        float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
216
217       
218        if (distance > tolerance)
219        {
220            //Yaw and Pitch are enough to start facing the target
221            this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR * rotateX);
222            this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR * rotateY);
223
224            //300 works, maybe less is better
225            if (distance < 400)
226            {
227                //Change roll when close. When Spaceship faces target, roll doesn't affect it's trajectory
228                //It's important that roll is not changed in the process of changing yaw and pitch
229                //Wingmen won't face same direction as Leaders, but when Leaders start moving
230                //Yaw and Pitch will adapt.
231                if (bHasTargetOrientation_)
232                {
233                    copyTargetOrientation();
234                }
235            }
236                    orxout (internal_error) << "MOVING" <<endl ;
237
238            this->getControllableEntity()->moveFrontBack(1.2f*SPEED*factor);
239        }
240        else
241        {     
242            bHasTargetPosition_ = false;
243            bHasTargetOrientation_ = false;
244        }
245    }
246
247    bool CommonController::isCloseAtTarget(float distance) const
248    {
249        if (!this->getControllableEntity())
250            return false;
251
252        if (!this->target_)
253            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
254        else
255            return (this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
256    }
257   
258
259    bool CommonController::canFire()
260    {
261       
262        float tolerance = 50.0f;
263       
264        //check pointers
265        if (!this->getControllableEntity() || !this->target_ || !this->target_->getControllableEntity())
266            return false;
267       
268        //check if this points in the direction of target_
269
270        Vector3 myPosition = this->getControllableEntity()->getWorldPosition();
271        Vector3 targetPosition = this->target_->getControllableEntity()->getWorldPosition();
272       
273        Vector3 differenceVector = targetPosition - myPosition;
274        float differenceLength = differenceVector.length();
275       
276        Vector3 myDirection = this->getControllableEntity()->getOrientation() * WorldEntity::FRONT;
277       
278        float angle = getAngle (myPosition, myDirection, targetPosition);
279        float heightLength = sin(angle) * differenceLength;
280
281        if (heightLength > tolerance)
282            return false;
283       
284
285
286        //check if there are allies on the way
287        Vector3 allyPosition, allyDifference;
288        float allyDifferenceLength, allyAngle, allyHeightLength;
289
290        for (ObjectList<CommonController>::iterator it = ObjectList<CommonController>::begin(); it; ++it)
291        {
292            if (!it->getControllableEntity())
293                continue;
294            if ((this->getControllableEntity()->getTeam() == (it)->getControllableEntity()->getTeam()))
295            {
296                allyPosition = it->getControllableEntity()->getWorldPosition();
297
298                allyDifference = allyPosition - myPosition;
299                allyDifferenceLength = allyDifference.length();
300
301                allyAngle = getAngle (myPosition, myDirection, allyPosition);
302
303                allyHeightLength = sin(allyAngle) * allyDifferenceLength;
304
305                if (allyAngle > math::pi /2)
306                    continue;
307                if (allyHeightLength <= tolerance)
308                    return false;
309            } 
310        }
311
312        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
313        if (pawn)
314            pawn->setAimPosition(WorldEntity::FRONT);
315   
316        return true;
317
318    }
319    void CommonController::doFire()
320    {
321        this->getControllableEntity()->fire(0);
322    }
323   
324
325}
Note: See TracBrowser for help on using the repository browser.