Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8804 was 8727, checked in by dafrick, 14 years ago

Cleaning up in SpaceShip and Engine. Fixed several bugs.
Kicked localLinearAcceleration, primaryThrust and auxiliaryThrust out of the SpaceShip, since it wasn't used anymore.
Moved the trail lights back a bit.
Added some documentation to SpaceShip and Engine.
SpeedPickup is working again, will need some further tuning.

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