Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 11601 was 11601, checked in by zarron, 6 years ago

with Highscores

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