Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Fix team acquisition, edit test level and start to try to make a raytest

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