Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 12051 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
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 *      Julien Kindle
24 *   Co-authors:
25 *      Noah Zarro
26 *      Theo von Arx
27 *     
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"
41#include "graphics/Camera.h"
42#include "graphics/ParticleSpawner.h"
43#include <OgreMath.h>
44
45#include "SOBTube.h"
46#include "SOBMushroom.h"
47#include "SOBGumba.h"
48#include "SOBGumbaBoss.h"
49#include "SOBFireball.h"
50#include "SOB.h"
51#include "SOBFlagstone.h"
52#include "SOBCastlestone.h"
53#include "Highscore.h"
54#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
55
56namespace orxonox
57{
58    RegisterClass(SOBFigure);
59
60    SOBFigure::SOBFigure(Context* context) : ControllableEntity(context)
61    {
62        RegisterObject(SOBFigure);
63
64        // initialize variables
65        gravityAcceleration_ = 350.0;
66
67        //Vars for movement of player
68        moveUpPressed_      = false;
69        moveDownPressed_    = false;
70        moveLeftPressed_    = false;
71        moveRightPressed_    = false;
72        firePressed_        = false;
73        collDisZ_           = 0;
74        tube                = NULL;
75
76        //Variables for Action in Tube
77        tcol_               = false;
78        tubing              = false; 
79        kkk                 = 0;
80       
81        //Times and turning
82        timeSinceLastFire_  = 0.0;
83        lastSpeed_z         = 0.0;
84        timeCounter_        = 0;
85
86        //Properties of player
87
88        isColliding_        = true;
89        particlespawner_    = NULL;
90
91        //Properties of players life
92        predead_            = false;
93        dead_               = false;
94        lvlEnded_           = false;
95        reachedLvlEndState_ = 0;
96
97        positiontube_=10000;
98        // Properties concerning PowerUps and items
99       
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
107       
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
110    }
111
112
113
114    bool SOBFigure::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
115
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
117        isColliding_ = true;
118        collDisZ_ = getPosition().z - contactPoint.getPositionWorldOnB().getZ();
119
120
121        //Orxocast returns object with casted type if otherObject has that class, and if not a nullptr
122        //SOBTube* test;
123       
124        SOBMushroom*    mush        = orxonox_cast<SOBMushroom*>    (otherObject);
125        tube                        = orxonox_cast<SOBTube*>        (otherObject);
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()); 
132
133
134
135        //Check if otherObject is a powerup-mushroom
136        if (mush != nullptr && !(mush->hasCollided_)) {
137            otherObject->destroyLater();
138
139            PowerUpCounter_++;
140            if(PowerUpCounter_ > maxPowerUp_)   PowerUpCounter_ = maxPowerUp_; // you had already the max
141            else                                this->changeClothes();
142
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
145           
146           
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               
150
151
152        }else if (gumba != nullptr && gumbaBoss == nullptr && !(gumba->hasCollided_)) {
153            //Check if otherObject is a Gumba (that walking enemies)
154
155            //If player jumps on its head, kill the Gumba, else, kill the player
156            if (getVelocity().z >= -20) {
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();
164
165                    gumba->destroyLater();
166                    gumba->hasCollided_ = true;
167                }
168
169          } else {
170            gumba->destroyLater();
171            gumba->hasCollided_ = true;
172            SOBGame->addGumba();
173
174
175            }
176        }
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            }
182
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
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;
202
203        SOBGame->setDone(true);
204        SOBGame->addPoints(flagstone->getPoints());
205       
206
207    }
208    if (castlestone != nullptr && !(castlestone->hasCollided_)) {
209        castlestone->hasCollided_ = true;
210        reachedLvlEndState_++;
211
212    }
213
214    return true;
215}
216
217
218//Self implemented sign function that returns either 1 or -1 (and never 0)
219int SOBFigure::sgn(float x) {
220    if (x < 0.0) return -1;
221    return 1;
222}
223/*bool SOBFigure::tubeAction(){
224return true;
225}*/
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
252//For those of you who don't have an idea: the tick function is called about 50 times/sec
253void SOBFigure::tick(float dt)
254{
255    SUPER(SOBFigure, tick, dt);
256   
257
258    bool inputAllowed = true;
259   
260
261    //the particle spawner that generates the fire from the backpack when pressed
262    if (particlespawner_ == NULL) {
263        for (WorldEntity* object : this->getAttachedObjects())
264        {
265           if (object->isA(Class(ParticleSpawner)))
266            particlespawner_ = object;
267        }
268
269    }
270   
271
272
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    }
282
283
284    //if input blocked, then cancel every movement operation
285    if (!inputAllowed) {
286        moveUpPressed_      = false;
287        moveDownPressed_    = false;
288        moveLeftPressed_    = false;
289        moveRightPressed_   = false;
290    }
291
292    //set the gravityto standard 350
293    if (firePressed_ == false) {
294        gravityAcceleration_ = 350.0;
295
296    }
297
298    if (hasLocalController())
299    {
300        SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
301        Vector3 velocity = getVelocity();
302        Vector3 position = getPosition();
303
304        if (!predead_)
305            velocity.y = 0;
306        //If player falls in a hole
307        if (position.z < -180) {
308            dead_ = true;
309            SOBGame->setDone(true);
310        }
311
312
313        if (dead_) {
314            velocity.x = 0;
315            velocity.z = 0;
316            setVelocity(velocity);
317           
318            if (firePressed_)
319                SOBGame->restart();
320            return;
321        }
322
323
324        int maxvelocity_x = 100;
325        int speedAddedPerTick = 5;
326        int camMaxOffset = 25;
327
328        timeSinceLastFire_ += dt;
329        lastSpeed_z = velocity.z;
330
331
332
333        //Handle the rocket fire from the jetpack
334        if (velocity.z > 40)
335            particlespawner_->setVisible(true); 
336        else
337            particlespawner_->setVisible(false); 
338       
339
340        //If player hits space and collides against an object under him then jump
341        if (inputAllowed && firePressed_ && isColliding_ && (collDisZ_ >= 0 && collDisZ_ <+ 10)) {
342            gravityAcceleration_ = 350;
343            velocity.z = 175; 
344        }
345
346
347        //Left-right movement with acceleration and rotation
348        float rot = getOrientation().getRoll().valueDegrees();
349        if (moveRightPressed_) {
350            if (!(rot < 5.0 && -5.0 < rot))
351                setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() - sgn(rot)*dt*Radian(6));
352
353            if (std::abs(velocity.x) < maxvelocity_x) {
354                velocity.x += speedAddedPerTick;
355
356            }
357        } else if (moveLeftPressed_) {
358            if (!(abs(rot) > 175.0 ))
359                setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() + sgn(rot)*dt*Radian(6));
360
361
362
363            if (std::abs(velocity.x) < maxvelocity_x) {
364                velocity.x -= speedAddedPerTick;
365            }
366        } else {
367            velocity.x /= 1.1;
368        }
369
370        //If moveUp pressed, fire a fireball
371        if(moveUpPressed_ && inputAllowed) //if pressed up jump through tube if you are underground
372        {
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_){
386            spawnFireball();
387
388            fireallowed_  = false;
389            firecooldown_ = 0;}
390        }
391       
392         if(moveDownPressed_ && inputAllowed ){ //if movedownpressed change collisiontype of tube and slip through tube
393               
394             
395                Vector3 position1 = getPosition();
396             
397
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
408        //Increase the firecooldown
409        if(firecooldown_> 0.5)
410        {
411            fireallowed_ = true;
412        }
413        if(!fireallowed_)
414        {
415            firecooldown_ += dt;
416        }
417
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;
426            setOrientation(Vector3::UNIT_Z, Degree(90));
427        }
428        if (reachedLvlEndState_ == 4) {
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            }
436            lvlEnded_ = true;
437            dead_ = true;
438        }
439
440        //velocity = acc. * time
441        velocity.z -= gravityAcceleration_*dt;
442        setVelocity(velocity);
443
444
445        //Camera operation - the camera should always follow the player in a specific region
446        Camera* cam = getCamera();
447        Vector3 campos = cam->getPosition();
448
449        if (campos.x + camMaxOffset < position.x) {
450            campos.x = position.x - camMaxOffset;
451            cam->setPosition(campos);
452        }
453        if (campos.x - camMaxOffset > position.x) {
454            campos.x = position.x + camMaxOffset;
455            cam->setPosition(campos);
456        }
457
458    }
459
460    // Reset key variables
461    moveUpPressed_      = false;
462    moveDownPressed_    = false;
463    moveLeftPressed_    = false;
464    moveRightPressed_   = false;
465   
466
467    isColliding_ = false;
468    collDisZ_ = 0;
469
470}
471
472
473
474
475
476//The following functions read the input of the player and then set the bools for the movement
477void SOBFigure::moveFrontBack(const Vector2& value)
478{
479    if (value.x > 0)
480    {
481        moveUpPressed_ = true;
482        moveDownPressed_ = false;
483    }
484    else
485    {
486        moveUpPressed_ = false;
487        moveDownPressed_ = true;
488    }
489}
490
491void SOBFigure::moveRightLeft(const Vector2& value)
492{
493    if (value.x > 0)
494    {
495        moveLeftPressed_ = false;
496        moveRightPressed_ = true;
497    }
498    else
499    {
500        moveLeftPressed_ = true;
501        moveRightPressed_ = false;
502    }
503}
504
505void SOBFigure::boost(bool boost)
506{
507    firePressed_ = boost;
508}
509
510
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            }   
529}
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.