Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

not compilable change to move behaviour

File size: 12.9 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    //to be called in action
254    //PRE: relativeTargetPosition is desired position relative to the spaceship,
255    //angleRoll is the angle of Roll that should be applied by the end of the movement
256    //POST: targetPosition_ and angleRoll_ are set, so that it can be used by MoveAndRoll()
257    void MoveToPoint(const Vector3& relativeTargetPosition, float angleRoll)
258    {
259        ControllableEntity* entity = this->getControllableEntity();
260        if (!entity)
261            return false;
262        Quaternion orient = entity->getWorldOrientation();
263
264        Vector3 target = orient * relativeTargetPosition + entity->getWorldPosition();
265        setTargetPosition(target);
266        this->angleRoll_ = angleRoll;
267        this->angleRolled_ = 0;
268    }
269    //to be called in tick
270    //PRE: MoveToPoint was called
271    //POST: spaceship changes its yaw and pitch to point towards targetPosition_,
272    //moves towards targetPosition_ by amount depending on dt and its speed,
273    //rolls by amount depending on the difference between angleRoll_ and angleRolled_, dt, and
274    //angular speed
275    //if position reached with a certain tolerance, and angleRolled_ = angleRoll_, returns false,
276    //otherwise returns true
277    bool MoveAndRoll(float dt)
278    {
279        int tolerance = 60;
280        float rollDiff = angleRoll-angleRolled_;
281        float angleToRoll = 0;
282        ControllableEntity* entity = this->getControllableEntity();
283        if (!entity)
284            return false;
285        Vector2 coord = get2DViewCoordinates
286            (entity->getPosition(), 
287            entity->getOrientation() * WorldEntity::FRONT, 
288            entity->getOrientation() * WorldEntity::UP, 
289            targetPosition_);
290
291        float distance = (targetPosition_ - this->getControllableEntity()->getPosition()).length();
292
293        //rotates should be in range [-1,+1], clamp cuts off all that is not
294        float rotateX = clamp(coord.x * 10, -1.0f, 1.0f);
295        float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
296
297       
298        if (distance > tolerance)
299        {
300            //Yaw and Pitch are enough to start facing the target
301            this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR * rotateX * dt);
302            this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR * rotateY * dt);
303           
304            //Move
305            this->getControllableEntity()->moveFrontBack(1.2f * SPEED * factor * dt);
306           
307            //Roll
308            angleToRoll = rollDiff * ROTATEFACTOR * dt;
309            this->getControllableEntity()->rotateRoll(angleToRoll);
310            angleRolled_ += angleToRoll;
311            //if still moving, return false
312            return false;
313        }
314        else
315        {     
316            if (rollDiff > 0)
317            {
318                //Roll
319                angleToRoll = rollDiff * ROTATEFACTOR * dt;
320                this->getControllableEntity()->rotateRoll(angleToRoll);
321                angleRolled_ += angleToRoll;               
322
323                //Move
324                this->getControllableEntity()->moveFrontBack(0.6f * SPEED * factor);
325                return false;
326            }
327            //if finished, return true;
328            retun true;
329        }
330    }
331
332    float squaredDistanceToTarget()
333    {
334        if ( !this->getControllableEntity() )
335            return 0;
336        if ( !this->target_ )
337            return ( this->getControllableEntity()->
338                getPosition().squaredDistance(this->targetPosition_) );
339        else
340            return ( this->getControllableEntity()->
341                getPosition().squaredDistance(this->target_->getPosition()) );
342    }
343   
344    bool CommonController::isLookingAtTarget(float angle) const
345    {
346        if (!this->getControllableEntity())
347            return false;
348
349        return (getAngle(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->targetPosition_) < angle);
350    }
351
352    bool CommonController::canFire()
353    {
354        float squaredDistance = squaredDistanceToTarget();
355        if ( this->bShooting_ && squaredDistance < 9000000 && squaredDistance > 10000 && this->isLookingAtTarget(math::pi /(0.0002f*squaredDistance)) )
356        {
357            return true;
358        }
359        else
360        {
361            return false;
362        }
363
364    }
365    void CommonController::doFire()
366    {
367        if (!this->target_ || !this->getControllableEntity())
368            return;
369        static const float hardcoded_projectile_speed = 750;
370
371        this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getWorldPosition(), hardcoded_projectile_speed, this->target_->getWorldPosition(), this->target_->getVelocity());
372        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
373
374        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
375        if (pawn)
376            pawn->setAimPosition(this->getControllableEntity()->getWorldPosition() + 4000*(this->getControllableEntity()->getOrientation() * WorldEntity::FRONT));
377   
378        this->getControllableEntity()->fire(0);
379    }
380   
381
382}
Note: See TracBrowser for help on using the repository browser.