Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/weapons/projectiles/GravityBombField.cc @ 11006

Last change on this file since 11006 was 10622, checked in by landauf, 9 years ago

merged branch presentationFS15merge back to trunk

  • Property svn:eol-style set to native
File size: 7.6 KB
Line 
1/*
2 * GravityBombField.cc
3 *
4 *  Created on: Apr 2, 2015
5 *      Author: Manuel Eggimann
6 */
7
8#include "GravityBombField.h"
9#include "graphics/Model.h"
10
11namespace orxonox{
12    RegisterClass(GravityBombField);
13
14    //Change these constants to alter the behaviour of the field.
15   
16    const float GravityBombField::FORCE_FIELD_LIFETIME = 15;
17    const float GravityBombField::FORCE_SPHERE_START_RADIUS = 250;
18    const float GravityBombField::FORCE_SPHERE_START_STRENGTH = -700;
19    const float GravityBombField::PEAK_EXPLOSION_FORCE = 5e4;
20    const float GravityBombField::FORCE_FIELD_EXPLOSION_DAMMAGE = 100;
21    const float GravityBombField::EXPLOSION_DURATION = 1;
22    const float GravityBombField::EXPLOSION_RADIUS = 600;
23    const float GravityBombField::PEAK_ANGULAR_VELOCITY = 20;
24    const float GravityBombField::CENTRE_MODEL_END_SIZE = 1.5;
25
26    GravityBombField::GravityBombField(Context* context) : ForceField(context),RadarViewable(this, static_cast<WorldEntity*>(this))
27    {
28        RegisterObject(GravityBombField);
29        //Initialize variable with their initial values.
30        lifetime_=FORCE_FIELD_LIFETIME;
31        forceStrength_ = FORCE_SPHERE_START_STRENGTH;
32        forceSphereRadius_ = FORCE_SPHERE_START_RADIUS;
33        modelScaling_ = 1;
34        fieldExploded_ = false;
35
36        setVelocity(FORCE_SPHERE_START_STRENGTH);
37        setDiameter(2*FORCE_SPHERE_START_RADIUS);
38        setMode(modeSphere_s);
39        setCollisionResponse(false);
40
41        //Make the Field visible on Radar and minimap.
42        this->setRadarObjectColour(ColourValue(1.0, 0.0, 0.2,1)); // Red
43        this->setRadarObjectShape(RadarViewable::Dot);
44        this->setRadarObjectScale(1.0f);
45       
46
47        //Attach Model
48        Model* model = new Model(this->getContext());
49        model->setMeshSource("GravityBomb.mesh"); //Demo Model from SimpleRocket
50        model->scale(2.5f);
51        bombModel_ = new MovableEntity(context);
52        bombModel_->attach(model);
53        this->attach(bombModel_);
54
55        //Add a Backlight to the centre.
56        centreLight_ = new Backlight(context);
57        centreLight_->setColour(ColourValue(0.2,0.9,0.2,1));
58        centreLight_->setScale(0.3);
59        centreLight_->setTrailMaterial("Trail/backlighttrail");
60        centreLight_->setMaterial("Examples/Flare");
61        centreLight_->setLifetime(20);
62        bombModel_->attach(centreLight_);
63
64        //Let the Bomb Modell in the centre rotate in a random direction.
65        Vector3 randomRotation;
66        randomRotation.x = rnd();
67        randomRotation.y = rnd();
68        randomRotation.y = rnd();
69        randomRotation.normalise();
70        bombModel_->setAngularAcceleration(randomRotation*(PEAK_ANGULAR_VELOCITY/FORCE_FIELD_LIFETIME));
71
72        //Add Collision Shape
73        SphereCollisionShape* collisionShape = new SphereCollisionShape(context);
74        collisionShape->setRadius(10.0);
75        this->attachCollisionShape(collisionShape);
76
77        //Add particle effect to visualize the force field.
78        this->particleSphere_ = new ParticleEmitter(this->getContext());
79        this->attach(this->particleSphere_);
80        particleSphere_->setSource("Orxonox/GravityBombField");
81
82        //Add a sound effect to the field.
83        WorldSound* fieldSound = new WorldSound(context);
84        fieldSound->setSource("sounds/GravityField.ogg");
85        fieldSound->setLooping(true);
86        fieldSound->setVolume(1.0);
87        this->attach(fieldSound);
88        fieldSound->play();
89    }
90
91    GravityBombField::~GravityBombField(){}
92
93   
94    void GravityBombField::tick(float dt)
95    {
96        SUPER(GravityBombField,tick,dt);
97        lifetime_-=dt;
98
99        if(lifetime_ > EXPLOSION_DURATION)//If field is still alive, make it smaller and stronger.
100        {
101            modelScaling_ += ((CENTRE_MODEL_END_SIZE-1) / FORCE_FIELD_LIFETIME)*dt;
102            forceStrength_ *= (1+dt/10);
103            forceSphereRadius_ = FORCE_SPHERE_START_RADIUS*(1-((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME)*((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME)*((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME));
104        }
105        else if(lifetime_ > 0)
106        {
107            if (!fieldExploded_) // Start the field explosion if it has not been started yet.
108            {
109                forceStrength_ = pow((EXPLOSION_DURATION + lifetime_),4)/EXPLOSION_DURATION * PEAK_EXPLOSION_FORCE;
110                fieldExploded_ = true;
111
112                //Add particle effect to visualize explosion
113                explosionCross_ = new ParticleEmitter(this->getContext());
114                explosionCross_->setSource("Orxonox/FieldExplosion");
115                explosionCross_->setOrientation(rnd(), rnd(), rnd(), rnd());
116                explosionCross_->setScale(0.7);
117                this->attach(explosionCross_);
118
119                //Add explosion sound effect.
120                explosionSound_ = new WorldSound(getContext());
121                explosionSound_->setSource("sounds/GravityFieldExplosion.ogg");
122                explosionSound_->setVolume(1.0);
123                explosionSound_->play();
124            }
125
126            //Check if any pawn is inside the shockwave and hit it with dammage proportional to the distance between explosion centre and pawn. Make sure, the same pawn is damaged only once.
127            for (ObjectList<Pawn>::iterator it = ObjectList<Pawn>::begin(); it != ObjectList<Pawn>::end(); ++it)
128            {
129                Vector3 distanceVector = it->getWorldPosition()-this->getWorldPosition();
130                 //orxout(debug_output) << "Found Pawn:" << it->getWorldPosition() << endl;
131                if(distanceVector.length()< forceSphereRadius_)
132                {
133                    //orxout(debug_output) << "Force sphere radius is: " << forceSphereRadius_ << " Distance to Pawn is: " << distanceVector.length();
134                    if (std::find(victimsAlreadyDamaged_.begin(),victimsAlreadyDamaged_.end(),*it) == victimsAlreadyDamaged_.end())
135                    {
136                        //orxout(debug_output) << "Found Pawn to damage: " << it->getWorldPosition() << endl;
137                        float damage = FORCE_FIELD_EXPLOSION_DAMMAGE*(1-distanceVector.length()/EXPLOSION_RADIUS);
138                        //orxout(debug_output) << "Damage: " << damage << endl;
139                        it->hit(shooter_, it->getWorldPosition(), NULL, damage, 0,0);
140                        victimsAlreadyDamaged_.push_back(*it);
141                    }
142                }
143            }
144
145            forceSphereRadius_ = EXPLOSION_RADIUS*(1-lifetime_/EXPLOSION_DURATION);
146            explosionCross_->setScale(forceSphereRadius_/FORCE_SPHERE_START_RADIUS);
147        }
148        else if (lifetime_ > -6) //The field has to exist for 6 more seconds for the particles of the particle effect to vanish smoothly.
149        {
150            //Make the bomb model invisible, let the strength of the field be zero and remove all particle emitters so the particle effect will slowly vanish.
151            bombModel_->setVisible(false);
152            this->setRadarVisibility(false);
153            forceStrength_ = 0;
154            forceSphereRadius_ = 0.00001;
155            particleSphere_->getParticleInterface()->removeAllEmitters();
156            explosionCross_->getParticleInterface()->removeAllEmitters();
157        }
158       
159        setDiameter(forceSphereRadius_*2);
160        setVelocity(forceStrength_);
161        if(lifetime_>0) particleSphere_->setScale(forceSphereRadius_/FORCE_SPHERE_START_RADIUS);
162        bombModel_->setScale(modelScaling_);
163
164        if (lifetime_ <= -4)
165        {
166            orxout(debug_output) << "Timeout. Destroying field." << endl;
167            this->destroy();
168        }
169    }
170
171    void GravityBombField::destroy()
172    {
173        ForceField::destroy();
174    }
175
176}
Note: See TracBrowser for help on using the repository browser.