Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/turretFS14/src/modules/objects/Turret.cc @ 10062

Last change on this file since 10062 was 10061, checked in by muemart, 11 years ago

Lower means better means lower means better…

File size: 9.6 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 *      Marian Runo, Martin Mueller
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "Turret.h"
30#include "core/CoreIncludes.h"
31#include "core/XMLPort.h"
32#include "Scene.h"
33#include <OgreSceneManager.h>
34
35
36namespace orxonox
37{
38    RegisterClass(Turret);
39
40
41
42    /**
43        @brief
44        Sets default values for all variables. Also hides the turret from the radar.
45
46        @param context
47        The context
48     */
49    Turret::Turret(Context* context) : Pawn(context)
50    {
51        RegisterObject(Turret);
52        this->rotationThrust_ = 50;
53        this->startDir_ = Vector3::ZERO;
54        this->localZ_ = Vector3::UNIT_Z;
55        this->localY_ = Vector3::UNIT_Y;
56        this->localX_ = Vector3::UNIT_X;
57        this->maxAttackRadius_ = 200;
58        this->minAttackRadius_ = 0;
59        this->maxPitch_ = 90;
60        this->maxYaw_ = 90;
61        this->once_ = false;
62        this->rotation_ = Quaternion::IDENTITY;
63
64        this->setRadarVisibility(false);
65    }
66
67    /**
68        @brief
69        Destructor. Nothing to see here.
70     */
71    Turret::~Turret()
72    {
73
74    }
75
76    /**
77        @brief
78        Checks, if a WorldEntity is inside the turret's range.
79
80        This function is safe to use on turrets that are attached, rotated, etc.
81        The turret's range is determined with the maxPitch, maxYaw, and the two attackRadius.
82
83        @param target
84        The WorldEntity to check
85
86        @return
87        The squared distance to the position. -1, if it's ouside of range
88    */
89    float Turret::isInRange(const WorldEntity* target ) const
90    {
91        //Check distance
92        Vector3 distance = target->getWorldPosition() - this->getWorldPosition();
93        float distanceVal = distance.squaredLength();
94        if(distanceVal > (this->maxAttackRadius_ * this->maxAttackRadius_) || distanceVal < (this->minAttackRadius_ * this->minAttackRadius_))
95        {
96            return -1.f;
97        }
98
99        //Check pitch
100        Vector3 dir = getTransformedVector(distance, this->localX_, this->localY_, this->localZ_);
101        Vector3 dirProjected = dir;
102        dirProjected.x = 0;
103        Vector3 startDirProjected = this->startDir_;
104        startDirProjected.x = 0;
105        Ogre::Real angle = startDirProjected.angleBetween(dirProjected).valueDegrees();
106        if(angle > this->maxPitch_)
107        {
108            return -1.f;
109        }
110
111        //Check yaw
112        dirProjected = dir;
113        dirProjected.y = 0;
114        startDirProjected = this->startDir_;
115        startDirProjected.y = 0;
116        angle = startDirProjected.angleBetween(dirProjected).valueDegrees();
117        if(angle > this->maxYaw_)
118        {
119            return -1.f;
120        }
121
122        Ogre::SceneManager* scenemanager = this->getScene()->getSceneManager();
123        Ogre::Ray ray = Ogre::Ray(this->getWorldPosition(), distance);
124        Ogre::DefaultRaySceneQuery rayscenequery = Ogre::DefaultRaySceneQuery(scenemanager);
125        rayscenequery.setRay(ray);
126       //rayscenequery.execute();
127
128        return distanceVal;
129    }
130
131    /**
132        @brief
133        Rotates the turret to make it aim at a certain position.
134
135        @note
136        There are no checks, if the position is valid (i.e. if the turret is allowed to aim there).
137        This function must be called again for every tick, or the turret will stop rotating.
138
139        @param position
140        The position to aim at
141    */
142    void Turret::aimAtPosition(const Vector3& position)
143    {
144        Vector3 currDir = this->getWorldOrientation() * WorldEntity::FRONT;
145        Vector3 targetDir = position - this->getWorldPosition();
146
147        this->rotation_ = currDir.getRotationTo(targetDir);
148    }
149
150    /**
151        @brief
152        Does currently nothing.
153
154        Should rotate the turret with the specified pitch. Contains a failed attempt at limiting said rotation.
155    */
156    void Turret::rotatePitch(const Vector2& value)
157    {   
158        //This is a failed attempt at limiting the turret's rotation. It's handled in the controller (for now?)
159        /*
160        Vector3 currentDir = getTransformedVector(this->getOrientation() * WorldEntity::FRONT, this->localX_, this->localY_, this->localZ_);
161        Vector3 currentDirProjected = currentDir;
162        currentDirProjected.x = 0;
163        Vector3 startDirProjected = this->startDir_;
164        startDirProjected.x = 0;     
165        Ogre::Real angle = startDirProjected.angleBetween(currentDirProjected).valueDegrees();
166        //orxout() << "Pitch: " << angle << endl;   
167        //if(angle < this->maxPitch_ || (currentDirProjected.y <= 0 && value.x > 0) || (currentDirProjected.y > 0 && value.x < 0) )
168        {
169            this->localAngularAcceleration_.setX(this->localAngularAcceleration_.x() + value.x*0.8f);
170        }
171        */
172    }
173
174    /**
175        @brief
176        Does currently nothing.
177
178        Should rotate the turret with the specified yaw. Contains a failed attempt at limiting said rotation.
179    */
180    void Turret::rotateYaw(const Vector2& value)
181    {
182        //This is a failed attempt at limiting the turret's rotation. It's handled in the controller (for now?)
183        /*
184        Vector3 currentDir = getTransformedVector(this->getOrientation() * WorldEntity::FRONT, this->localX_, this->localY_, this->localZ_);
185        Vector3 currentDirProjected = currentDir;
186        currentDirProjected.y = 0;
187        Vector3 startDirProjected = this->startDir_;
188        startDirProjected.y = 0;
189        Ogre::Real angle = startDirProjected.angleBetween(currentDirProjected).valueDegrees();
190        orxout() << "Yaw: " << angle << endl;
191        if(angle < this->maxYaw_ || (currentDirProjected.x <= 0 && value.x < 0) || (currentDirProjected.x > 0 && value.x > 0))
192        {
193            this->localAngularAcceleration_.setY(this->localAngularAcceleration_.y() + value.x*0.8f);
194        }
195        */
196    }
197
198    /**
199        @brief
200        Does currently nothing.
201
202        May be used to limit turret's rotation in the future.
203    */
204    void Turret::rotateRoll(const Vector2& value)
205    {
206    }
207
208    /**
209        @brief
210        Loads parameters from xml
211
212        Parameters loaded are: rotationThrust, maxAttackRadius, minAttackRadius, maxYaw, maxPitch
213    */
214    void Turret::XMLPort(Element& xmlelement, XMLPort::Mode mode)
215    {
216        SUPER(Turret, XMLPort, xmlelement, mode);
217       
218        XMLPortParamVariable(Turret, "rotationThrust", rotationThrust_, xmlelement, mode);
219        XMLPortParam(Turret, "maxAttackRadius", setMaxAttackRadius, getMaxAttackRadius, xmlelement, mode);
220        XMLPortParam(Turret, "minAttackRadius", setMinAttackRadius, getMinAttackRadius, xmlelement, mode);
221        XMLPortParam(Turret, "maxYaw", setMaxYaw, getMaxYaw, xmlelement, mode);
222        XMLPortParam(Turret, "maxPitch", setMaxPitch, getMaxPitch, xmlelement, mode);
223    }
224
225    /**
226        @brief
227        The turret's actions are done here.
228
229        Every tick, the turret gets rotated if it should, and the local axes get updated with the parent's rotation.
230   
231        @param dt
232        Duration of the tick
233    */
234    void Turret::tick(float dt)
235    {
236        SUPER(Turret, tick, dt);
237
238        //Stuff isn't properly initialized in the c'tor, so we have to do it like this
239        if(!this->once_)
240        {
241            //Account for rotations done in xml
242            Quaternion startOrient = this->getOrientation();
243            this->localXStart_ = startOrient * this->localX_;
244            this->localXStart_.normalise();
245            this->localX_ = this->localXStart_;
246            this->localYStart_ = startOrient * this->localY_;
247            this->localYStart_.normalise();
248            this->localY_ = this->localYStart_;
249            this->localZStart_ = startOrient * this->localZ_;
250            this->localZStart_.normalise();
251            this->localZ_ = this->localZStart_;
252
253            //startDir should always be (0,0,-1)
254            this->startDir_ = getTransformedVector(startOrient * WorldEntity::FRONT, this->localX_, this->localY_, this->localZ_);
255
256            this->once_ = true;
257
258        }
259
260        //Adjust local axes to parent's rotation
261        WorldEntity* parent = this->getParent();
262        if(parent)
263        {
264            Quaternion parentrot = parent->getWorldOrientation();
265            this->localX_ = parentrot * this->localXStart_;
266            this->localY_ = parentrot * this->localYStart_;
267            this->localZ_ = parentrot * this->localZStart_;
268        }
269
270        //rotate
271        if(this->rotation_ != Quaternion::IDENTITY)
272        {
273            //Don't make the rotation instantaneous. Use an arbitrary interpolation, not that great...
274            //TODO: make the rotation better (constant velocity etc.). At the moment, the turret rotates
275            //      slower the closer it is to the destination
276            Quaternion drot = Quaternion::nlerp(dt*this->rotationThrust_/20.f, Quaternion::IDENTITY, this->rotation_);
277            this->rotate(drot, WorldEntity::World);
278            this->rotation_ = Quaternion::IDENTITY;
279        }
280
281    }
282}
Note: See TracBrowser for help on using the repository browser.