Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

shooting mechanism fixed

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