Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/mergeFS18/src/modules/superorxobros/SOBFigure.cc @ 12146

Last change on this file since 12146 was 12031, checked in by merholzl, 6 years ago

merged Tubes into SuperOrxoBros

  • Property svn:eol-style set to native
File size: 16.5 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:
[11783]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"
[11783]43#include <OgreMath.h>
[11379]44
[12031]45#include "SOBTube.h"
[11402]46#include "SOBMushroom.h"
[11412]47#include "SOBGumba.h"
[11783]48#include "SOBGumbaBoss.h"
49#include "SOBFireball.h"
[11405]50#include "SOB.h"
[11412]51#include "SOBFlagstone.h"
[11416]52#include "SOBCastlestone.h"
[11783]53#include "Highscore.h"
[11418]54#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
[11400]55
[11379]56namespace orxonox
57{
58    RegisterClass(SOBFigure);
59
60    SOBFigure::SOBFigure(Context* context) : ControllableEntity(context)
61    {
62        RegisterObject(SOBFigure);
63
64        // initialize variables
[11416]65        gravityAcceleration_ = 350.0;
[11383]66
[11416]67        //Vars for movement of player
[11783]68        moveUpPressed_      = false;
69        moveDownPressed_    = false;
70        moveLeftPressed_    = false;
71        moveRightPressed_    = false;
72        firePressed_        = false;
73        collDisZ_           = 0;
[12031]74        tube                = NULL;
[11783]75
[12031]76        //Variables for Action in Tube
77        tcol_               = false;
78        tubing              = false; 
79        kkk                 = 0;
80       
[11416]81        //Times and turning
[11783]82        timeSinceLastFire_  = 0.0;
83        lastSpeed_z         = 0.0;
84        timeCounter_        = 0;
[11416]85
86        //Properties of player
[11383]87
[11783]88        isColliding_        = true;
89        particlespawner_    = NULL;
90
[11416]91        //Properties of players life
[11783]92        predead_            = false;
93        dead_               = false;
94        lvlEnded_           = false;
[11416]95        reachedLvlEndState_ = 0;
96
[12031]97        positiontube_=10000;
[11783]98        // Properties concerning PowerUps and items
[12031]99       
[11783]100        PowerUpCounter_     = 0;
101        maxPowerUp_         = 2;
102        FireballPower       = 2;
103        //Properties of fireing Fireballs, NOTE! fireballs are fired with the moveUP Key, not with the fire key
104        fireallowed_        = true;
105        firecooldown_       = 0;
106
[11405]107       
[11416]108        setAngularFactor(0.0); //Means player doesn't turn on collision, so he doesn't fall over while walking over the ground
109        this->enableCollisionCallback(); // Turns on that on every collision function collidesAgainst is executed
[11379]110    }
111
[11400]112
113
114    bool SOBFigure::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
115
[11418]116        //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]117        isColliding_ = true;
[11418]118        collDisZ_ = getPosition().z - contactPoint.getPositionWorldOnB().getZ();
[11416]119
[11418]120
[11416]121        //Orxocast returns object with casted type if otherObject has that class, and if not a nullptr
[12031]122        //SOBTube* test;
123       
[11783]124        SOBMushroom*    mush        = orxonox_cast<SOBMushroom*>    (otherObject);
[12031]125        tube                        = orxonox_cast<SOBTube*>        (otherObject);
[11783]126        SOBGumba*       gumba       = orxonox_cast<SOBGumba*>       (otherObject);
127        SOBGumbaBoss*   gumbaBoss   = orxonox_cast<SOBGumbaBoss*>   (otherObject);
128        SOBFlagstone*   flagstone   = orxonox_cast<SOBFlagstone*>   (otherObject);
129        SOBCastlestone* castlestone = orxonox_cast<SOBCastlestone*> (otherObject);
130        SOBFireball*    fireball    = orxonox_cast<SOBFireball*>    (otherObject);
131        SOB* SOBGame                = orxonox_cast<SOB*>            (getGametype()); 
[11412]132
[11783]133
[12031]134
[11783]135        //Check if otherObject is a powerup-mushroom
[11405]136        if (mush != nullptr && !(mush->hasCollided_)) {
137            otherObject->destroyLater();
[11783]138
139            PowerUpCounter_++;
140            if(PowerUpCounter_ > maxPowerUp_)   PowerUpCounter_ = maxPowerUp_; // you had already the max
141            else                                this->changeClothes();
142
[11416]143            SOBGame->addMushroom(); // Tell the gametype to increase points
144            mush->hasCollided_ = true; // needed because of destroyLater takes some time and player should receive points only once
[11783]145           
146           
[12031]147        }else if(tube != nullptr && !(tube->hasCollided_)){ //Check if other Object is a tube and set position wher tube is in positiontube_
148            tube->hasCollided_=true;positiontube_=getPosition().x;tcol_=true; //tcol_ used for movedown function in SOBfigure.cc
149               
[11405]150
[11783]151
[12031]152        }else if (gumba != nullptr && gumbaBoss == nullptr && !(gumba->hasCollided_)) {
153            //Check if otherObject is a Gumba (that walking enemies)
[11412]154
[11783]155            //If player jumps on its head, kill the Gumba, else, kill the player
[11412]156            if (getVelocity().z >= -20) {
[11783]157                // If player hasn't a power up, he dies. Else he shrinks and the gumba dies.
158                if(PowerUpCounter_ == 0){
159                    this->die();
160                } 
161                else{
162                    PowerUpCounter_--;
163                    this->changeClothes();
[11416]164
[11783]165                    gumba->destroyLater();
166                    gumba->hasCollided_ = true;
167                }
168
[11412]169          } else {
170            gumba->destroyLater();
171            gumba->hasCollided_ = true;
172            SOBGame->addGumba();
173
174
[11783]175            }
[11402]176        }
[11783]177        else if (gumbaBoss != nullptr && !(gumbaBoss->hasCollided_)) {
178            if (getVelocity().z >= -20) {
179                // If player hasn't a power up, he dies. Else he dies directly.
180                this->die(); 
181            }
[11400]182
[11783]183            else {
184                gumbaBoss->destroyLater();
185                gumbaBoss->hasCollided_ = true;
186                SOBGame->addGumbaBoss();
187                }
188        }
189        else if (fireball != nullptr && !(fireball->hasCollided_)){
190            if(PowerUpCounter_ == 0){
191                    this->die();
192                } 
193            PowerUpCounter_--;
194            this->changeClothes();
195            fireball->destroyLater();
196        }
197
[11416]198    //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
199    if (reachedLvlEndState_ == 0 && flagstone != nullptr && !(flagstone->hasCollided_)) {
200        flagstone->hasCollided_ = true;
201        reachedLvlEndState_ = 1;
[11783]202
[11418]203        SOBGame->setDone(true);
[11416]204        SOBGame->addPoints(flagstone->getPoints());
[11418]205       
[11400]206
[11416]207    }
208    if (castlestone != nullptr && !(castlestone->hasCollided_)) {
209        castlestone->hasCollided_ = true;
210        reachedLvlEndState_++;
[11400]211
[11416]212    }
213
[11412]214    return true;
215}
[11383]216
[11379]217
[11416]218//Self implemented sign function that returns either 1 or -1 (and never 0)
[11412]219int SOBFigure::sgn(float x) {
220    if (x < 0.0) return -1;
221    return 1;
222}
[12031]223/*bool SOBFigure::tubeAction(){
224return true;
225}*/
[11783]226//Function to spawn the Fireball
227void SOBFigure::spawnFireball() {
228        SOBCenterpoint* center_ = ((SOB*)getGametype())->center_;
229
230         SOBFireball* ball = new SOBFireball(center_->getContext());
231         Vector3 spawnpos = this->getWorldPosition();
232         spawnpos.z += 0;
233
234        if (ball != nullptr && center_ != nullptr)
235        {
236            ball->addTemplate("fireball");
237            bool direction = ((this->getWorldOrientation().getRoll().valueRadians())>-1.6&&(this->getWorldOrientation().getRoll().valueRadians()<1.6));
238            ball->setDirection(direction);
239            if(direction)
240            {
241                spawnpos.x+=10;
242            }
243            else
244            {
245                spawnpos.x-=10;
246            }
247            ball->setPosition(spawnpos);
248
249        }
250     }
251
[11416]252//For those of you who don't have an idea: the tick function is called about 50 times/sec
[11412]253void SOBFigure::tick(float dt)
254{
255    SUPER(SOBFigure, tick, dt);
[12031]256   
[11412]257
[11416]258    bool inputAllowed = true;
[12031]259   
[11416]260
261    //the particle spawner that generates the fire from the backpack when pressed
[11412]262    if (particlespawner_ == NULL) {
263        for (WorldEntity* object : this->getAttachedObjects())
264        {
[11416]265           if (object->isA(Class(ParticleSpawner)))
[11412]266            particlespawner_ = object;
[11416]267        }
[11783]268
[11405]269    }
[11783]270   
[11400]271
272
[11416]273    //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
274    if (reachedLvlEndState_ != 0) {
275        timeCounter_+= dt;
276        inputAllowed = false;
277    }
278    if (reachedLvlEndState_ == 1 && timeCounter_ >= 1.5) {
279        timeCounter_ = 0;
280        reachedLvlEndState_ = 2;
281    }
[11400]282
[11402]283
[11416]284    //if input blocked, then cancel every movement operation
285    if (!inputAllowed) {
[11783]286        moveUpPressed_      = false;
287        moveDownPressed_    = false;
288        moveLeftPressed_    = false;
289        moveRightPressed_   = false;
[11416]290    }
[11400]291
[11416]292    //set the gravityto standard 350
293    if (firePressed_ == false) {
294        gravityAcceleration_ = 350.0;
[11400]295
[11416]296    }
[11379]297
[11416]298    if (hasLocalController())
299    {
[11783]300        SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
[11416]301        Vector3 velocity = getVelocity();
302        Vector3 position = getPosition();
[11402]303
[11416]304        if (!predead_)
305            velocity.y = 0;
[11418]306        //If player falls in a hole
[12031]307        if (position.z < -180) {
[11416]308            dead_ = true;
[11418]309            SOBGame->setDone(true);
[11416]310        }
[11402]311
[11381]312
[11416]313        if (dead_) {
314            velocity.x = 0;
315            velocity.z = 0;
316            setVelocity(velocity);
[11783]317           
[11416]318            if (firePressed_)
319                SOBGame->restart();
320            return;
321        }
[11379]322
323
[11416]324        int maxvelocity_x = 100;
325        int speedAddedPerTick = 5;
326        int camMaxOffset = 25;
[11381]327
[11416]328        timeSinceLastFire_ += dt;
329        lastSpeed_z = velocity.z;
[11381]330
331
[11405]332
[11416]333        //Handle the rocket fire from the jetpack
334        if (velocity.z > 40)
335            particlespawner_->setVisible(true); 
336        else
337            particlespawner_->setVisible(false); 
[11783]338       
[11405]339
[11418]340        //If player hits space and collides against an object under him then jump
[11783]341        if (inputAllowed && firePressed_ && isColliding_ && (collDisZ_ >= 0 && collDisZ_ <+ 10)) {
342            gravityAcceleration_ = 350;
343            velocity.z = 175; 
[11392]344        }
[11381]345
[11392]346
[11420]347        //Left-right movement with acceleration and rotation
[11400]348        float rot = getOrientation().getRoll().valueDegrees();
[11383]349        if (moveRightPressed_) {
[11412]350            if (!(rot < 5.0 && -5.0 < rot))
351                setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() - sgn(rot)*dt*Radian(6));
[11400]352
[11383]353            if (std::abs(velocity.x) < maxvelocity_x) {
354                velocity.x += speedAddedPerTick;
[11400]355
[11379]356            }
[11383]357        } else if (moveLeftPressed_) {
[11412]358            if (!(abs(rot) > 175.0 ))
359                setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() + sgn(rot)*dt*Radian(6));
[11400]360
[11412]361
362
[11383]363            if (std::abs(velocity.x) < maxvelocity_x) {
364                velocity.x -= speedAddedPerTick;
[11379]365            }
[11383]366        } else {
367            velocity.x /= 1.1;
[11392]368        }
[11379]369
[11783]370        //If moveUp pressed, fire a fireball
[12031]371        if(moveUpPressed_ && inputAllowed) //if pressed up jump through tube if you are underground
[11783]372        {
[12031]373            Vector3 position1 = getPosition();
374
375             
376               
377               
378                if(position1.z>=-100 && position1.z<=-40){
379                    position1.z=40;
380                    if(460<=position1.x && position1.x<480){setPosition(position1);}  //little hack works without this but first tube must be touched     //position where second tube is
381                    if(positiontube_-10<=position1.x && position1.x<positiontube_+10){      //function for jumping through any SOBtube`s
382                    setPosition(position1);}}
383
384
385            if((PowerUpCounter_ >= FireballPower) && fireallowed_){
[11783]386            spawnFireball();
[12031]387
[11783]388            fireallowed_  = false;
[12031]389            firecooldown_ = 0;}
[11783]390        }
[12031]391       
392         if(moveDownPressed_ && inputAllowed ){ //if movedownpressed change collisiontype of tube and slip through tube
393               
394             
395                Vector3 position1 = getPosition();
396             
[11392]397
[12031]398               
399           
400               if(tube != nullptr && !(tube->movedown)){ //Check if other Object is a tube
401               
402                if(positiontube_-10<position1.x && position1.x<positiontube_+10){
403                tube->movedown=true;}
404                }
405   
406        }
407
[11783]408        //Increase the firecooldown
409        if(firecooldown_> 0.5)
410        {
411            fireallowed_ = true;
412        }
413        if(!fireallowed_)
414        {
415            firecooldown_ += dt;
416        }
417
[11416]418        //Again another EndOfLevel behavior
419        if (reachedLvlEndState_ == 1)
420            velocity.x = -2;
421        if (reachedLvlEndState_ == 2)
422            velocity.x = 30;
423        if (reachedLvlEndState_ == 3) {
424            velocity.x = 0;
425            velocity.y = 20;
[11783]426            setOrientation(Vector3::UNIT_Z, Degree(90));
[11416]427        }
428        if (reachedLvlEndState_ == 4) {
[11783]429            //Highscore
430            if (Highscore::exists())
431            {
432                int score = SOBGame->getPoints();
433                bool isHighScore = Highscore::getInstance().storeScore("Super Orxo Bros.", score, this->getPlayer());
434                SOBGame->newHighscore = isHighScore;
435            }
[11416]436            lvlEnded_ = true;
437            dead_ = true;
438        }
439
440        //velocity = acc. * time
[11383]441        velocity.z -= gravityAcceleration_*dt;
442        setVelocity(velocity);
[11379]443
444
[11416]445        //Camera operation - the camera should always follow the player in a specific region
[11383]446        Camera* cam = getCamera();
447        Vector3 campos = cam->getPosition();
[11379]448
[11383]449        if (campos.x + camMaxOffset < position.x) {
450            campos.x = position.x - camMaxOffset;
451            cam->setPosition(campos);
[11379]452        }
[11405]453        if (campos.x - camMaxOffset > position.x) {
[11383]454            campos.x = position.x + camMaxOffset;
455            cam->setPosition(campos);
456        }
[11379]457
[11383]458    }
459
[11416]460    // Reset key variables
[11783]461    moveUpPressed_      = false;
462    moveDownPressed_    = false;
463    moveLeftPressed_    = false;
464    moveRightPressed_   = false;
[12031]465   
[11416]466
[11400]467    isColliding_ = false;
[11418]468    collDisZ_ = 0;
[11379]469
[11383]470}
[11379]471
472
[11383]473
474
475
[11416]476//The following functions read the input of the player and then set the bools for the movement
[11383]477void SOBFigure::moveFrontBack(const Vector2& value)
478{
479    if (value.x > 0)
[11379]480    {
[11383]481        moveUpPressed_ = true;
482        moveDownPressed_ = false;
[11379]483    }
[11383]484    else
485    {
486        moveUpPressed_ = false;
487        moveDownPressed_ = true;
488    }
489}
[11379]490
[11383]491void SOBFigure::moveRightLeft(const Vector2& value)
492{
493    if (value.x > 0)
[11379]494    {
[11383]495        moveLeftPressed_ = false;
496        moveRightPressed_ = true;
[11379]497    }
[11383]498    else
499    {
500        moveLeftPressed_ = true;
501        moveRightPressed_ = false;
502    }
503}
[11379]504
[11383]505void SOBFigure::boost(bool boost)
506{
[11400]507    firePressed_ = boost;
[11379]508}
[11416]509
510
[11783]511
512// PRE: name is an existing name of a material. Example orxo_material for orxo_material.material in data_extern/materials
513//      !!! PowerUpCounter_ has to be modified before changing the clothes!!!
514// POST: clothes of body of player are changed to name
515void SOBFigure::changeClothes(){
516            // clothes: white (basic), red (one PowerUp), orange (Fireball enabled)
517            std::string clothes[] = {"orxo_material", "orxo_material_gross", "orxo_material_fire"};
518
519            std::set<WorldEntity*> attachedObjects = this->getAttachedObjects();
520            std::set<WorldEntity*>::iterator it;
521            for (it = attachedObjects.begin(); it != attachedObjects.end(); ++it)
522            {
523                Model* FiguresModel = orxonox_cast<Model*>(*it);
524                if (FiguresModel != nullptr)
525                {
526                    FiguresModel->setSubMaterial(clothes[PowerUpCounter_] , 4); // 4 is the body
527                }
528            }   
[11383]529}
[11783]530// PRE:
531// POST: Player jumps out of the game, game is finished and can be restarted.
532void SOBFigure::die(){
533    Vector3 vel = getVelocity();
534    vel.y = -80;
535    vel.z = 200;
536    setVelocity(vel);
537    predead_= true; 
538    SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
539    SOBGame->setDone(true);
540}
541
542}
Note: See TracBrowser for help on using the repository browser.