Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/campaignHS15/src/orxonox/controllers/FlyingController.cc @ 10886

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

improved dodging

File size: 8.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 *      Gani Aliguzhinov
24
25 *   Co-authors:
26 *      Dominik Solenicki
27 *
28 */
29#include "controllers/FlyingController.h"
30#include "core/XMLPort.h"
31#include "worldentities/pawns/SpaceShip.h"
32#include "util/Math.h"
33#include <OgreMatrix3.h>
34
35namespace orxonox
36{   
37    RegisterClass (FlyingController);
38   
39    FlyingController::FlyingController(Context* context): CommonController(context)
40    {
41        RegisterObject(FlyingController);       
42        this->rotationProgress_ = 0;
43        this->spread_ = 200;
44        this->tolerance_ = 100;
45    }
46    FlyingController::~FlyingController() 
47    {
48
49    }
50
51    void FlyingController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
52    {
53        XMLPortParam(FlyingController, "spread", setSpread, getSpread,  xmlelement, mode);
54        XMLPortParam(FlyingController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode);
55        SUPER(FlyingController, XMLPort, xmlelement, mode);
56    }
57   
58    void FlyingController::setFormationModeXML(std::string val)
59    {
60        const std::string valUpper = getUppercase(val);
61        FormationMode::Value value;
62       
63        if ( valUpper == "WALL" )
64            value = FormationMode::WALL;
65        else if ( valUpper == "FINGER4" )
66            value = FormationMode::FINGER4;
67        else if ( valUpper == "DIAMOND" )
68            value = FormationMode::DIAMOND;
69        else
70            ThrowException(ParseError, std::string( "Attempting to set an unknown FormationMode: '" )+ val + "'.");
71        this->setFormationMode(value);
72    }
73    std::string FlyingController::getFormationModeXML() const
74    {
75        switch ( this->formationMode_ )
76        {
77            case FormationMode::WALL:
78            { return "WALL"; break; }
79            case FormationMode::FINGER4:
80            { return "FINGER4"; break; }
81            case FormationMode::DIAMOND:
82            { return "DIAMOND"; break; }
83            default:
84                return "DIAMOND"; break;
85        }
86    }
87    void FlyingController::stopMoving()
88    {
89        this->bHasTargetPosition_ = false;
90    }
91    void FlyingController::moveToPosition(const Vector3& target, float dt)
92    {
93        ControllableEntity* entity = this->getControllableEntity();
94
95        float distance = ( target - entity->getPosition() ).length();
96
97        if ( distance >= this->tolerance_ )
98        {
99            Vector2 coord = get2DViewCoordinates
100                ( entity->getPosition() , 
101                entity->getOrientation()  * WorldEntity::FRONT, 
102                entity->getOrientation()  * WorldEntity::UP, 
103                target );
104            float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
105            float rotateY = clamp( coord.y * 10, -1.0f, 1.0f );
106            entity->rotateYaw( ROTATEFACTOR * rotateX * dt );
107            entity->rotatePitch( ROTATEFACTOR * rotateY * dt );
108         
109            if (distance > this->tolerance_*1.5f || (rotateX > -0.01 && rotateX < 0.01 && rotateY > -0.01 && rotateY < 0.01))
110                entity->moveFrontBack( SPEED * dt );
111                copyTargetOrientation(dt);
112        }
113        else
114        {     
115            bHasTargetPosition_ = false;
116        }
117    }
118   
119    void FlyingController::moveToTargetPosition(float dt)
120    {
121        this->moveToPosition (this->targetPosition_, dt);
122    }
123    void FlyingController::copyOrientation(const Quaternion& orient, float dt)
124    {
125        //inspired by
126        //http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Quaternion+and+Rotation+Primer&structure=Tutorials#Q._How_can_I_make_my_objects_rotate_smoothly_You_mentioned_slerp_etc_
127        //how can I make my objects rotate smoothly?
128       
129        Quaternion myOrient = this->getControllableEntity()->getOrientation();
130        this->rotationProgress_ += dt;
131
132        if (this->rotationProgress_ > 1)
133        {
134            this->rotationProgress_ = 0;
135            this->bHasTargetOrientation_ = false;
136        }
137        else
138        {
139
140            Quaternion delta = Quaternion::Slerp(rotationProgress_, myOrient, orient, true);
141           
142            //rotate roll builds a Quaternion in roll method of WorldEntity, then it sets orientation.
143            //it is faster just to set orientation, plus that way there is no need in calculating the roll angle.
144            //On the downside, however, ship might also yaw and pitch, but this effect is neglectable, as we only call
145            //copyOrientation after we move our ship, thus it doesn't affect ships's flying direction too much.
146            //If you don't like the code style, you are welcomed to uncomment the code below
147            //and comment out setOrientation part, it will work just fine, but it will also be a tiny bit slower.
148            //P.S. apperantly it did affect ship's direction and did so way too much.
149            Matrix3 orientMatrix, myMatrix;
150
151            delta.ToRotationMatrix(orientMatrix);
152            myOrient.ToRotationMatrix (myMatrix);
153
154            Radian yRad, pRad, rRad, yMy, pMy, rMy;
155            orientMatrix.ToEulerAnglesYXZ(yRad, pRad, rRad);
156            myMatrix.ToEulerAnglesYXZ (yMy, pMy, rMy);
157
158            this->getControllableEntity()->rotateRoll ((rRad.valueRadians() - rMy.valueRadians())*ROTATEFACTOR*dt);
159            // this->getControllableEntity()->setOrientation(delta);
160        }
161       
162       
163    }
164    //change log: increased precision, increased rotation speed
165    void FlyingController::copyTargetOrientation(float dt)
166    {
167        if (bHasTargetOrientation_)
168        {   
169            copyOrientation(targetOrientation_, dt);
170        }
171    }
172   
173    void FlyingController::setTargetPosition(const Vector3& target)
174    {
175        this->targetPosition_ = target;
176        this->bHasTargetPosition_ = true;
177    }
178
179    void FlyingController::setTargetOrientation(const Quaternion& orient)
180    {
181        this->targetOrientation_=orient;
182        this->bHasTargetOrientation_=true;
183    }
184
185    void FlyingController::setTargetOrientation(ControllableEntity* target)
186    {
187        if (target)
188            setTargetOrientation(target->getOrientation());
189    }
190    void FlyingController::boostControl()
191    {
192        SpaceShip* ship = orxonox_cast<SpaceShip*>(this->getControllableEntity());
193        if(ship == NULL) return;
194        if(ship->getBoostPower()*1.5f > ship->getInitialBoostPower() ) //upper limit ->boost
195        {
196            this->getControllableEntity()->boost(true);
197        }
198        else if(ship->getBoostPower()*4.0f < ship->getInitialBoostPower()) //lower limit ->do not boost
199        {
200           this->getControllableEntity()->boost(false);
201        }
202    }
203    void FlyingController::keepFormation(const ControllableEntity* leaderEntity, Vector3& targetRelativePosition)
204    {
205        ControllableEntity* myEntity = this->getControllableEntity();
206        Vector3 myPosition = myEntity->getWorldPosition();
207
208        if (!leaderEntity)
209        {
210            return;
211        }
212        Quaternion orient = leaderEntity->getWorldOrientation();
213        Vector3 leaderPosition = leaderEntity->getWorldPosition();
214
215        if (!leaderEntity)
216        {
217            return;
218        }
219        Vector3 targetAbsolutePosition = 
220            (leaderPosition + (orient*WorldEntity::FRONT) * (leaderEntity->getVelocity().length()/5)
221             + (orient* (targetRelativePosition)));
222        //let ship finish rotating. also don't call copyOrientation to often as it is a slow function.
223        if (this->actionCounter_ % 6 == 0 && !this->bHasTargetOrientation_)
224            this->setTargetOrientation (orient);
225        this->setTargetPosition (targetAbsolutePosition);
226        if ((targetAbsolutePosition - myPosition).length() > this->tolerance_ * 1.5f)
227        {
228            this->boostControl();
229        }
230        else
231        {
232           this->getControllableEntity()->boost(false);
233        }
234    }
235}
Note: See TracBrowser for help on using the repository browser.