Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

fixed firing direction

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