Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/objects/Turret.cc @ 10248

Last change on this file since 10248 was 10216, checked in by landauf, 10 years ago

merged branch presentationFS14 back to trunk

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