Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 11117 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 9.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 *      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        XMLPortParam(Turret, "rotationThrust", setRotationThrust, getRotationThrust, xmlelement, mode);
226    }
227
228    /**
229        @brief
230        The turret's actions are done here.
231
232        Every tick, the turret gets rotated if it should, and the local axes get updated with the parent's rotation.
233   
234        @param dt
235        Duration of the tick
236    */
237    void Turret::tick(float dt)
238    {
239        SUPER(Turret, tick, dt);
240
241        //Stuff isn't properly initialized in the c'tor, so we have to do it like this
242        if(!this->once_)
243        {
244            //Account for rotations done in xml
245            Quaternion startOrient = this->getOrientation();
246            this->localXStart_ = startOrient * this->localX_;
247            this->localXStart_.normalise();
248            this->localX_ = this->localXStart_;
249            this->localYStart_ = startOrient * this->localY_;
250            this->localYStart_.normalise();
251            this->localY_ = this->localYStart_;
252            this->localZStart_ = startOrient * this->localZ_;
253            this->localZStart_.normalise();
254            this->localZ_ = this->localZStart_;
255
256            //startDir should always be (0,0,-1)
257            this->startDir_ = getTransformedVector(startOrient * WorldEntity::FRONT, this->localX_, this->localY_, this->localZ_);
258
259            this->once_ = true;
260
261        }
262
263        //Adjust local axes to parent's rotation
264        WorldEntity* parent = this->getParent();
265        if(parent)
266        {
267            Quaternion parentrot = parent->getWorldOrientation();
268            this->localX_ = parentrot * this->localXStart_;
269            this->localY_ = parentrot * this->localYStart_;
270            this->localZ_ = parentrot * this->localZStart_;
271        }
272
273        //rotate
274        if(this->rotation_ != Quaternion::IDENTITY)
275        {
276            //Don't make the rotation instantaneous. Use an arbitrary interpolation, not that great...
277            //TODO: make the rotation better (constant velocity etc.). At the moment, the turret rotates
278            //slower the closer it is to the destination
279            Quaternion drot = Quaternion::nlerp(dt*this->rotationThrust_/20.f, Quaternion::IDENTITY, this->rotation_);
280            this->rotate(drot, WorldEntity::TransformSpace::World);
281            this->rotation_ = Quaternion::IDENTITY;
282        }
283
284    }
285}
Note: See TracBrowser for help on using the repository browser.