Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/superorxobros/SOBFigure.cc @ 12017

Last change on this file since 12017 was 11783, checked in by landauf, 7 years ago

merged Presentation_HS17_merge back to trunk

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