Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/rocket/src/orxonox/controllers/NewHumanController.cc @ 7007

Last change on this file since 7007 was 6948, checked in by scheusso, 14 years ago

somes fixes/changes in NewHumanController

  • Property svn:eol-style set to native
File size: 22.7 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 (showArrows_)
188            {
189                if (this->arrowsOverlay1_)
190                    this->arrowsOverlay1_->destroy();
191                if (this->arrowsOverlay2_)
192                    this->arrowsOverlay2_->destroy();
193                if (this->arrowsOverlay3_)
194                    this->arrowsOverlay3_->destroy();
195                if (this->arrowsOverlay4_)
196                    this->arrowsOverlay4_->destroy();
197            }
198        }
199    }
200
201    void NewHumanController::tick(float dt)
202    {
203        if (GameMode::showsGraphics())
204        {
205
206            if (this->controllableEntity_ && !this->controllableEntity_->isInMouseLook())
207            {
208                this->updateTarget();
209
210                if (!controlPaused_ )
211                {
212                    if (this->getControllableEntity() && (this->getControllableEntity()->isExactlyA(ClassByString("SpaceShip")) || this->getControllableEntity()->isExactlyA(ClassByString("Rocket"))))
213                        this->showOverlays();
214
215                    this->crossHairOverlay_->setPosition(Vector2(static_cast<float>(this->currentYaw_)/2*-1+.5f-overlaySize_/2, static_cast<float>(this->currentPitch_)/2*-1+.5f-overlaySize_/2));
216
217                    if (this->controlMode_ == 0 || (this->controlMode_ == 1 && this->firemode_ == 1))
218                    {
219                        if (this->showOverlays_ && this->showArrows_)
220                            alignArrows();
221                    }
222                    else
223                        hideArrows();
224
225                    if (this->showDamageOverlay_ && (this->damageOverlayTT_ > 0 || this->damageOverlayTR_ > 0 || this->damageOverlayTB_ > 0 || this->damageOverlayTL_ > 0))
226                    {
227                        this->damageOverlayTT_ -= dt;
228                        this->damageOverlayTR_ -= dt;
229                        this->damageOverlayTB_ -= dt;
230                        this->damageOverlayTL_ -= dt;
231                        if (this->damageOverlayTT_ <= 0)
232                            this->damageOverlayTop_->hide();
233                        if (this->damageOverlayTR_ <= 0)
234                            this->damageOverlayRight_->hide();
235                        if (this->damageOverlayTB_ <= 0)
236                            this->damageOverlayBottom_->hide();
237                        if (this->damageOverlayTL_ <= 0)
238                            this->damageOverlayLeft_->hide();
239                    }
240                }
241            }
242            else
243                this->hideOverlays();
244
245            if (this->acceleration_ > 0)
246            {
247                if (this->accelerating_)
248                    HumanController::moveFrontBack(Vector2(1, 0));
249                else
250                    HumanController::moveFrontBack(Vector2(this->acceleration_, 0));
251                this->accelerating_ = false;
252                //HumanController::moveFrontBack(Vector2(clamp(this->acceleration_ + this->currentAcceleration_, 0.0f, 1.0f), 0));
253            }
254        }
255
256        // Reset pitch and yaw rates
257        // TODO: Reactivate this to fix the game pad problem with 0 input
258        //this->currentPitch_ = 0;
259        //this->currentYaw_ = 0;
260
261        HumanController::tick(dt);
262    }
263
264    void NewHumanController::doFire(unsigned int firemode)
265    {
266        if (!this->controllableEntity_)
267            return;
268
269        this->firemode_ = firemode;
270
271        if (firemode == 1 && this->controlMode_ == 1)
272        {
273            //unlocked steering, steer on right mouse click
274            HumanController::yaw(Vector2(this->currentYaw_, 0));
275            HumanController::pitch(Vector2(this->currentPitch_, 0));
276        }
277        else
278            HumanController::localController_s->getControllableEntity()->fire(firemode);
279
280    }
281
282    void NewHumanController::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage)
283    {
284        if (this->showDamageOverlay_ && !this->controlPaused_ && this->controllableEntity_ && !this->controllableEntity_->isInMouseLook())
285        {
286            Vector3 posA;
287            if (originator)
288                posA = originator->getWorldPosition();
289            else
290                posA = multi_cast<Vector3>(contactpoint.getPositionWorldOnA());
291            //Vector3 posB = multi_cast<Vector3>(contactpoint.getPositionWorldOnB());
292            //posA and posB are almost identical
293
294            Vector3 relativeHit = this->getControllableEntity()->getWorldOrientation().UnitInverse() * (this->getControllableEntity()->getWorldPosition() - posA);
295
296            //back is z positive
297            //x is left positive
298            //y is down positive
299            relativeHit.normalise();
300
301            float threshold = 0.3f;
302            if (relativeHit.x > threshold) // Left
303            {
304                this->damageOverlayLeft_->show();
305                this->damageOverlayTL_ = this->damageOverlayTime_;
306                //this->damageOverlayLeft_->setBackgroundAlpha(0.3);
307            }
308            if (relativeHit.x < -threshold) //Right
309            {
310                this->damageOverlayRight_->show();
311                this->damageOverlayTR_ = this->damageOverlayTime_;
312                //this->damageOverlayRight_->setBackgroundAlpha(0.3);
313            }
314            if (relativeHit.y > threshold) //Top
315            {
316                this->damageOverlayBottom_->show();
317                this->damageOverlayTB_ = this->damageOverlayTime_;
318                //this->damageOverlayTop_->setBackgroundAlpha(0.3);
319            }
320            if (relativeHit.y < -threshold) //Bottom
321            {
322                this->damageOverlayTop_->show();
323                this->damageOverlayTT_ = this->damageOverlayTime_;
324                //this->damageOverlayBottom_->setBackgroundAlpha(0.3);
325            }
326        }
327    }
328
329    void NewHumanController::unfire()
330    {
331        if (NewHumanController::localController_s)
332            NewHumanController::localController_s->doUnfire();
333    }
334
335    void NewHumanController::doUnfire()
336    {
337        this->firemode_ = -1;
338        hideArrows();
339    }
340
341    void NewHumanController::updateTarget()
342    {
343        Ogre::RaySceneQuery * rsq = HumanController::localController_s->getControllableEntity()->getScene()->getSceneManager()->createRayQuery(Ogre::Ray());
344
345        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);
346
347        rsq->setRay(mouseRay);
348        rsq->setSortByDistance(true);
349
350        /*
351        Distance of objects:
352        ignore everything under 200 maybe even take 1000 as min distance to shoot at
353
354        shots are regularly traced and are entities!!!!!!!!! this is the biggest problem
355        they vanish only after a distance of 10'000
356        */
357
358
359        Ogre::RaySceneQueryResult& result = rsq->execute();
360        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
361        WorldEntity* myWe = static_cast<WorldEntity*>(this->getControllableEntity());
362
363        Ogre::RaySceneQueryResult::iterator itr;
364        for (itr = result.begin(); itr != result.end(); ++itr)
365        {
366//             CCOUT(0) << "testing object as target" << endl;
367            if (itr->movable->isInScene() && itr->movable->getMovableType() == "Entity" /*&& itr->distance > 500*/)
368            {
369                // Try to cast the user pointer
370                WorldEntity* wePtr = dynamic_cast<WorldEntity*>(Ogre::any_cast<OrxonoxClass*>(itr->movable->getUserAny()));
371               
372                // make sure we don't shoot ourselves
373                if( wePtr==myWe )
374                    continue;
375               
376                if (wePtr)
377                {
378                    // go through all parents of object and look whether they are sightable or not
379                    bool isSightable = false;
380                    WorldEntity* parent = wePtr->getParent();
381                    while (parent)
382                    {
383                        if (this->targetMask_.isExcluded(parent->getIdentifier()) || parent==myWe)
384                        {
385                            parent = parent->getParent();
386                            continue;
387                        }
388                        else
389                        {
390                            isSightable = true;
391                            break;
392                        }
393                    }
394                    if (!isSightable)
395                        continue;
396                }
397
398                if (this->getControllableEntity() && this->getControllableEntity()->getTarget() != wePtr)
399                    this->getControllableEntity()->setTarget(wePtr);
400
401                if (pawn)
402                    pawn->setAimPosition( mouseRay.getOrigin() + mouseRay.getDirection() * itr->distance );
403
404                //itr->movable->getParentSceneNode()->showBoundingBox(true);
405                //return mouseRay.getOrigin() + mouseRay.getDirection() * itr->distance; //or itr->movable->getParentSceneNode()->_getDerivedPosition()
406                return;
407            }
408        }
409
410        if (pawn)
411            pawn->setAimPosition( mouseRay.getOrigin() + mouseRay.getDirection() * 1200 );
412
413        if( this->getControllableEntity() && this->getControllableEntity()->getTarget() != 0 )
414            this->getControllableEntity()->setTarget( 0 );
415
416        //return this->controllableEntity_->getWorldPosition() + (this->controllableEntity_->getWorldOrientation() * Vector3::NEGATIVE_UNIT_Z * 2000);
417        //return this->controllableEntity_->getWorldPosition() + (this->controllableEntity_->getCamera()->getOgreCamera()->getOrientation() * Vector3::NEGATIVE_UNIT_Z);
418    }
419
420    void NewHumanController::frontback(const Vector2& value)
421    {
422        this->accelerating_ = true;
423
424        //if (this->acceleration_ == 0)
425        HumanController::frontback(value);
426    }
427
428    void NewHumanController::yaw(const Vector2& value)
429    {
430        //SUPER(NewHumanController, yaw, value);
431        if (this->controlMode_ == 0 || (this->controllableEntity_ && this->controllableEntity_->isInMouseLook()))
432            HumanController::yaw(value);
433
434        this->currentYaw_ = value.x;
435    }
436
437    void NewHumanController::pitch(const Vector2& value)
438    {
439        //SUPER(NewHumanController, pitch, value);
440        if (this->controlMode_ == 0 || (this->controllableEntity_ && this->controllableEntity_->isInMouseLook()))
441            HumanController::pitch(value);
442
443        this->currentPitch_ = value.x;
444    }
445
446    void NewHumanController::changeMode()
447    {
448        if (NewHumanController::localController_s)
449        {
450            if (NewHumanController::localController_s->controlMode_ == 0)
451            {
452                NewHumanController::localController_s->controlMode_ = 1;
453                NewHumanController::localController_s->hideArrows();
454            }
455            else
456                NewHumanController::localController_s->controlMode_ = 0;
457        }
458    }
459
460    void NewHumanController::changedControllableEntity()
461    {
462        this->controlMode_ = 0;
463        this->currentYaw_ = 0;
464        this->currentPitch_ = 0;
465        if (this->getControllableEntity() && (this->getControllableEntity()->isExactlyA(ClassByString("SpaceShip")) || this->getControllableEntity()->isExactlyA(ClassByString("Rocket"))))
466        {
467            this->showOverlays_ = true;
468            if (!this->controlPaused_)
469            {
470                this->showOverlays();
471                this->alignArrows();
472            }
473        }
474        else
475        {
476            this->showOverlays_ = false;
477            this->hideOverlays();
478        }
479    }
480
481    void NewHumanController::accelerate()
482    {
483        if (NewHumanController::localController_s)
484            NewHumanController::localController_s->acceleration_ = clamp(NewHumanController::localController_s->acceleration_ + 0.2f, 0.00f, 1.0f);
485    }
486
487    void NewHumanController::decelerate()
488    {
489        if (NewHumanController::localController_s)
490            NewHumanController::localController_s->acceleration_ = clamp(NewHumanController::localController_s->acceleration_ - 0.1f, 0.0f, 1.0f);
491    }
492
493    void NewHumanController::doResumeControl()
494    {
495        this->controlPaused_ = false;
496        if (this->showOverlays_)
497            this->showOverlays();
498    }
499
500    void NewHumanController::doPauseControl()
501    {
502        this->controlPaused_ = true;
503        this->hideOverlays();
504    }
505
506    void NewHumanController::alignArrows()
507    {
508        if (showArrows_)
509        {
510            hideArrows();
511
512            float distance = sqrt(pow(static_cast<float>(this->currentYaw_)/2*-1,2) + pow(static_cast<float>(this->currentPitch_)/2*-1,2));
513
514            if (distance > 0.04f && distance <= 0.59f * arrowsSize_ / 2.0f )
515            {
516                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));
517                this->arrowsOverlay1_->show();
518            }
519            else if (distance > 0.59f * arrowsSize_ / 2.0f && distance <= 0.77f * arrowsSize_ / 2.0f )
520            {
521                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));
522                this->arrowsOverlay2_->show();
523            }
524            else if (distance > 0.77f * arrowsSize_ / 2.0f && distance <= arrowsSize_ / 2.0f)
525            {
526                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));
527                this->arrowsOverlay3_->show();
528            }
529            else if (distance > arrowsSize_ / 2.0f)
530            {
531                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));
532                this->arrowsOverlay4_->show();
533            }
534        }
535    }
536
537    void NewHumanController::showOverlays()
538    {
539        if (!GameMode::showsGraphics())
540            return;
541        this->crossHairOverlay_->show();
542        this->centerOverlay_->show();
543
544        if (showArrows_)
545        {
546            this->arrowsOverlay1_->show();
547            this->arrowsOverlay2_->show();
548            this->arrowsOverlay3_->show();
549            this->arrowsOverlay4_->show();
550        }
551    }
552
553    void NewHumanController::hideOverlays()
554    {
555        if (!GameMode::showsGraphics())
556            return;
557        this->crossHairOverlay_->hide();
558        this->centerOverlay_->hide();
559
560        if (showDamageOverlay_)
561        {
562            this->damageOverlayTop_->hide();
563            this->damageOverlayRight_->hide();
564            this->damageOverlayBottom_->hide();
565            this->damageOverlayLeft_->hide();
566        }
567
568        this->hideArrows();
569    }
570
571    void NewHumanController::hideArrows()
572    {
573        if(!GameMode::showsGraphics())
574            return;
575        if (showArrows_)
576        {
577            this->arrowsOverlay1_->hide();
578            this->arrowsOverlay2_->hide();
579            this->arrowsOverlay3_->hide();
580            this->arrowsOverlay4_->hide();
581        }
582    }
583       
584
585   
586
587
588}
Note: See TracBrowser for help on using the repository browser.