Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

did nothing today

File size: 12.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#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/0.02f;
48    float ROTATEFACTOR = 0.3f/0.02f;
49
50    CommonController::CommonController(Context* context) : Controller(context)
51    {
52        this->bSetupWorked = false;
53
54        this->executingManeuver_ = false;
55        this->executingMoveToPoint_ = false;
56
57        RegisterObject(CommonController);
58    }
59
60
61    CommonController::~CommonController()
62    {
63    }
64
65    void CommonController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
66    {
67        SUPER(CommonController, XMLPort, xmlelement, mode);
68        XMLPortParam(CommonController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode);
69
70    }
71    void CommonController::setFormationModeXML(std::string val)
72    {
73        const std::string valUpper = getUppercase(val);
74        FormationMode::Value value;
75        if (valUpper == "VEE")
76            value = FormationMode::VEE;
77        else if (valUpper == "WALL")
78            value = FormationMode::WALL;
79        else if (valUpper == "FINGER4")
80            value = FormationMode::FINGER4;
81        else if (valUpper == "DIAMOND")
82            value = FormationMode::DIAMOND;
83        else
84            ThrowException(ParseError, std::string("Attempting to set an unknown FormationMode: '") + val + "'.");
85        this->setFormationMode(value);
86       
87    }
88    std::string CommonController::getFormationModeXML()
89    {
90        switch (this->formationMode_)
91        {
92            case FormationMode::VEE:
93            {
94                return "VEE";
95                break;
96            }
97            case FormationMode::WALL:
98            {
99                return "WALL";
100                break;
101            }
102            case FormationMode::FINGER4:
103            {
104                return "FINGER4";
105                break;
106            }
107            case FormationMode::DIAMOND:
108            {
109                return "DIAMOND";
110                break;
111            }
112            default:
113                return "DIAMOND";
114                break;
115
116        }
117    }
118
119    bool CommonController::setWingman (CommonController* wingman)
120    {
121        return false;
122    }
123   
124    bool CommonController::hasWingman()
125    {
126        return true;
127    }
128    void CommonController::setTarget(ControllableEntity* target)
129    {
130        this->target_ = target;
131        orxout (internal_error) << " TARGET SET " << endl;
132        if (target)
133            this->targetPosition_ = target->getPosition();
134    }
135
136
137
138    void CommonController::setTargetPosition(const Vector3& target)
139    {
140        this->targetPosition_ = target;
141        this->bHasTargetPosition_ = true;
142    }
143
144    void CommonController::setTargetOrientation(const Quaternion& orient)
145    {
146        this->targetOrientation_=orient;
147        this->bHasTargetOrientation_=true;
148    }
149
150    void CommonController::setTargetOrientation(ControllableEntity* target)
151    {
152        if (target)
153            setTargetOrientation(target->getOrientation());
154    }
155
156    /*void CommonController::spin()
157    {
158        this->moveToTargetPosition();
159        this->getControllableEntity()->rotateRoll(8.0f);
160    }
161    void CommonController::turn180()
162    {
163        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
164
165        this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);
166        this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);
167
168        this->getControllableEntity()->moveFrontBack(SPEED);
169    }*/
170
171
172
173    //copy the Roll orientation of given Quaternion.
174    void CommonController::copyOrientation(const Quaternion& orient, float dt)
175    {
176        //roll angle difference in radian
177        float diff=orient.getRoll(false).valueRadians()-(this->getControllableEntity()->getOrientation().getRoll(false).valueRadians());
178        while(diff>math::twoPi) diff-=math::twoPi;
179        while(diff<-math::twoPi) diff+=math::twoPi;
180        this->getControllableEntity()->rotateRoll(diff*ROTATEFACTOR * dt);
181    }
182    void CommonController::copyTargetOrientation(float dt)
183    {
184        if (bHasTargetOrientation_)
185        {   
186            copyOrientation(targetOrientation_, dt);
187        }
188    }
189
190
191
192
193    void CommonController::moveToTargetPosition(float dt)
194    {
195        this->moveToPosition(this->targetPosition_, dt);
196    }
197    void CommonController::moveToPosition(const Vector3& target, float dt)
198    {
199        float factor = 1;
200        if (!this->getControllableEntity())
201            return;
202        if (this->rank_ == Rank::DIVISIONLEADER)
203            factor = 0.8;
204        if (this->rank_ == Rank::SECTIONLEADER)
205            factor = 0.9;
206       
207        //100 is (so far) the smallest tolerance (empirically found) that can be reached,
208        //with smaller distance spaceships can't reach position and go circles around it instead
209        int tolerance = 60;
210
211        ControllableEntity* entity = this->getControllableEntity();
212        Vector2 coord = get2DViewCoordinates
213            (entity->getPosition(), 
214            entity->getOrientation() * WorldEntity::FRONT, 
215            entity->getOrientation() * WorldEntity::UP, 
216            target);
217
218        float distance = (target - this->getControllableEntity()->getPosition()).length();
219
220        //rotates should be in range [-1,+1], clamp cuts off all that is not
221        float rotateX = clamp(coord.x * 10, -1.0f, 1.0f);
222        float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
223
224       
225        if (distance > tolerance)
226        {
227            //Yaw and Pitch are enough to start facing the target
228            this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR * rotateX * dt);
229            this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR * rotateY * dt);
230
231            //300 works, maybe less is better
232            if (distance < 400)
233            {
234                //Change roll when close. When Spaceship faces target, roll doesn't affect it's trajectory
235                //It's important that roll is not changed in the process of changing yaw and pitch
236                //Wingmen won't face same direction as Leaders, but when Leaders start moving
237                //Yaw and Pitch will adapt.
238                if (bHasTargetOrientation_)
239                {
240                    copyTargetOrientation(dt);
241                }
242            }
243
244            this->getControllableEntity()->moveFrontBack(1.2f*SPEED*factor * dt);
245        }
246        else
247        {     
248            bHasTargetPosition_ = false;
249            bHasTargetOrientation_ = false;
250        }
251    }
252    //to be called in action
253    //PRE: relativeTargetPosition is desired position relative to the spaceship,
254    //angleRoll is the angle in degrees of Roll that should be applied by the end of the movement
255    //POST: target orientation and position are set, so that it can be used by MoveAndRoll()
256    void CommonController::moveToPoint(const Vector3& relativeTargetPosition, float angleRoll)
257    {
258        ControllableEntity* entity = this->getControllableEntity();
259        if (!entity)
260            return;
261        Quaternion orient = entity->getWorldOrientation();
262        Quaternion rotation = Quaternion(Degree(angleRoll), Vector3::UNIT_Z);
263
264        Vector3 target = orient * relativeTargetPosition + entity->getWorldPosition();
265        setTargetPosition(target);
266        orient = orient * rotation;
267        this->setTargetOrientation(orient);
268       
269    }
270    //to be called in tick
271    //PRE: MoveToPoint was called
272    //POST: spaceship changes its yaw and pitch to point towards targetPosition_,
273    //moves towards targetPosition_ by amount depending on dt and its speed,
274    //rolls by amount depending on the difference between angleRoll_ and angleRolled_, dt, and
275    //angular speed
276    //if position reached with a certain tolerance, and angleRolled_ = angleRoll_, returns false,
277    //otherwise returns true
278    //dt is normally around 0.02f, which makes it 1/0.02 = 50 frames/sec
279    bool CommonController::moveAndRoll(float dt)
280    {
281        float factor = 1;
282        if (!this->getControllableEntity())
283            return false;
284        if (this->rank_ == Rank::DIVISIONLEADER)
285            factor = 0.8;
286        if (this->rank_ == Rank::SECTIONLEADER)
287            factor = 0.9;
288        int tolerance = 60;
289       
290        ControllableEntity* entity = this->getControllableEntity();
291        if (!entity)
292            return true;
293        Vector2 coord = get2DViewCoordinates
294            (entity->getPosition(), 
295            entity->getOrientation() * WorldEntity::FRONT, 
296            entity->getOrientation() * WorldEntity::UP, 
297            targetPosition_);
298
299        float distance = (targetPosition_ - this->getControllableEntity()->getPosition()).length();
300
301        //rotates should be in range [-1,+1], clamp cuts off all that is not
302        float rotateX = clamp(coord.x * 10, -1.0f, 1.0f);
303        float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
304
305       
306        if (distance > tolerance)
307        {
308            //Yaw and Pitch are enough to start facing the target
309            this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR * rotateX * dt);
310            this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR * rotateY * dt);
311           
312            //Roll
313            if (bHasTargetOrientation_)
314            {
315                copyTargetOrientation(dt);
316            }
317         
318            //Move
319            this->getControllableEntity()->moveFrontBack(1.2f * SPEED * factor * dt);
320            //if still moving, return false
321            return false;
322        }
323        else
324        {     
325           
326            //if finished, return true;
327            return true;
328        }
329    }
330
331    float CommonController::squaredDistanceToTarget() const
332    {
333        if ( !this->getControllableEntity() )
334            return 0;
335        if ( !this->target_ )
336            return ( this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) );
337        else
338            return ( this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) );
339    }
340   
341    bool CommonController::isLookingAtTarget(float angle) const
342    {
343        if (!this->getControllableEntity())
344            return false;
345
346        return (getAngle(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->targetPosition_) < angle);
347    }
348
349    bool CommonController::canFire()
350    {
351        float squaredDistance = squaredDistanceToTarget();
352        if ( this->bShooting_ && squaredDistance < 9000000 && squaredDistance > 10000 && this->isLookingAtTarget(math::pi /(0.0002f*squaredDistance)) )
353        {
354            return true;
355        }
356        else
357        {
358            return false;
359        }
360
361    }
362    void CommonController::doFire()
363    {
364        if (!this->target_ || !this->getControllableEntity())
365            return;
366        static const float hardcoded_projectile_speed = 750;
367
368        this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getWorldPosition(), hardcoded_projectile_speed, this->target_->getWorldPosition(), this->target_->getVelocity());
369        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
370
371        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
372        if (pawn)
373            pawn->setAimPosition(this->getControllableEntity()->getWorldPosition() + 4000*(this->getControllableEntity()->getOrientation() * WorldEntity::FRONT));
374   
375        this->getControllableEntity()->fire(0);
376    }
377   
378
379}
Note: See TracBrowser for help on using the repository browser.