Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/orxonox/worldentities/pawns/SpaceShip.cc @ 8658

Last change on this file since 8658 was 8658, checked in by landauf, 13 years ago

the "lift" which is applied to the spaceship when pitching is now also applied when yawing.
moving up/down or left/right is now again possible.

  • Property svn:eol-style set to native
File size: 15.1 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 *      ...
26 *
27 */
28
29#include "SpaceShip.h"
30
31#include <BulletDynamics/Dynamics/btRigidBody.h>
32
33#include "core/CoreIncludes.h"
34#include "core/ConfigValueIncludes.h"
35#include "core/Template.h"
36#include "core/XMLPort.h"
37#include "tools/Shader.h"
38#include "util/Debug.h" // TODO: Needed?
39#include "util/Math.h"
40
41#include "graphics/Camera.h"
42#include "items/Engine.h"
43
44#include "CameraManager.h"
45#include "Scene.h"
46
47namespace orxonox
48{
49    const float orientationGain = 100;
50    CreateFactory(SpaceShip);
51
52    SpaceShip::SpaceShip(BaseObject* creator) : Pawn(creator), boostBlur_(NULL)
53    {
54        RegisterObject(SpaceShip);
55
56        this->primaryThrust_  = 100;
57        this->auxilaryThrust_ =  30;
58        this->rotationThrust_ =  10;
59
60        this->localLinearAcceleration_.setValue(0, 0, 0);
61        this->localAngularAcceleration_.setValue(0, 0, 0);
62        this->bBoost_ = false;
63        this->steering_ = Vector3::ZERO;
64
65        this->boostPower_ = 10.0f;
66        this->initialBoostPower_ = 10.0f;
67        this->boostRate_ = 5.0;
68        this->boostPowerRate_ = 1.0;
69        this->boostCooldownDuration_ = 5.0;
70        this->bBoostCooldown_ = false;
71
72        this->lift_ = 1.0f;                         // factor of the lift, standard is 1
73        this->stallSpeed_ = 220.0f;                 // max speed where lift is added
74
75        this->bInvertYAxis_ = false;
76
77        this->setDestroyWhenPlayerLeft(true);
78
79        // SpaceShip is always a physical object per default
80        // Be aware of this call: The collision type legality check will not reach derived classes!
81        this->setCollisionType(WorldEntity::Dynamic);
82        // Get notification about collisions
83        this->enableCollisionCallback();
84
85        this->engineTicksNotDone = 0;
86        this->setConfigValues();
87        this->registerVariables();
88       
89        this->cameraOriginalPosition_ = Vector3::UNIT_SCALE;
90        this->cameraOriginalOrientation_ = Quaternion::IDENTITY;
91
92        this->shakeFrequency_ = 15;
93        this->shakeAmplitude_ = 5;
94        this->shakeDt_ = 0;
95    }
96
97    SpaceShip::~SpaceShip()
98    {
99        if (this->isInitialized())
100        {
101            this->removeAllEngines();
102       
103            if (this->boostBlur_)
104                this->boostBlur_->destroy();
105        }
106    }
107
108    void SpaceShip::XMLPort(Element& xmlelement, XMLPort::Mode mode)
109    {
110        SUPER(SpaceShip, XMLPort, xmlelement, mode);
111
112        //XMLPortParam(SpaceShip, "engine",            setEngineTemplate,    getEngineTemplate,    xmlelement, mode);
113        XMLPortParamVariable(SpaceShip, "primaryThrust",  primaryThrust_,  xmlelement, mode);
114        XMLPortParamVariable(SpaceShip, "auxilaryThrust", auxilaryThrust_, xmlelement, mode);
115        XMLPortParamVariable(SpaceShip, "rotationThrust", rotationThrust_, xmlelement, mode);
116        XMLPortParamVariable(SpaceShip, "boostPower", initialBoostPower_, xmlelement, mode);
117        XMLPortParamVariable(SpaceShip, "boostPowerRate", boostPowerRate_, xmlelement, mode);
118        XMLPortParamVariable(SpaceShip, "boostRate", boostRate_, xmlelement, mode);
119        XMLPortParamVariable(SpaceShip, "boostCooldownDuration", boostCooldownDuration_, xmlelement, mode);
120        XMLPortParamVariable(SpaceShip, "shakeFrequency", shakeFrequency_, xmlelement, mode);
121        XMLPortParamVariable(SpaceShip, "shakeAmplitude", shakeAmplitude_, xmlelement, mode);
122        XMLPortParamVariable(SpaceShip, "lift", lift_, xmlelement, mode);
123        XMLPortParamVariable(SpaceShip, "stallSpeed", stallSpeed_, xmlelement, mode);
124
125        XMLPortObject(SpaceShip, Engine, "engines", addEngine, getEngine, xmlelement, mode);
126    }
127
128    void SpaceShip::registerVariables()
129    {
130        registerVariable(this->primaryThrust_,  VariableDirection::ToClient);
131        registerVariable(this->auxilaryThrust_, VariableDirection::ToClient);
132        registerVariable(this->rotationThrust_, VariableDirection::ToClient);
133        // TODO: Synchronization of boost needed?
134        registerVariable(this->boostPower_, VariableDirection::ToClient);
135        registerVariable(this->boostPowerRate_, VariableDirection::ToClient);
136        registerVariable(this->boostRate_, VariableDirection::ToClient);
137        registerVariable(this->boostCooldownDuration_, VariableDirection::ToClient);
138        registerVariable(this->shakeFrequency_, VariableDirection::ToClient);
139        registerVariable(this->shakeAmplitude_, VariableDirection::ToClient);
140        registerVariable(this->lift_, VariableDirection::ToClient);
141        registerVariable(this->stallSpeed_, VariableDirection::ToClient);
142    }
143
144    void SpaceShip::setConfigValues()
145    {
146        SetConfigValue(bInvertYAxis_, false).description("Set this to true for joystick-like mouse behaviour (mouse up = ship down).");
147       
148        SetConfigValueExternal(bEnableMotionBlur_, "GraphicsSettings", "enableMotionBlur", true)
149            .description("Enable or disable the motion blur effect when moving very fast")
150            .callback(this, &SpaceShip::changedEnableMotionBlur);
151        SetConfigValueExternal(blurStrength_, "GraphicsSettings", "blurStrength", 3.0f)
152            .description("Defines the strength of the motion blur effect");
153    }
154
155    bool SpaceShip::isCollisionTypeLegal(WorldEntity::CollisionType type) const
156    {
157        if (type != WorldEntity::Dynamic)
158        {
159            CCOUT(1) << "Error: Cannot tell a SpaceShip not to be dynamic! Ignoring." << std::endl;
160            assert(false); // Only in debug mode
161            return false;
162        }
163        else
164            return true;
165    }
166
167    void SpaceShip::tick(float dt)
168    {
169        SUPER(SpaceShip, tick, dt);
170
171        if (this->hasLocalController())
172        {
173            // Handle mouse look
174            if (!this->isInMouseLook())
175            {
176                this->localAngularAcceleration_ *= this->getLocalInertia() * this->rotationThrust_;
177                this->physicalBody_->applyTorque(physicalBody_->getWorldTransform().getBasis() * this->localAngularAcceleration_);
178            }
179            this->localAngularAcceleration_.setValue(0, 0, 0);
180
181            // Charge boostPower
182            if(!this->bBoostCooldown_ && this->boostPower_ < this->initialBoostPower_)
183            {
184                this->boostPower_ += this->boostPowerRate_*dt;
185            }
186            // Use boostPower
187            if(this->bBoost_)
188            {
189                this->boostPower_ -=this->boostRate_*dt;
190                if(this->boostPower_ <= 0.0f)
191                {
192                    this->boost(false);
193                    this->bBoostCooldown_ = true;
194                    this->timer_.setTimer(this->boostCooldownDuration_, false, createExecutor(createFunctor(&SpaceShip::boostCooledDown, this)));
195                }
196
197                this->shakeCamera(dt);
198            }
199
200            // Enable Blur depending on settings
201            if (this->bEnableMotionBlur_ && !this->boostBlur_ && this->hasLocalController() && this->hasHumanController())
202            {
203                this->boostBlur_ = new Shader(this->getScene()->getSceneManager());
204                this->boostBlur_->setCompositorName("Radial Blur");
205            }
206
207            if (this->boostBlur_) // && this->maxSpeedFront_ != 0 && this->boostFactor_ != 1)
208            {
209                // TODO: this->maxSpeedFront_ gets fastest engine
210                float blur = this->blurStrength_ * clamp((-this->getLocalVelocity().z - 0.0f /*this->maxSpeedFront_*/) / ((150.0f /*boostFactor_*/ - 1) * 1.5f /*this->maxSpeedFront_*/), 0.0f, 1.0f);
211
212                // Show and hide blur effect depending on state of booster
213                if(this->bBoost_)
214                    this->boostBlur_->setVisible(blur > 0);
215                else
216                    this->boostBlur_->setVisible(false);
217
218                this->boostBlur_->setParameter(0, 0, "sampleStrength", blur);
219            }
220        }
221    }
222
223    void SpaceShip::moveFrontBack(const Vector2& value)
224    {
225        this->localLinearAcceleration_.setZ(this->localLinearAcceleration_.z() - value.x);
226        this->steering_.z -= value.x;
227    }
228
229    void SpaceShip::moveRightLeft(const Vector2& value)
230    {
231        this->localLinearAcceleration_.setX(this->localLinearAcceleration_.x() + value.x);
232        this->steering_.x += value.x;
233    }
234
235    void SpaceShip::moveUpDown(const Vector2& value)
236    {
237        this->localLinearAcceleration_.setY(this->localLinearAcceleration_.y() + value.x);
238        this->steering_.y += value.x;
239    }
240
241    void SpaceShip::rotateYaw(const Vector2& value)
242    {
243        this->localAngularAcceleration_.setY(this->localAngularAcceleration_.y() + value.x);
244
245        Pawn::rotateYaw(value);
246
247                //This function call adds a lift to the ship when it is rotating to make it's movement more "realistic" and enhance the feeling.
248        if (abs(this-> getLocalVelocity().z) < stallSpeed_)  {this->moveRightLeft(-lift_ / 5 * value * sqrt(abs(this-> getLocalVelocity().z)));}
249    }
250
251    void SpaceShip::rotatePitch(const Vector2& value)
252    {
253        this->localAngularAcceleration_.setX(this->localAngularAcceleration_.x() + value.x*0.8f);
254
255        Pawn::rotatePitch(value);
256
257                //This function call adds a lift to the ship when it is pitching to make it's movement more "realistic" and enhance the feeling.
258        if (abs(this-> getLocalVelocity().z) < stallSpeed_)  {this->moveUpDown(lift_ / 5 * value * sqrt(abs(this-> getLocalVelocity().z)));}
259    }
260
261    void SpaceShip::rotateRoll(const Vector2& value)
262    {
263        this->localAngularAcceleration_.setZ(this->localAngularAcceleration_.z() + value.x);
264
265        Pawn::rotateRoll(value);
266    }
267
268    void SpaceShip::fire()
269    {
270    }
271
272    /**
273    @brief
274        Starts or stops boosting.
275    @param bBoost
276        Whether to start or stop boosting.
277    */
278    void SpaceShip::boost(bool bBoost)
279    {
280        if(bBoost && !this->bBoostCooldown_)
281        {
282            this->bBoost_ = true;
283            Camera* camera = CameraManager::getInstance().getActiveCamera();
284            this->cameraOriginalPosition_ = camera->getPosition();
285            this->cameraOriginalOrientation_ = camera->getOrientation();
286        }
287        if(!bBoost)
288        {
289            this->bBoost_ = false;
290            this->resetCamera();
291        }
292    }
293
294    void SpaceShip::boostCooledDown(void)
295    {
296        this->bBoostCooldown_ = false;
297    }
298   
299    void SpaceShip::shakeCamera(float dt)
300    {
301        //make sure the ship is only shaking if it's moving
302        if (this->getVelocity().squaredLength() > 80.0f)
303        {
304            this->shakeDt_ += dt;
305   
306            float frequency = this->shakeFrequency_ * (this->getVelocity().squaredLength());
307   
308            if (this->shakeDt_ >= 1.0f/frequency)
309            {
310                this->shakeDt_ -= 1.0f/frequency;
311            }
312   
313            Degree angle = Degree(sin(this->shakeDt_ *2.0f* math::pi * frequency) * this->shakeAmplitude_);
314   
315            //COUT(0) << "Angle: " << angle << std::endl;
316            Camera* camera = this->getCamera();
317
318            //Shaking Camera effect
319            if (camera != 0)
320            {
321                camera->setOrientation(Vector3::UNIT_X, angle);
322            }
323        }
324    }
325
326    void SpaceShip::resetCamera()
327    {
328        Camera *camera = this->getCamera();
329
330        if (camera == 0)
331        {
332            COUT(2) << "Failed to reset camera!";
333            return;
334        }
335   
336        this->shakeDt_ = 0;
337        camera->setPosition(this->cameraOriginalPosition_);
338        camera->setOrientation(this->cameraOriginalOrientation_);
339    }
340
341    void SpaceShip::backupCamera()
342    {
343        Camera* camera = CameraManager::getInstance().getActiveCamera();
344        if(camera != NULL)
345        {
346            this->cameraOriginalPosition_ = camera->getPosition();
347            this->cameraOriginalOrientation_ = camera->getOrientation();
348        }
349    }
350
351    void SpaceShip::addEngine(orxonox::Engine* engine)
352    {
353        //COUT(0)<<"Adding an Engine: " << engine << endl;
354        this->engineList_.push_back(engine);
355        engine->addToSpaceShip(this);
356        this->resetEngineTicks();
357    }
358
359    bool SpaceShip::hasEngine(Engine* engine)
360    {
361        for(unsigned int i=0; i<this->engineList_.size(); i++)
362        {
363            if(this->engineList_[i]==engine)
364                return true;
365        }
366        return false;
367    }
368
369    Engine* SpaceShip::getEngine(unsigned int i)
370    {
371        if(this->engineList_.size()>=i)
372            return 0;
373        else
374            return this->engineList_[i];
375    }
376
377    void SpaceShip::removeAllEngines()
378    {
379        while(this->engineList_.size())
380            this->engineList_.back()->destroy();
381    }
382   
383    void SpaceShip::removeEngine(Engine* engine)
384    {
385        for(std::vector<Engine*>::iterator it=this->engineList_.begin(); it!=this->engineList_.end(); ++it)
386        {
387            if(*it==engine)
388            {
389                this->engineList_.erase(it);
390                return;
391            }
392        }
393    }
394
395    void SpaceShip::setSpeedFactor(float factor)
396    {
397        for(unsigned int i=0; i<this->engineList_.size(); i++)
398            this->engineList_[i]->setSpeedFactor(factor);
399    }
400    float SpaceShip::getSpeedFactor() // Calculate mean SpeedFactor.
401    {
402        float ret = 0; unsigned int i = 0;
403        for(; i<this->engineList_.size(); i++)
404            ret += this->engineList_[i]->getSpeedFactor();
405        ret /= (float)i;
406        return ret;
407    }
408    float SpaceShip::getMaxSpeedFront()
409    {
410        float ret=0;
411        for(unsigned int i=0; i<this->engineList_.size(); i++)
412        {
413            if(this->engineList_[i]->getMaxSpeedFront() > ret)
414                ret = this->engineList_[i]->getMaxSpeedFront();
415        }
416        return ret;
417    }
418
419    float SpaceShip::getBoostFactor()
420    {
421        float ret = 0; unsigned int i=0;
422        for(; i<this->engineList_.size(); i++)
423            ret += this->engineList_[i]->getBoostFactor();
424        ret /= (float)i;
425        return ret;
426    }
427
428    std::vector<PickupCarrier*>* SpaceShip::getCarrierChildren(void) const
429    {
430        std::vector<PickupCarrier*>* list = new std::vector<PickupCarrier*>();
431        for(unsigned int i=0; i<this->engineList_.size(); i++)
432            list->push_back(this->engineList_[i]);
433        return list;
434    }
435   
436    void SpaceShip::changedEnableMotionBlur()
437    {
438        if (!this->bEnableMotionBlur_)
439        {
440            this->boostBlur_->destroy();
441            this->boostBlur_ = 0;
442        }
443    }
444
445}
Note: See TracBrowser for help on using the repository browser.