Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/SOBv2_HS17/src/modules/superorxobros/SOBFigure.cc @ 11599

Last change on this file since 11599 was 11599, checked in by varxth, 7 years ago

fireball with particle spawner

File size: 13.9 KB
RevLine 
[11379]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:
[11416]23 *      Julien Kindle
[11379]24 *   Co-authors:
[11599]25 *      Noah Zarro
26 *      Theo von Arx
[11416]27 *     
[11379]28 *
29 */
30
31/**
32    @file SOBFigure.cc
33    @brief This class represents your figure when you play the minigame. Here the movement of the figure, activating items, ... are handled.
34*/
35
36#include "SOBFigure.h"
37
38#include "core/CoreIncludes.h"
39#include "core/XMLPort.h"
40#include "graphics/Model.h"
[11383]41#include "graphics/Camera.h"
[11400]42#include "graphics/ParticleSpawner.h"
[11577]43#include <OgreMath.h>
[11379]44
[11402]45#include "SOBMushroom.h"
[11412]46#include "SOBGumba.h"
[11575]47#include "SOBFireball.h"
[11405]48#include "SOB.h"
[11412]49#include "SOBFlagstone.h"
[11416]50#include "SOBCastlestone.h"
[11573]51#include "SOBFireball.h"
[11418]52#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
[11400]53
[11379]54namespace orxonox
55{
56    RegisterClass(SOBFigure);
57
58    SOBFigure::SOBFigure(Context* context) : ControllableEntity(context)
59    {
60        RegisterObject(SOBFigure);
61
62        // initialize variables
[11416]63        gravityAcceleration_ = 350.0;
[11383]64
[11416]65        //Vars for movement of player
[11578]66        moveUpPressed_      = false;
67        moveDownPressed_    = false;
68        moveLeftPressed_    = false;
69        moveDownPressed_    = false;
70        firePressed_        = false;
71        collDisZ_           = 0;
[11517]72
[11416]73        //Times and turning
[11578]74        timeSinceLastFire_  = 0.0;
75        lastSpeed_z         = 0.0;
76        pitch_              = 0.0;
77        timeCounter_        = 0;
[11416]78
79        //Properties of player
[11383]80
[11578]81        isColliding_        = true;
82        particlespawner_    = NULL;
83
[11416]84        //Properties of players life
[11578]85        predead_            = false;
86        dead_               = false;
87        lvlEnded_           = false;
[11416]88        reachedLvlEndState_ = 0;
89
[11578]90        // Properties concerning PowerUps and items
91        PowerUpCounter_     = 0;
92        maxPowerUp_         = 2;
93        FireballPower       = 2;
[11573]94        //Properties of fireing Fireballs, NOTE! fireballs are fired with the moveUP Key, not with the fire key
[11578]95        fireallowed_        = true;
96        firecooldown_       = 0;
[11573]97
[11405]98       
[11416]99        setAngularFactor(0.0); //Means player doesn't turn on collision, so he doesn't fall over while walking over the ground
100        this->enableCollisionCallback(); // Turns on that on every collision function collidesAgainst is executed
[11379]101    }
102
[11400]103
104
105    bool SOBFigure::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
106
[11418]107        //Inform tick fct that player is colliding and tell him how far away the collision point is from player middle point in z dir
[11400]108        isColliding_ = true;
[11418]109        collDisZ_ = getPosition().z - contactPoint.getPositionWorldOnB().getZ();
[11416]110
[11418]111
[11416]112        //Orxocast returns object with casted type if otherObject has that class, and if not a nullptr
[11575]113        SOBMushroom*    mush        = orxonox_cast<SOBMushroom*>    (otherObject);
114        SOBGumba*       gumba       = orxonox_cast<SOBGumba*>       (otherObject);
115        SOBFlagstone*   flagstone   = orxonox_cast<SOBFlagstone*>   (otherObject);
116        SOBCastlestone* castlestone = orxonox_cast<SOBCastlestone*> (otherObject);
117        SOBFireball* fireball       = orxonox_cast<SOBFireball*>    (otherObject);
[11578]118        SOB* SOBGame                = orxonox_cast<SOB*>            (getGametype()); 
[11412]119
[11578]120
121        //Check if otherObject is a powerup-mushroom
[11405]122        if (mush != nullptr && !(mush->hasCollided_)) {
123            otherObject->destroyLater();
[11578]124
125            PowerUpCounter_++;
126            if(PowerUpCounter_ > maxPowerUp_)   PowerUpCounter_ = maxPowerUp_; // you had already the max
127            else                                this->changeClothes();
128
[11416]129            SOBGame->addMushroom(); // Tell the gametype to increase points
130            mush->hasCollided_ = true; // needed because of destroyLater takes some time and player should receive points only once
[11538]131           
[11578]132           
[11491]133        }
[11538]134       
[11575]135
[11416]136        //Check if otherObject is a Gumba (that walking enemies)
[11412]137
[11491]138         else if (gumba != nullptr && !(gumba->hasCollided_)) {
139
[11556]140            //If player jumps on its head, kill the Gumba, else, kill the player
[11412]141            if (getVelocity().z >= -20) {
[11491]142                // If player hasn't a power up, he dies. Else he shrinks and the gumba dies.
[11578]143                if(PowerUpCounter_ == 0){
[11575]144                    this->die();
[11578]145                } 
146                else{
147                    PowerUpCounter_--;
148                    this->changeClothes();
149
[11491]150                    gumba->destroyLater();
151                    gumba->hasCollided_ = true;
152                }
153
[11412]154          } else {
155            gumba->destroyLater();
156            gumba->hasCollided_ = true;
157            SOBGame->addGumba();
158
159
[11402]160        }
[11400]161    }
162
[11575]163        else if (fireball != nullptr && !(fireball->hasCollided_)){
[11599]164            if(PowerUpCounter_ == 0){
165                    this->die();
166                } 
[11597]167            PowerUpCounter_--;
168            this->changeClothes();
[11575]169        }
170
[11416]171    //Purpose is that if player hits the flag, he should walk into the castle at the end of the level. For that we use SOBCastlestone
172    if (reachedLvlEndState_ == 0 && flagstone != nullptr && !(flagstone->hasCollided_)) {
173        flagstone->hasCollided_ = true;
174        reachedLvlEndState_ = 1;
[11578]175
[11418]176        SOBGame->setDone(true);
[11416]177        SOBGame->addPoints(flagstone->getPoints());
[11418]178       
[11400]179
[11416]180    }
181    if (castlestone != nullptr && !(castlestone->hasCollided_)) {
182        castlestone->hasCollided_ = true;
183        reachedLvlEndState_++;
[11400]184
[11416]185    }
186
[11412]187    return true;
188}
[11383]189
[11379]190
[11416]191//Self implemented sign function that returns either 1 or -1 (and never 0)
[11412]192int SOBFigure::sgn(float x) {
193    if (x < 0.0) return -1;
194    return 1;
195}
196
[11573]197//Function to spawn the Fireball
198void SOBFigure::spawnFireball() {
199        SOBCenterpoint* center_ = ((SOB*)getGametype())->center_;
200
201         SOBFireball* ball = new SOBFireball(center_->getContext());
202         Vector3 spawnpos = this->getWorldPosition();
203         spawnpos.z += 0;
204
205        if (ball != nullptr && center_ != nullptr)
206        {
207            ball->addTemplate("fireball");
[11577]208            bool direction = ((this->getWorldOrientation().getRoll().valueRadians())>-1.6&&(this->getWorldOrientation().getRoll().valueRadians()<1.6));
209            ball->setDirection(direction);
210            orxout() << "Rotation: " << this->getWorldOrientation().getRoll() << " direction: "<< direction <<endl;
[11592]211            if(direction)
212            {
213                spawnpos.x+=10;
214            }
215            else
216            {
217                spawnpos.x-=10;
218            }
219            ball->setPosition(spawnpos);
[11577]220
[11573]221        }
222     }
223
[11416]224//For those of you who don't have an idea: the tick function is called about 50 times/sec
[11412]225void SOBFigure::tick(float dt)
226{
227    SUPER(SOBFigure, tick, dt);
228
[11416]229
230    bool inputAllowed = true;
231
232    //the particle spawner that generates the fire from the backpack when pressed
[11412]233    if (particlespawner_ == NULL) {
234        for (WorldEntity* object : this->getAttachedObjects())
235        {
[11416]236           if (object->isA(Class(ParticleSpawner)))
[11412]237            particlespawner_ = object;
[11416]238        }
[11599]239
[11405]240    }
[11599]241   
[11400]242
243
[11416]244    //Behavior on level end - this is like described above for the movement from the player when hit the flag. He moves then into the castle
245    if (reachedLvlEndState_ != 0) {
246        timeCounter_+= dt;
247        inputAllowed = false;
248    }
249    if (reachedLvlEndState_ == 1 && timeCounter_ >= 1.5) {
250        timeCounter_ = 0;
251        reachedLvlEndState_ = 2;
252    }
[11400]253
[11402]254
[11416]255    //if input blocked, then cancel every movement operation
256    if (!inputAllowed) {
[11578]257        moveUpPressed_      = false;
258        moveDownPressed_    = false;
259        moveLeftPressed_    = false;
260        moveRightPressed_   = false;
[11416]261    }
[11400]262
[11416]263    //set the gravityto standard 350
264    if (firePressed_ == false) {
265        gravityAcceleration_ = 350.0;
[11400]266
[11416]267    }
[11379]268
[11416]269    if (hasLocalController())
270    {
[11578]271        SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
[11416]272        Vector3 velocity = getVelocity();
273        Vector3 position = getPosition();
[11402]274
[11416]275        if (!predead_)
276            velocity.y = 0;
[11418]277        //If player falls in a hole
[11416]278        if (position.z < -100) {
279            dead_ = true;
[11418]280            SOBGame->setDone(true);
[11416]281        }
[11402]282
[11381]283
[11416]284        if (dead_) {
285            velocity.x = 0;
286            velocity.z = 0;
287            setVelocity(velocity);
[11578]288           
[11416]289            if (firePressed_)
290                SOBGame->restart();
291            return;
292        }
[11379]293
294
[11416]295        int maxvelocity_x = 100;
296        int speedAddedPerTick = 5;
297        int camMaxOffset = 25;
[11381]298
[11416]299        timeSinceLastFire_ += dt;
300        lastSpeed_z = velocity.z;
[11381]301
302
[11405]303
[11416]304        //Handle the rocket fire from the jetpack
305        if (velocity.z > 40)
306            particlespawner_->setVisible(true); 
307        else
308            particlespawner_->setVisible(false); 
[11599]309       
[11405]310
[11418]311        //If player hits space and collides against an object under him then jump
[11517]312        if (inputAllowed && firePressed_ && isColliding_ && (collDisZ_ >= 0 && collDisZ_ <+ 10)) {
[11599]313            gravityAcceleration_ = 350;
314            velocity.z = 175; 
[11392]315        }
[11381]316
[11392]317
[11420]318        //Left-right movement with acceleration and rotation
[11400]319        float rot = getOrientation().getRoll().valueDegrees();
[11383]320        if (moveRightPressed_) {
[11412]321            if (!(rot < 5.0 && -5.0 < rot))
322                setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() - sgn(rot)*dt*Radian(6));
[11400]323
[11383]324            if (std::abs(velocity.x) < maxvelocity_x) {
325                velocity.x += speedAddedPerTick;
[11400]326
[11379]327            }
[11383]328        } else if (moveLeftPressed_) {
[11412]329            if (!(abs(rot) > 175.0 ))
330                setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() + sgn(rot)*dt*Radian(6));
[11400]331
[11412]332
333
[11383]334            if (std::abs(velocity.x) < maxvelocity_x) {
335                velocity.x -= speedAddedPerTick;
[11379]336            }
[11383]337        } else {
338            velocity.x /= 1.1;
[11392]339        }
[11379]340
[11573]341        //If moveUp pressed, fire a fireball
[11578]342        if(moveUpPressed_ && (PowerUpCounter_ >= FireballPower) && fireallowed_)
[11573]343        {
344            spawnFireball();
[11578]345            fireallowed_  = false;
346            firecooldown_ = 0;
[11573]347        }
[11392]348
[11573]349        //Increase the firecooldown
[11578]350        if(firecooldown_> 0.5)
[11573]351        {
[11578]352            fireallowed_ = true;
[11573]353        }
354        if(!fireallowed_)
355        {
[11578]356            firecooldown_ += dt;
[11573]357        }
358
[11416]359        //Again another EndOfLevel behavior
360        if (reachedLvlEndState_ == 1)
361            velocity.x = -2;
362        if (reachedLvlEndState_ == 2)
363            velocity.x = 30;
364        if (reachedLvlEndState_ == 3) {
365            velocity.x = 0;
366            velocity.y = 20;
367        }
368        if (reachedLvlEndState_ == 4) {
369            lvlEnded_ = true;
370            dead_ = true;
371        }
372
373        //velocity = acc. * time
[11383]374        velocity.z -= gravityAcceleration_*dt;
375        setVelocity(velocity);
[11379]376
377
[11416]378        //Camera operation - the camera should always follow the player in a specific region
[11383]379        Camera* cam = getCamera();
380        Vector3 campos = cam->getPosition();
[11379]381
[11383]382        if (campos.x + camMaxOffset < position.x) {
383            campos.x = position.x - camMaxOffset;
384            cam->setPosition(campos);
[11379]385        }
[11405]386        if (campos.x - camMaxOffset > position.x) {
[11383]387            campos.x = position.x + camMaxOffset;
388            cam->setPosition(campos);
389        }
[11379]390
[11383]391    }
392
[11416]393    // Reset key variables
[11578]394    moveUpPressed_      = false;
395    moveDownPressed_    = false;
396    moveLeftPressed_    = false;
397    moveRightPressed_   = false;
[11416]398
[11400]399    isColliding_ = false;
[11418]400    collDisZ_ = 0;
[11379]401
[11383]402}
[11379]403
404
[11383]405
406
407
[11416]408//The following functions read the input of the player and then set the bools for the movement
[11383]409void SOBFigure::moveFrontBack(const Vector2& value)
410{
411    if (value.x > 0)
[11379]412    {
[11383]413        moveUpPressed_ = true;
414        moveDownPressed_ = false;
[11379]415    }
[11383]416    else
417    {
418        moveUpPressed_ = false;
419        moveDownPressed_ = true;
420    }
421}
[11379]422
[11383]423void SOBFigure::moveRightLeft(const Vector2& value)
424{
425    if (value.x > 0)
[11379]426    {
[11383]427        moveLeftPressed_ = false;
428        moveRightPressed_ = true;
[11379]429    }
[11383]430    else
431    {
432        moveLeftPressed_ = true;
433        moveRightPressed_ = false;
434    }
435}
[11379]436
[11383]437void SOBFigure::boost(bool boost)
438{
[11400]439    firePressed_ = boost;
[11379]440}
[11416]441
442
[11538]443
444// PRE: name is an existing name of a material. Example orxo_material for orxo_material.material in data_extern/materials
[11578]445//      !!! PowerUpCounter_ has to be modified before changing the clothes!!!
[11538]446// POST: clothes of body of player are changed to name
[11578]447void SOBFigure::changeClothes(){
448            // clothes: white (basic), red (one PowerUp), orange (Fireball enabled)
449            std::string clothes[] = {"orxo_material", "orxo_material_gross", "orxo_material_fire"};
450
[11538]451            std::set<WorldEntity*> attachedObjects = this->getAttachedObjects();
452            std::set<WorldEntity*>::iterator it;
453            for (it = attachedObjects.begin(); it != attachedObjects.end(); ++it)
454            {
455                Model* FiguresModel = orxonox_cast<Model*>(*it);
456                if (FiguresModel != nullptr)
457                {
[11578]458                    FiguresModel->setSubMaterial(clothes[PowerUpCounter_] , 4); // 4 is the body
[11538]459                }
460            }   
[11383]461}
[11578]462// PRE:
463// POST: Player jumps out of the game, game is finished and can be restarted.
[11575]464void SOBFigure::die(){
465    Vector3 vel = getVelocity();
466    vel.y = -80;
467    vel.z = 200;
468    setVelocity(vel);
[11578]469    predead_= true; 
[11575]470    SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
471    SOBGame->setDone(true);
472}
473
[11538]474}
Note: See TracBrowser for help on using the repository browser.