Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

more improvements

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