Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/orxonox/controllers/NewHumanController.cc @ 6906

Last change on this file since 6906 was 6598, checked in by scheusso, 15 years ago

someone forgot to delete these overlays

  • Property svn:eol-style set to native
File size: 22.6 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 *      Michael Wirth
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "NewHumanController.h"
30
31#include <cmath>
32#include <OgreRay.h>
33#include <OgreSceneQuery.h>
34#include <OgreCamera.h>
35#include <OgreSceneManager.h>
36#include <bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
37
38#include "core/CoreIncludes.h"
39#include "core/ConsoleCommand.h"
40#include "worldentities/ControllableEntity.h"
41#include "worldentities/pawns/Pawn.h"
42#include "infos/PlayerInfo.h"
43#include "overlays/OrxonoxOverlay.h"
44#include "graphics/Camera.h"
45#include "sound/SoundManager.h"
46#include "tools/BulletConversions.h"
47#include "Scene.h"
48
49namespace orxonox
50{
51    SetConsoleCommand(NewHumanController, changeMode, false).keybindMode(KeybindMode::OnPress);
52    SetConsoleCommand(NewHumanController, accelerate, false).keybindMode(KeybindMode::OnPress);
53    SetConsoleCommand(NewHumanController, decelerate, false).keybindMode(KeybindMode::OnPress);
54    SetConsoleCommand(NewHumanController, unfire,      true).keybindMode(KeybindMode::OnRelease);
55
56    CreateUnloadableFactory(NewHumanController);
57
58    NewHumanController* NewHumanController::localController_s = 0;
59
60    NewHumanController::NewHumanController(BaseObject* creator)
61        : HumanController(creator)
62        , crossHairOverlay_(NULL)
63        , centerOverlay_(NULL)
64        , damageOverlayTop_(NULL)
65        , damageOverlayRight_(NULL)
66        , damageOverlayBottom_(NULL)
67        , damageOverlayLeft_(NULL)
68        , damageOverlayTT_(0)
69        , arrowsOverlay1_(NULL)
70        , arrowsOverlay2_(NULL)
71        , arrowsOverlay3_(NULL)
72        , arrowsOverlay4_(NULL)
73    {
74        RegisterObject(NewHumanController);
75
76        overlaySize_ = 0.08f;
77        arrowsSize_ = 0.4f;
78
79        damageOverlayTime_ = 0.6f;
80
81        controlMode_ = 0;
82        acceleration_ = 0;
83        accelerating_ = false;
84        firemode_ = -1;
85
86        showArrows_ = true;
87        showOverlays_ = false;
88        showDamageOverlay_ = true;
89
90        //currentPitch_ = 1;
91        //currentYaw_ = 1;
92
93        if (GameMode::showsGraphics())
94        {
95            crossHairOverlay_ = new OrxonoxOverlay(this);
96            crossHairOverlay_->setBackgroundMaterial("Orxonox/Crosshair3");
97            crossHairOverlay_->setSize(Vector2(overlaySize_, overlaySize_));
98            crossHairOverlay_->hide();
99            //crossHairOverlay_->setAspectCorrection(true); not working
100
101            centerOverlay_ = new OrxonoxOverlay(this);
102            centerOverlay_->setBackgroundMaterial("Orxonox/CenterOverlay");
103            centerOverlay_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
104            centerOverlay_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
105            centerOverlay_->hide();
106
107            if (showDamageOverlay_)
108            {
109                damageOverlayTop_ = new OrxonoxOverlay(this);
110                damageOverlayTop_->setBackgroundMaterial("Orxonox/DamageOverlayTop");
111                damageOverlayTop_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
112                damageOverlayTop_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
113                damageOverlayTop_->hide();
114
115                damageOverlayRight_ = new OrxonoxOverlay(this);
116                damageOverlayRight_->setBackgroundMaterial("Orxonox/DamageOverlayRight");
117                damageOverlayRight_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
118                damageOverlayRight_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
119                damageOverlayRight_->hide();
120
121                damageOverlayBottom_ = new OrxonoxOverlay(this);
122                damageOverlayBottom_->setBackgroundMaterial("Orxonox/DamageOverlayBottom");
123                damageOverlayBottom_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
124                damageOverlayBottom_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
125                damageOverlayBottom_->hide();
126
127                damageOverlayLeft_ = new OrxonoxOverlay(this);
128                damageOverlayLeft_->setBackgroundMaterial("Orxonox/DamageOverlayLeft");
129                damageOverlayLeft_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
130                damageOverlayLeft_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
131                damageOverlayLeft_->hide();
132            }
133
134            if (showArrows_)
135            {
136                arrowsOverlay1_ = new OrxonoxOverlay(this);
137                arrowsOverlay1_->setBackgroundMaterial("Orxonox/DirectionArrows1");
138                arrowsOverlay1_->setSize(Vector2(0.02727f, 0.36f * arrowsSize_));
139                arrowsOverlay1_->setPickPoint(Vector2(0.5f, 0.5f));
140                arrowsOverlay1_->setPosition(Vector2(0.5f, 0.5f));
141                arrowsOverlay1_->hide();
142
143                arrowsOverlay2_ = new OrxonoxOverlay(this);
144                arrowsOverlay2_->setBackgroundMaterial("Orxonox/DirectionArrows2");
145                arrowsOverlay2_->setSize(Vector2(0.02727f, 0.59f * arrowsSize_));
146                arrowsOverlay2_->setPickPoint(Vector2(0.5f, 0.5f));
147                arrowsOverlay2_->setPosition(Vector2(0.5f, 0.5f));
148                arrowsOverlay2_->hide();
149
150                arrowsOverlay3_ = new OrxonoxOverlay(this);
151                arrowsOverlay3_->setBackgroundMaterial("Orxonox/DirectionArrows3");
152                arrowsOverlay3_->setSize(Vector2(0.02727f, 0.77f * arrowsSize_));
153                arrowsOverlay3_->setPickPoint(Vector2(0.5f, 0.5f));
154                arrowsOverlay3_->setPosition(Vector2(0.5f, 0.5f));
155                arrowsOverlay3_->hide();
156
157                arrowsOverlay4_ = new OrxonoxOverlay(this);
158                arrowsOverlay4_->setBackgroundMaterial("Orxonox/DirectionArrows4");
159                arrowsOverlay4_->setSize(Vector2(0.02727f, arrowsSize_));
160                arrowsOverlay4_->setPickPoint(Vector2(0.5f, 0.5f));
161                arrowsOverlay4_->setPosition(Vector2(0.5f, 0.5f));
162                arrowsOverlay4_->hide();
163            }
164        }
165
166        // HACK: Define which objects are targetable when considering the creator of an orxonox::Model
167        this->targetMask_.exclude(ClassByString("BaseObject"));
168        this->targetMask_.include(ClassByString("WorldEntity"));
169        this->targetMask_.exclude(ClassByString("Projectile"));
170
171        NewHumanController::localController_s = this;
172
173        controlPaused_ = false;
174
175        //HumanController::localController_s->getControllableEntity()->getCamera()->setDrag(true);
176    }
177
178    NewHumanController::~NewHumanController()
179    {
180        if (this->isInitialized())
181        {
182            if (this->crossHairOverlay_)
183                this->crossHairOverlay_->destroy();
184            if (this->centerOverlay_)
185                this->centerOverlay_->destroy();
186
187            if (this->arrowsOverlay1_)
188                this->arrowsOverlay1_->destroy();
189            if (this->arrowsOverlay2_)
190                this->arrowsOverlay2_->destroy();
191            if (this->arrowsOverlay3_)
192                this->arrowsOverlay3_->destroy();
193            if (this->arrowsOverlay4_)
194                this->arrowsOverlay4_->destroy();
195            if (this->damageOverlayTop_)
196                this->damageOverlayTop_->destroy();
197            if (this->damageOverlayLeft_)
198                this->damageOverlayLeft_->destroy();
199            if (this->damageOverlayRight_)
200                this->damageOverlayRight_->destroy();
201            if (this->damageOverlayBottom_)
202                this->damageOverlayBottom_->destroy();
203        }
204    }
205
206    void NewHumanController::tick(float dt)
207    {
208        if (GameMode::showsGraphics())
209        {
210
211            if (this->controllableEntity_ && !this->controllableEntity_->isInMouseLook())
212            {
213                this->updateTarget();
214
215                if (!controlPaused_ )
216                {
217                    if (this->getControllableEntity() && (this->getControllableEntity()->isExactlyA(ClassByString("SpaceShip")) || this->getControllableEntity()->isExactlyA(ClassByString("Rocket"))))
218                        this->showOverlays();
219
220                    this->crossHairOverlay_->setPosition(Vector2(static_cast<float>(this->currentYaw_)/2*-1+.5f-overlaySize_/2, static_cast<float>(this->currentPitch_)/2*-1+.5f-overlaySize_/2));
221
222                    if (this->controlMode_ == 0 || (this->controlMode_ == 1 && this->firemode_ == 1))
223                    {
224                        if (this->showOverlays_ && this->showArrows_)
225                            alignArrows();
226                    }
227                    else
228                        hideArrows();
229
230                    if (this->showDamageOverlay_ && (this->damageOverlayTT_ > 0 || this->damageOverlayTR_ > 0 || this->damageOverlayTB_ > 0 || this->damageOverlayTL_ > 0))
231                    {
232                        this->damageOverlayTT_ -= dt;
233                        this->damageOverlayTR_ -= dt;
234                        this->damageOverlayTB_ -= dt;
235                        this->damageOverlayTL_ -= dt;
236                        if (this->damageOverlayTT_ <= 0)
237                            this->damageOverlayTop_->hide();
238                        if (this->damageOverlayTR_ <= 0)
239                            this->damageOverlayRight_->hide();
240                        if (this->damageOverlayTB_ <= 0)
241                            this->damageOverlayBottom_->hide();
242                        if (this->damageOverlayTL_ <= 0)
243                            this->damageOverlayLeft_->hide();
244                    }
245                }
246            }
247            else
248                this->hideOverlays();
249
250            if (this->acceleration_ > 0)
251            {
252                if (this->accelerating_)
253                    HumanController::moveFrontBack(Vector2(1, 0));
254                else
255                    HumanController::moveFrontBack(Vector2(this->acceleration_, 0));
256                this->accelerating_ = false;
257                //HumanController::moveFrontBack(Vector2(clamp(this->acceleration_ + this->currentAcceleration_, 0.0f, 1.0f), 0));
258            }
259        }
260
261        // Reset pitch and yaw rates
262        // TODO: Reactivate this to fix the game pad problem with 0 input
263        //this->currentPitch_ = 0;
264        //this->currentYaw_ = 0;
265
266        HumanController::tick(dt);
267    }
268
269    void NewHumanController::doFire(unsigned int firemode)
270    {
271        if (!this->controllableEntity_)
272            return;
273
274        this->firemode_ = firemode;
275
276        if (firemode == 1 && this->controlMode_ == 1)
277        {
278            //unlocked steering, steer on right mouse click
279            HumanController::yaw(Vector2(this->currentYaw_, 0));
280            HumanController::pitch(Vector2(this->currentPitch_, 0));
281        }
282        else
283            HumanController::localController_s->getControllableEntity()->fire(firemode);
284
285    }
286
287    void NewHumanController::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage)
288    {
289        if (this->showDamageOverlay_ && !this->controlPaused_ && this->controllableEntity_ && !this->controllableEntity_->isInMouseLook())
290        {
291            Vector3 posA;
292            if (originator)
293                posA = originator->getWorldPosition();
294            else
295                posA = multi_cast<Vector3>(contactpoint.getPositionWorldOnA());
296            //Vector3 posB = multi_cast<Vector3>(contactpoint.getPositionWorldOnB());
297            //posA and posB are almost identical
298
299            Vector3 relativeHit = this->getControllableEntity()->getWorldOrientation().UnitInverse() * (this->getControllableEntity()->getWorldPosition() - posA);
300
301            //back is z positive
302            //x is left positive
303            //y is down positive
304            relativeHit.normalise();
305
306            float threshold = 0.3f;
307            if (relativeHit.x > threshold) // Left
308            {
309                this->damageOverlayLeft_->show();
310                this->damageOverlayTL_ = this->damageOverlayTime_;
311                //this->damageOverlayLeft_->setBackgroundAlpha(0.3);
312            }
313            if (relativeHit.x < -threshold) //Right
314            {
315                this->damageOverlayRight_->show();
316                this->damageOverlayTR_ = this->damageOverlayTime_;
317                //this->damageOverlayRight_->setBackgroundAlpha(0.3);
318            }
319            if (relativeHit.y > threshold) //Top
320            {
321                this->damageOverlayBottom_->show();
322                this->damageOverlayTB_ = this->damageOverlayTime_;
323                //this->damageOverlayTop_->setBackgroundAlpha(0.3);
324            }
325            if (relativeHit.y < -threshold) //Bottom
326            {
327                this->damageOverlayTop_->show();
328                this->damageOverlayTT_ = this->damageOverlayTime_;
329                //this->damageOverlayBottom_->setBackgroundAlpha(0.3);
330            }
331        }
332    }
333
334    void NewHumanController::unfire()
335    {
336        if (NewHumanController::localController_s)
337            NewHumanController::localController_s->doUnfire();
338    }
339
340    void NewHumanController::doUnfire()
341    {
342        this->firemode_ = -1;
343        hideArrows();
344    }
345
346    void NewHumanController::updateTarget()
347    {
348        Ogre::RaySceneQuery * rsq = HumanController::localController_s->getControllableEntity()->getScene()->getSceneManager()->createRayQuery(Ogre::Ray());
349
350        Ogre::Ray mouseRay = HumanController::localController_s->getControllableEntity()->getCamera()->getOgreCamera()->getCameraToViewportRay(static_cast<float>(this->currentYaw_)/2*-1+.5f, static_cast<float>(this->currentPitch_)/2*-1+.5f);
351
352        rsq->setRay(mouseRay);
353        rsq->setSortByDistance(true);
354
355        /*
356        Distance of objects:
357        ignore everything under 200 maybe even take 1000 as min distance to shoot at
358
359        shots are regularly traced and are entities!!!!!!!!! this is the biggest problem
360        they vanish only after a distance of 10'000
361        */
362
363
364        Ogre::RaySceneQueryResult& result = rsq->execute();
365        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
366
367        Ogre::RaySceneQueryResult::iterator itr;
368        for (itr = result.begin(); itr != result.end(); ++itr)
369        {
370            if (itr->movable->isInScene() && itr->movable->getMovableType() == "Entity" && itr->distance > 500)
371            {
372                // Try to cast the user pointer
373                WorldEntity* wePtr = dynamic_cast<WorldEntity*>(Ogre::any_cast<OrxonoxClass*>(itr->movable->getUserAny()));
374                if (wePtr)
375                {
376                    // go through all parents of object and look whether they are sightable or not
377                    bool isSightable = false;
378                    WorldEntity* parent = wePtr->getParent();
379                    while (parent)
380                    {
381                        if (this->targetMask_.isExcluded(parent->getIdentifier()))
382                        {
383                            parent = parent->getParent();
384                            continue;
385                        }
386                        else
387                        {
388                            isSightable = true;
389                            break;
390                        }
391                    }
392                    if (!isSightable)
393                        continue;
394                }
395
396                if (this->getControllableEntity() && this->getControllableEntity()->getTarget() != wePtr)
397                    this->getControllableEntity()->setTarget(wePtr);
398
399                if (pawn)
400                    pawn->setAimPosition( mouseRay.getOrigin() + mouseRay.getDirection() * itr->distance );
401
402                //itr->movable->getParentSceneNode()->showBoundingBox(true);
403                //return mouseRay.getOrigin() + mouseRay.getDirection() * itr->distance; //or itr->movable->getParentSceneNode()->_getDerivedPosition()
404                return;
405            }
406        }
407
408        if (pawn)
409            pawn->setAimPosition( mouseRay.getOrigin() + mouseRay.getDirection() * 1200 );
410
411        if( this->getControllableEntity() && this->getControllableEntity()->getTarget() != 0 )
412            this->getControllableEntity()->setTarget( 0 );
413
414        //return this->controllableEntity_->getWorldPosition() + (this->controllableEntity_->getWorldOrientation() * Vector3::NEGATIVE_UNIT_Z * 2000);
415        //return this->controllableEntity_->getWorldPosition() + (this->controllableEntity_->getCamera()->getOgreCamera()->getOrientation() * Vector3::NEGATIVE_UNIT_Z);
416    }
417
418    void NewHumanController::frontback(const Vector2& value)
419    {
420        this->accelerating_ = true;
421
422        //if (this->acceleration_ == 0)
423        HumanController::frontback(value);
424    }
425
426    void NewHumanController::yaw(const Vector2& value)
427    {
428        //SUPER(NewHumanController, yaw, value);
429        if (this->controlMode_ == 0 || (this->controllableEntity_ && this->controllableEntity_->isInMouseLook()))
430            HumanController::yaw(value);
431
432        this->currentYaw_ = value.x;
433    }
434
435    void NewHumanController::pitch(const Vector2& value)
436    {
437        //SUPER(NewHumanController, pitch, value);
438        if (this->controlMode_ == 0 || (this->controllableEntity_ && this->controllableEntity_->isInMouseLook()))
439            HumanController::pitch(value);
440
441        this->currentPitch_ = value.x;
442    }
443
444    void NewHumanController::changeMode()
445    {
446        if (NewHumanController::localController_s)
447        {
448            if (NewHumanController::localController_s->controlMode_ == 0)
449            {
450                NewHumanController::localController_s->controlMode_ = 1;
451                NewHumanController::localController_s->hideArrows();
452            }
453            else
454                NewHumanController::localController_s->controlMode_ = 0;
455        }
456    }
457
458    void NewHumanController::changedControllableEntity()
459    {
460        this->controlMode_ = 0;
461        this->currentYaw_ = 0;
462        this->currentPitch_ = 0;
463        if (this->getControllableEntity() && (this->getControllableEntity()->isExactlyA(ClassByString("SpaceShip")) || this->getControllableEntity()->isExactlyA(ClassByString("Rocket"))))
464        {
465            this->showOverlays_ = true;
466            if (!this->controlPaused_)
467            {
468                this->showOverlays();
469                this->alignArrows();
470            }
471        }
472        else
473        {
474            this->showOverlays_ = false;
475            this->hideOverlays();
476        }
477    }
478
479    void NewHumanController::accelerate()
480    {
481        if (NewHumanController::localController_s)
482            NewHumanController::localController_s->acceleration_ = clamp(NewHumanController::localController_s->acceleration_ + 0.2f, 0.00f, 1.0f);
483    }
484
485    void NewHumanController::decelerate()
486    {
487        if (NewHumanController::localController_s)
488            NewHumanController::localController_s->acceleration_ = clamp(NewHumanController::localController_s->acceleration_ - 0.1f, 0.0f, 1.0f);
489    }
490
491    void NewHumanController::doResumeControl()
492    {
493        this->controlPaused_ = false;
494        if (this->showOverlays_)
495            this->showOverlays();
496    }
497
498    void NewHumanController::doPauseControl()
499    {
500        this->controlPaused_ = true;
501        this->hideOverlays();
502    }
503
504    void NewHumanController::alignArrows()
505    {
506        if (showArrows_)
507        {
508            hideArrows();
509
510            float distance = sqrt(pow(static_cast<float>(this->currentYaw_)/2*-1,2) + pow(static_cast<float>(this->currentPitch_)/2*-1,2));
511
512            if (distance > 0.04f && distance <= 0.59f * arrowsSize_ / 2.0f )
513            {
514                this->arrowsOverlay1_->setRotation(Degree(-90 + -1.0f * atan2(static_cast<float>(this->currentPitch_)/2*-1, static_cast<float>(this->currentYaw_)/2*-1) / (2.0f * Ogre::Math::PI) * 360.0f));
515                this->arrowsOverlay1_->show();
516            }
517            else if (distance > 0.59f * arrowsSize_ / 2.0f && distance <= 0.77f * arrowsSize_ / 2.0f )
518            {
519                this->arrowsOverlay2_->setRotation(Degree(-90 + -1.0f * atan2(static_cast<float>(this->currentPitch_)/2*-1, static_cast<float>(this->currentYaw_)/2*-1) / (2.0f * Ogre::Math::PI) * 360.0f));
520                this->arrowsOverlay2_->show();
521            }
522            else if (distance > 0.77f * arrowsSize_ / 2.0f && distance <= arrowsSize_ / 2.0f)
523            {
524                this->arrowsOverlay3_->setRotation(Degree(-90 + -1.0f * atan2(static_cast<float>(this->currentPitch_)/2*-1, static_cast<float>(this->currentYaw_)/2*-1) / (2.0f * Ogre::Math::PI) * 360.0f));
525                this->arrowsOverlay3_->show();
526            }
527            else if (distance > arrowsSize_ / 2.0f)
528            {
529                this->arrowsOverlay4_->setRotation(Degree(-90 + -1.0f * atan2(static_cast<float>(this->currentPitch_)/2*-1, static_cast<float>(this->currentYaw_)/2*-1) / (2.0f * Ogre::Math::PI) * 360.0f));
530                this->arrowsOverlay4_->show();
531            }
532        }
533    }
534
535    void NewHumanController::showOverlays()
536    {
537        if (!GameMode::showsGraphics())
538            return;
539        this->crossHairOverlay_->show();
540        this->centerOverlay_->show();
541
542        if (showArrows_)
543        {
544            this->arrowsOverlay1_->show();
545            this->arrowsOverlay2_->show();
546            this->arrowsOverlay3_->show();
547            this->arrowsOverlay4_->show();
548        }
549    }
550
551    void NewHumanController::hideOverlays()
552    {
553        if (!GameMode::showsGraphics())
554            return;
555        this->crossHairOverlay_->hide();
556        this->centerOverlay_->hide();
557
558        if (showDamageOverlay_)
559        {
560            this->damageOverlayTop_->hide();
561            this->damageOverlayRight_->hide();
562            this->damageOverlayBottom_->hide();
563            this->damageOverlayLeft_->hide();
564        }
565
566        this->hideArrows();
567    }
568
569    void NewHumanController::hideArrows()
570    {
571        if(!GameMode::showsGraphics())
572            return;
573        if (showArrows_)
574        {
575            this->arrowsOverlay1_->hide();
576            this->arrowsOverlay2_->hide();
577            this->arrowsOverlay3_->hide();
578            this->arrowsOverlay4_->hide();
579        }
580    }
581}
Note: See TracBrowser for help on using the repository browser.