Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/worldentities/pawns/SpaceShip.cc @ 12141

Last change on this file since 12141 was 12029, checked in by merholzl, 6 years ago

added space race improvements

  • Property svn:eol-style set to native
File size: 17.9 KB
RevLine 
[2072]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
[3196]31#include <BulletDynamics/Dynamics/btRigidBody.h>
[2662]32
[2072]33#include "core/CoreIncludes.h"
[9667]34#include "core/config/ConfigValueIncludes.h"
[2662]35#include "core/Template.h"
[2072]36#include "core/XMLPort.h"
[8706]37#include "tools/Shader.h"
38#include "util/Math.h"
39
40#include "graphics/Camera.h"
[5735]41#include "items/Engine.h"
[2072]42
[8706]43#include "CameraManager.h"
44#include "Scene.h"
45
[2072]46namespace orxonox
47{
[9667]48    RegisterClass(SpaceShip);
[2072]49
[11071]50    SpaceShip::SpaceShip(Context* context) : Pawn(context), boostBlur_(nullptr)
[2072]51    {
52        RegisterObject(SpaceShip);
53
[8727]54        this->bInvertYAxis_ = false;
55
56        this->steering_ = Vector3::ZERO;
57
[2662]58        this->rotationThrust_ =  10;
[8727]59        this->localAngularAcceleration_.setValue(0, 0, 0);
[2072]60
[2662]61        this->bBoost_ = false;
[8727]62        this->bBoostCooldown_ = false;
63        this->initialBoostPower_ = 10.0f;
[7801]64        this->boostPower_ = 10.0f;
[8727]65        this->boostPowerRate_ = 1.0f;
66        this->boostRate_ = 5.0f;
[12029]67        this->boostCooldownDuration_ = 10.0f;
[2072]68
[8727]69        this->shakeFrequency_ = 15.0f;
70        this->shakeAmplitude_ = 5.0f;
71        this->shakeDt_ = 0.0f;
72        this->cameraOriginalPosition_ = Vector3::UNIT_SCALE;
73        this->cameraOriginalOrientation_ = Quaternion::IDENTITY;
[8706]74
[8727]75        this->lift_ = 1.0f;
76        this->stallSpeed_ = 220.0f;
[2072]77
78        this->setDestroyWhenPlayerLeft(true);
79
[2662]80        // SpaceShip is always a physical object per default
81        // Be aware of this call: The collision type legality check will not reach derived classes!
[11071]82        this->setCollisionType(WorldEntity::CollisionType::Dynamic);
[2662]83        // Get notification about collisions
84        this->enableCollisionCallback();
85
[2072]86        this->setConfigValues();
87        this->registerVariables();
[8706]88
[2072]89    }
90
91    SpaceShip::~SpaceShip()
92    {
[8706]93        if (this->isInitialized())
94        {
95            this->removeAllEngines();
[8727]96
[8706]97            if (this->boostBlur_)
[9667]98                delete this->boostBlur_;
[8706]99        }
[2072]100    }
101
102    void SpaceShip::XMLPort(Element& xmlelement, XMLPort::Mode mode)
103    {
104        SUPER(SpaceShip, XMLPort, xmlelement, mode);
105
[2662]106        XMLPortParamVariable(SpaceShip, "rotationThrust", rotationThrust_, xmlelement, mode);
[8727]107        XMLPortParam(SpaceShip, "boostPower", setInitialBoostPower, getInitialBoostPower, xmlelement, mode);
108        XMLPortParam(SpaceShip, "boostPowerRate", setBoostPowerRate, getBoostPowerRate, xmlelement, mode);
109        XMLPortParam(SpaceShip, "boostRate", setBoostRate, getBoostRate, xmlelement, mode);
110        XMLPortParam(SpaceShip, "boostCooldownDuration", setBoostCooldownDuration, getBoostCooldownDuration, xmlelement, mode);
111        XMLPortParam(SpaceShip, "shakeFrequency", setShakeFrequency, getShakeFrequency, xmlelement, mode);
112        XMLPortParam(SpaceShip, "shakeAmplitude", setShakeAmplitude, getShakeAmplitude, xmlelement, mode);
[8706]113        XMLPortParamVariable(SpaceShip, "lift", lift_, xmlelement, mode);
114        XMLPortParamVariable(SpaceShip, "stallSpeed", stallSpeed_, xmlelement, mode);
115
116        XMLPortObject(SpaceShip, Engine, "engines", addEngine, getEngine, xmlelement, mode);
[11052]117
118       
[2072]119    }
120
121    void SpaceShip::registerVariables()
122    {
[3280]123        registerVariable(this->rotationThrust_, VariableDirection::ToClient);
[8706]124        registerVariable(this->boostPower_, VariableDirection::ToClient);
125        registerVariable(this->boostPowerRate_, VariableDirection::ToClient);
126        registerVariable(this->boostRate_, VariableDirection::ToClient);
127        registerVariable(this->boostCooldownDuration_, VariableDirection::ToClient);
128        registerVariable(this->shakeFrequency_, VariableDirection::ToClient);
129        registerVariable(this->shakeAmplitude_, VariableDirection::ToClient);
130        registerVariable(this->lift_, VariableDirection::ToClient);
131        registerVariable(this->stallSpeed_, VariableDirection::ToClient);
[2072]132    }
133
134    void SpaceShip::setConfigValues()
135    {
136        SetConfigValue(bInvertYAxis_, false).description("Set this to true for joystick-like mouse behaviour (mouse up = ship down).");
[9348]137
[8706]138        SetConfigValueExternal(bEnableMotionBlur_, "GraphicsSettings", "enableMotionBlur", true)
139            .description("Enable or disable the motion blur effect when moving very fast")
140            .callback(this, &SpaceShip::changedEnableMotionBlur);
141        SetConfigValueExternal(blurStrength_, "GraphicsSettings", "blurStrength", 3.0f)
142            .description("Defines the strength of the motion blur effect");
[2072]143    }
144
[2662]145    bool SpaceShip::isCollisionTypeLegal(WorldEntity::CollisionType type) const
[2072]146    {
[11071]147        if (type != WorldEntity::CollisionType::Dynamic)
[2072]148        {
[8858]149            orxout(internal_warning) << "Cannot tell a SpaceShip not to be dynamic! Ignoring." << endl;
[2662]150            assert(false); // Only in debug mode
151            return false;
[2072]152        }
[2662]153        else
154            return true;
155    }
[2072]156
[2662]157    void SpaceShip::tick(float dt)
158    {
[2809]159        SUPER(SpaceShip, tick, dt);
[2072]160
[8727]161        // Run the engines
[11071]162        for(Engine* engine : this->engineList_)
163            engine->run(dt);
[8727]164
[12028]165        if (this->hasLocalController() || true)
[2072]166        {
[8727]167            // If not in mouse look apply the angular movement to the ship.
[2662]168            if (!this->isInMouseLook())
169            {
170                this->localAngularAcceleration_ *= this->getLocalInertia() * this->rotationThrust_;
171                this->physicalBody_->applyTorque(physicalBody_->getWorldTransform().getBasis() * this->localAngularAcceleration_);
172            }
[7860]173            this->localAngularAcceleration_.setValue(0, 0, 0);
174
[8727]175            // If not in boost cooldown, the boost power is recharged up to the initial boost power.
176            if(!this->isBoostCoolingDown() && this->boostPower_ < this->initialBoostPower_)
[7801]177            {
178                this->boostPower_ += this->boostPowerRate_*dt;
179            }
[8727]180            // If boosting
181            if(this->isBoosting())
[7801]182            {
[8727]183                // Discount the used power
184                this->boostPower_ -= this->boostRate_*dt;
185                // If the power has been used up boosting is stopped and boost cooldown is initiated.
[7801]186                if(this->boostPower_ <= 0.0f)
187                {
[8706]188                    this->boost(false);
[7801]189                    this->bBoostCooldown_ = true;
190                    this->timer_.setTimer(this->boostCooldownDuration_, false, createExecutor(createFunctor(&SpaceShip::boostCooledDown, this)));
191                }
[8706]192
[8727]193                // Shake the camera because of the boosting.
[8706]194                this->shakeCamera(dt);
[7801]195            }
[8706]196
197            // Enable Blur depending on settings
[8727]198            if(this->bEnableMotionBlur_)
[8706]199            {
[11071]200                if (this->boostBlur_ == nullptr && this->hasLocalController() && this->hasHumanController())
[8727]201                {
202                    this->boostBlur_ = new Shader(this->getScene()->getSceneManager());
203                    this->boostBlur_->setCompositorName("Radial Blur");
204                }
205                if (this->boostBlur_)
206                {
207                    float blur = this->blurStrength_ * clamp(-this->getLocalVelocity().z/(this->getMaxSpeedFront()*this->getBoostFactor()), 0.0f, 1.0f);
[8706]208
[8727]209                    // Show and hide blur effect depending on state of booster
210                    if(this->isBoosting())
211                        this->boostBlur_->setVisible(blur > 0.0f);
212                    else
213                        this->boostBlur_->setVisible(false);
[8706]214
[8727]215                    this->boostBlur_->setParameter(0, 0, "sampleStrength", blur);
216                }
[8706]217            }
[2072]218        }
[7860]219
[8727]220        this->steering_ = Vector3::ZERO;
[2072]221    }
222
[8727]223    /**
224    @brief
225        Rotate in yaw direction.
226        Due to added lift, can also lead to an additional right-left motion.
227    @param value
228        A vector whose first component specifies the magnitude of the rotation. Positive means yaw left, negative means yaw right.
229    */
[2072]230    void SpaceShip::rotateYaw(const Vector2& value)
231    {
[3039]232        this->localAngularAcceleration_.setY(this->localAngularAcceleration_.y() + value.x);
[2662]233
234        Pawn::rotateYaw(value);
[8706]235
[8727]236        // This function call adds a lift to the ship when it is rotating to make it's movement more "realistic" and enhance the feeling.
[11083]237        if (this->getLocalVelocity().z < 0 && std::abs(this->getLocalVelocity().z) < stallSpeed_)
238            this->moveRightLeft(-lift_ / 5.0f * value * sqrt(std::abs(this->getLocalVelocity().z)));
[2072]239    }
240
[8727]241    /**
242    @brief
243        Rotate in pitch direction.
244        Due to added left, can also lead to an additional up-down motion.
245    @param value
246        A vector whose first component specifies the magnitude of the rotation. Positive means pitch up, negative means pitch down.
247    */
[2072]248    void SpaceShip::rotatePitch(const Vector2& value)
249    {
[8727]250        Vector2 pitch = value;
251        if(this->bInvertYAxis_)
252            pitch.x = -pitch.x;
[2662]253
[8727]254        this->localAngularAcceleration_.setX(this->localAngularAcceleration_.x() + pitch.x*0.8f);
[8706]255
[8727]256        Pawn::rotatePitch(pitch);
257
258        // This function call adds a lift to the ship when it is pitching to make it's movement more "realistic" and enhance the feeling.
[11083]259        if (this->getLocalVelocity().z < 0 && std::abs(this->getLocalVelocity().z) < stallSpeed_)
260            this->moveUpDown(lift_ / 5.0f * pitch * sqrt(std::abs(this->getLocalVelocity().z)));
[2072]261    }
262
[8727]263    /**
264    @brief
265        Rotate in roll direction.
266    @param value
267        A vector whose first component specifies the magnitude of the rotation. Positive means roll left, negative means roll right.
268    */
[2072]269    void SpaceShip::rotateRoll(const Vector2& value)
270    {
[2662]271        this->localAngularAcceleration_.setZ(this->localAngularAcceleration_.z() + value.x);
272
273        Pawn::rotateRoll(value);
[2072]274    }
[7860]275
[8706]276    void SpaceShip::fire()
[7801]277    {
[8706]278    }
[7860]279
[8706]280    /**
281    @brief
282        Starts or stops boosting.
283    @param bBoost
284        Whether to start or stop boosting.
285    */
286    void SpaceShip::boost(bool bBoost)
287    {
[8727]288        // Can only boost if not cooling down.
289        if(bBoost && !this->isBoostCoolingDown())
[7801]290        {
[8706]291            this->bBoost_ = true;
[8727]292            this->backupCamera();
[8706]293        }
[8727]294        // Stop boosting.
[8706]295        if(!bBoost)
296        {
[7801]297            this->bBoost_ = false;
[8706]298            this->resetCamera();
[7801]299        }
300    }
[11052]301
302    void SpaceShip::gainBoostPower(float gainedBoostPower)
303    {
304        this->boostPower_ += gainedBoostPower;
305       
306        if (this->boostPower_ > this->initialBoostPower_)
307        {
308            this->boostPower_ = this->initialBoostPower_;
309        }
310
311        // If the booster is in cooldown mode and we gained boost power, the abort the cooldown.
312        if (this->isBoostCoolingDown() && this->boostPower_ > 0.0f)
313        {
314            timer_.stopTimer();
315            this->boostCooledDown();
316        }
317    }
318
[8892]319    /**
320    @brief
321        Add an Engine to the SpaceShip.
322    @param engine
323        A pointer to the Engine to be added.
324    */
[8706]325    void SpaceShip::addEngine(orxonox::Engine* engine)
326    {
[11071]327        OrxAssert(engine != nullptr, "The engine cannot be nullptr.");
[8706]328        this->engineList_.push_back(engine);
329        engine->addToSpaceShip(this);
330    }
[2662]331
[8727]332    /**
333    @brief
334        Check whether the SpaceShip has a particular Engine.
[11071]335    @param search
[8727]336        A pointer to the Engine to be checked.
337    */
[11071]338    bool SpaceShip::hasEngine(Engine* search) const
[8706]339    {
[11071]340        for(Engine* engine : this->engineList_)
[8706]341        {
[11071]342            if(engine == search)
[8706]343                return true;
344        }
345        return false;
346    }
[2662]347
[8727]348    /**
349    @brief
350        Get the i-th Engine of the SpaceShip.
351    @return
[11071]352        Returns a pointer to the i-the Engine. nullptr if there is no Engine with that index.
[8727]353    */
[8706]354    Engine* SpaceShip::getEngine(unsigned int i)
355    {
[8727]356        if(this->engineList_.size() >= i)
[11071]357            return nullptr;
[8706]358        else
359            return this->engineList_[i];
360    }
361
[8727]362    /**
363    @brief
[10216]364        Looks for an attached Engine with a certain name.
365    @param name
366        The name of the engine to be returned.
367    @return
[11071]368        Pointer to the engine with the given name, or nullptr if not found.
[10216]369    */
370    Engine* SpaceShip::getEngineByName(const std::string& name)
371    {
[11071]372        for(Engine* engine : this->engineList_)
373            if(engine->getName() == name)
374                return engine;
[10216]375
376        orxout(internal_warning) << "Couldn't find Engine with name \"" << name << "\"." << endl;
[11071]377        return nullptr;
[10216]378    }
379
380    /**
381    @brief
[8727]382        Remove and destroy all Engines of the SpaceShip.
383    */
[8706]384    void SpaceShip::removeAllEngines()
385    {
386        while(this->engineList_.size())
387            this->engineList_.back()->destroy();
388    }
[8727]389
390    /**
391    @brief
392        Remove a particular Engine from the SpaceShip.
393    @param engine
394        A pointer to the Engine to be removed.
[10216]395    @note
396        Don't forget to reset the Engine's ship pointer after it was removed (or destroy the engine).
[8727]397    */
[8706]398    void SpaceShip::removeEngine(Engine* engine)
399    {
[8727]400        for(std::vector<Engine*>::iterator it = this->engineList_.begin(); it != this->engineList_.end(); ++it)
[8706]401        {
[8727]402            if(*it == engine)
[8706]403            {
404                this->engineList_.erase(it);
405                return;
[2662]406            }
407        }
408    }
409
[8727]410    /**
411    @brief
412        Add to the speed factor for all engines of the SpaceShip.
413    @param factor
414        The factor to be added.
415    */
416    void SpaceShip::addSpeedFactor(float factor)
[2662]417    {
[11071]418        for(Engine* engine : this->engineList_)
419            engine->addSpeedMultiply(factor);
[2662]420    }
[8727]421
422    /**
423    @brief
424        Add to the speed factor for all engines of the SpaceShip.
425    @param speed
426        The speed to be added.
427    */
428    void SpaceShip::addSpeed(float speed)
[8706]429    {
[11071]430        for(Engine* engine : this->engineList_)
431            engine->addSpeedAdd(speed);
[8727]432    }
433
434    /**
435    @brief
436        Get the mean speed factor over all engines of the SpaceShip.
437    @return
438        Returns the mean speed factor over all engines of the SpaceShip.
439    */
440    float SpaceShip::getSpeedFactor() const
441    {
442        float sum = 0;
443        unsigned int i = 0;
[8706]444        for(; i<this->engineList_.size(); i++)
[8727]445            sum += this->engineList_[i]->getSpeedMultiply();
446        return sum/float(i);
[8706]447    }
[8727]448
449    /**
450    @brief
451        Get the largest maximal forward speed over all engines of the SpaceShip.
452    @return
453        Returns the largest forward speed over all engines of the SpaceShip.
454    */
455    float SpaceShip::getMaxSpeedFront() const
[8706]456    {
[8727]457        float speed=0;
[11071]458        for(Engine* engine : this->engineList_)
[8706]459        {
[11071]460            if(engine->getMaxSpeedFront() > speed)
461                speed = engine->getMaxSpeedFront();
[8706]462        }
[8727]463        return speed;
[8706]464    }
[6709]465
[8727]466    /**
467    @brief
468        Get the mean boost factor over all engines of the SpaceShip.
469    @return
470        Returns the mean boost factor over all engines of the SpaceShip.
471    */
472    float SpaceShip::getBoostFactor() const
[8706]473    {
[8727]474        float sum = 0;
475        unsigned int i=0;
[8706]476        for(; i<this->engineList_.size(); i++)
[8727]477            sum += this->engineList_[i]->getBoostFactor();
478        return sum/float(i);
[8706]479    }
480
[8727]481    /**
482    @brief
483        Is called when the enableMotionBlur config value has changed.
484    */
[8706]485    void SpaceShip::changedEnableMotionBlur()
486    {
[11071]487        if (!this->bEnableMotionBlur_ && this->boostBlur_ != nullptr)
[8706]488        {
[9667]489            delete this->boostBlur_;
[11071]490            this->boostBlur_ = nullptr;
[8706]491        }
492    }
493
[8727]494    /**
495    @brief
496        Shake the camera for a given time interval.
497    @param dt
498        The time interval in seconds.
499    */
500    void SpaceShip::shakeCamera(float dt)
501    {
502        // Make sure the ship is only shaking if it's moving forward and above the maximal forward speed.
503        if (-this->getLocalVelocity().z > this->getMaxSpeedFront())
504        {
505            this->shakeDt_ += dt;
506
[11083]507            float frequency = this->shakeFrequency_ * (square(std::abs(this->getLocalVelocity().z)));
[8727]508
509            if (this->shakeDt_ >= 1.0f/frequency)
510                this->shakeDt_ -= 1.0f/frequency;
511
512            Degree angle = Degree(sin(this->shakeDt_ * math::twoPi * frequency) * this->shakeAmplitude_);
513
514            Camera* camera = this->getCamera();
515            //Shaking Camera effect
[11071]516            if (camera != nullptr)
[8727]517                camera->setOrientation(Vector3::UNIT_X, angle);
518
519        }
520        // If the camera is no shaking, reset it.
521        else
522            this->resetCamera();
523    }
524
525    /**
526    @brief
527        Save the original position and orientation of the camera.
528    */
529    void SpaceShip::backupCamera()
530    {
531        Camera* camera = CameraManager::getInstance().getActiveCamera();
[11071]532        if(camera != nullptr)
[8727]533        {
534            this->cameraOriginalPosition_ = camera->getPosition();
535            this->cameraOriginalOrientation_ = camera->getOrientation();
536        }
537    }
538
539    /**
540    @brief
541        Reset the camera to its original position.
542    */
543    void SpaceShip::resetCamera()
544    {
[9348]545        if(this->hasLocalController() && this->hasHumanController())
546        {
[8891]547            Camera *camera = this->getCamera();
[11071]548            if (camera == nullptr)
[8891]549            {
550                orxout(internal_warning) << "Failed to reset camera!" << endl;
551                return;
552            }
553            this->shakeDt_ = 0.0f;
554            camera->setPosition(this->cameraOriginalPosition_);
555            camera->setOrientation(this->cameraOriginalOrientation_);
[9348]556        }
[8727]557    }
558
[2072]559}
Note: See TracBrowser for help on using the repository browser.