root/OpenSceneGraph/trunk/examples/osgcatch/osgcatch.cpp @ 4281

Revision 4281, 31.9 kB (checked in by robert, 9 years ago)

Added support for multiple levels, and exit on lose of all lives or on finishng
the highest level.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgProducer/Viewer>
15#include <osgDB/ReadFile>
16#include <osgDB/WriteFile>
17#include <osgUtil/Optimizer>
18
19#include <osg/Geode>
20#include <osg/Notify>
21#include <osg/MatrixTransform>
22#include <osg/PositionAttitudeTransform>
23#include <osg/Switch>
24#include <osg/TexMat>
25#include <osg/Texture2D>
26#include <osg/io_utils>
27
28#include <osgParticle/ExplosionEffect>
29#include <osgParticle/ExplosionDebriEffect>
30#include <osgParticle/SmokeEffect>
31#include <osgParticle/FireEffect>
32
33typedef std::vector<std::string> FileList;
34typedef std::map<std::string, osg::ref_ptr<osg::Node> >  ObjectMap;
35
36static ObjectMap    s_objectMap;
37
38class Character : public osg::Referenced
39{
40public:
41    Character();
42   
43    void setCharacter(const std::string& filename, const std::string& name, const osg::Vec3& orgin, const osg::Vec3& width, const osg::Vec3& catchPos, float positionRatio);
44   
45    void setLives(const std::string& filename, const osg::Vec3& orgin, const osg::Vec3& delta, unsigned int numLives);
46   
47    void setCatches(const std::string& filename, const osg::Vec3& orgin, const osg::Vec3& delta, unsigned int numLives);
48
49    void moveLeft();
50    void moveRight();
51    void moveTo(float positionRatio);
52
53    void reset();
54
55    void resetCatches();
56
57    bool addCatch();
58   
59    bool looseLife();
60
61    osg::Vec3 getCurrentCenterOfBasket() const { return _character->getPosition()+_centerBasket; }
62    float getCurrentRadiusOfBasket() const { return _radiusBasket; }
63
64    osg::Vec3 getLowerLeft() const { return _character->getPosition(); }
65    osg::Vec3 getUpperRight() const { return _character->getPosition(); }
66
67    osg::Vec3 _origin;
68    osg::Vec3 _width;
69
70    float                                        _positionRatio;
71    osg::ref_ptr<osg::PositionAttitudeTransform> _character;
72
73    unsigned int                                 _numLives;
74    osg::ref_ptr<osg::Switch>                    _livesSwitch;
75
76    unsigned int                                 _numCatches;
77    osg::ref_ptr<osg::Switch>                    _catchSwitch;
78   
79    osg::ref_ptr<osg::Group>                     _objectsGroup;
80   
81    osg::Vec3                                    _centerBasket;
82    float                                        _radiusBasket;
83   
84};
85
86Character::Character():
87    _positionRatio(0.5f),
88    _numLives(3),
89    _numCatches(0)
90{
91}
92
93
94void Character::setCharacter(const std::string& filename, const std::string& name, const osg::Vec3& origin, const osg::Vec3& width, const osg::Vec3& catchPos, float positionRatio)
95{
96    _origin = origin;
97    _width = width;
98    _positionRatio = positionRatio;
99    _numLives = 3;
100    _numCatches = 0;
101
102    float _characterSize = _width.length()*0.2f;
103
104    osg::Image* image = osgDB::readImageFile(filename);
105    if (image)
106    {
107        osg::Vec3 pos(-0.5f*_characterSize,0.0f,0.0f);
108        osg::Vec3 width(_characterSize*((float)image->s())/(float)(image->t()),0.0f,0.0);
109        osg::Vec3 height(0.0f,0.0f,_characterSize);
110
111        osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
112        osg::StateSet* stateset = geometry->getOrCreateStateSet();
113        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
114        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
115        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
116
117        osg::Geode* geode = new osg::Geode;
118        geode->addDrawable(geometry);
119
120        _character = new osg::PositionAttitudeTransform;
121        _character->setName(name);
122        _character->addChild(geode);
123       
124        moveTo(positionRatio);
125
126        _centerBasket = width*catchPos.x() + height*catchPos.y() + pos;
127        _radiusBasket = width.length()*catchPos.z();
128
129    }
130   
131}
132
133void Character::setLives(const std::string& filename, const osg::Vec3& origin, const osg::Vec3& delta, unsigned int numLives)
134{
135    float characterSize = delta.length();
136
137    _numLives = numLives;
138    _livesSwitch = new osg::Switch;
139
140    osg::Image* image = osgDB::readImageFile(filename);
141    if (image)
142    {
143        osg::StateSet* stateset = _livesSwitch->getOrCreateStateSet();
144        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
145        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
146        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
147
148        for(unsigned int i=0; i<numLives; ++i)
149        {
150            osg::Vec3 pos = origin + delta*(float)i + osg::Vec3(0.0f,0.0f,0.0f);
151            osg::Vec3 width(characterSize*((float)image->s())/(float)(image->t()),0.0f,0.0);
152            osg::Vec3 height(0.0f,0.0f,characterSize);
153
154            osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
155
156            osg::Geode* geode = new osg::Geode;
157            geode->addDrawable(geometry);
158
159            _livesSwitch->addChild(geode,true);
160
161        }
162    }
163
164}
165
166void Character::setCatches(const std::string& filename, const osg::Vec3& origin, const osg::Vec3& delta, unsigned int numCatches)
167{
168    float characterSize = delta.length();
169
170    _numCatches = 0;
171    _catchSwitch = new osg::Switch;
172
173    osg::Image* image = osgDB::readImageFile(filename);
174    if (image)
175    {
176        osg::StateSet* stateset = _catchSwitch->getOrCreateStateSet();
177        stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
178        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
179        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
180
181        for(unsigned int i=0; i<numCatches; ++i)
182        {
183            osg::Vec3 pos = origin + delta*(float)i + osg::Vec3(0.0f,0.0f,0.0f);
184            osg::Vec3 width(characterSize,0.0f,0.0);
185            osg::Vec3 height(0.0f,0.0f,characterSize*((float)image->t())/(float)(image->s()));
186
187            osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
188
189            osg::Geode* geode = new osg::Geode;
190            geode->addDrawable(geometry);
191
192            _catchSwitch->addChild(geode,false);
193
194        }
195    }
196
197}
198
199void Character::moveLeft()
200{
201    moveTo(_positionRatio - 0.01f);
202}
203
204void Character::moveRight()
205{
206    moveTo(_positionRatio + 0.01f);
207}
208
209void Character::moveTo(float positionRatio)
210{
211    if (positionRatio<0.0f) positionRatio = 0.0f;
212    if (positionRatio>1.0f) positionRatio = 1.0f;
213
214    _positionRatio = positionRatio;
215    _character->setPosition(_origin+_width*+positionRatio);
216}
217
218void Character::reset()
219{
220    _numCatches = 0;
221    _numLives = _livesSwitch->getNumChildren();
222
223    _livesSwitch->setAllChildrenOn();
224    _catchSwitch->setAllChildrenOff();
225}
226
227void Character::resetCatches()
228{
229    _numCatches = 0;
230    _catchSwitch->setAllChildrenOff();
231}
232
233bool Character::addCatch()
234{
235    if (!_catchSwitch || _numCatches>=_catchSwitch->getNumChildren()) return false;
236   
237    _catchSwitch->setValue(_numCatches,true);
238    ++_numCatches;
239   
240    return true;
241}
242
243bool Character::looseLife()
244{
245    if (!_livesSwitch || _numLives==0) return false;
246   
247    --_numLives;
248    _livesSwitch->setValue(_numLives,false);
249   
250    return (_numLives!=0);
251}
252
253
254//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
255//
256class CatchableObject  : public osg::Referenced
257{
258    public:
259        CatchableObject();
260
261        void setObject(const std::string& filename, const std::string& name, const osg::Vec3& center, float size, const osg::Vec3& direction);
262
263        bool anyInside(const osg::Vec3& lower_left, const osg::Vec3& top_right);
264
265        bool centerInside(const osg::Vec3& center, float radius);
266       
267        void explode();
268       
269        bool dangerous() { return _dangerous; }
270
271        void stop() { _stopped = true; }
272       
273        bool stopped() { return _stopped; }
274       
275        void setTimeToRemove(double time) { _timeToRemove=time; }
276       
277        double getTimeToRemove() { return _timeToRemove; }
278       
279        bool needToRemove(double time) { return  _timeToRemove>=0.0 && time>_timeToRemove; }
280       
281        osg::ref_ptr<osg::PositionAttitudeTransform> _object;
282        osg::Vec3                                    _velocity;
283        float                                        _mass;
284        float                                        _radius;
285
286        bool                                         _stopped;
287        bool                                         _dangerous;
288
289        double                                       _timeToRemove;
290
291        static void setUpCatchablesMap(const FileList& fileList);
292
293    public:
294   
295        // update position and velocity
296        void update(double dt);
297
298        /// Set the viscosity of the fluid.
299        inline void setFluidViscosity(float v)
300        {
301            _viscosity = v;
302            _viscosityCoefficient = 6 * osg::PI * _viscosity;
303        }
304       
305        /// Get the viscosity of the fluid.
306        inline float getFluidViscosity() const { return _viscosity; }
307
308        /// Set the density of the fluid.
309        inline void setFluidDensity(float d)
310        {
311            _density = d;
312            _densityCoefficeint = 0.2f * osg::PI * _density;
313        }
314
315        /// Get the density of the fluid.
316        inline float getFluidDensity() const { return _density; }
317       
318       
319        /// Set the wind vector.
320        inline void setWind(const osg::Vec3& wind) { _wind = wind; }
321       
322        /// Get the wind vector.
323        inline const osg::Vec3& getWind() const { return _wind; }
324       
325        /// Set the acceleration vector.
326        inline void setAcceleration(const osg::Vec3& v) { _acceleration = v; }
327       
328        /// Get the acceleration vector.
329        inline const osg::Vec3& getAcceleration() const { return _acceleration; }
330
331        /** Set the acceleration vector to the gravity on earth (0, 0, -9.81).
332            The acceleration will be multiplied by the <CODE>scale</CODE> parameter.
333        */
334        inline void setToGravity(float scale = 1.0f) { _acceleration.set(0, 0, -9.81f*scale); }
335
336        /// Set the fluid parameters as for air (20°C temperature).
337        inline void setFluidToAir()
338        {
339            setToGravity(1.0f);
340            setFluidDensity(1.2929f);
341            setFluidViscosity(1.8e-5f);
342        }
343       
344        /// Set the fluid parameters as for pure water (20°C temperature).
345        inline void setFluidToWater()
346        {
347            setToGravity(1.0f);
348            setFluidDensity(1.0f);
349            setFluidViscosity(1.002e-3f);
350        }
351           
352
353    protected:
354
355        osg::Vec3   _acceleration;
356        float       _viscosity;
357        float       _density;
358        osg::Vec3   _wind;
359
360        float       _viscosityCoefficient;
361        float       _densityCoefficeint;
362       
363 
364};
365
366CatchableObject::CatchableObject()
367{
368    _stopped = false;
369    _dangerous = false;
370   
371    _timeToRemove = -1.0; // do not remove.
372    setFluidToAir();
373}
374
375void CatchableObject::setUpCatchablesMap(const FileList& fileList)
376{
377    for(FileList::const_iterator itr=fileList.begin();
378        itr!=fileList.end();
379        ++itr)
380    {
381        const std::string& filename = *itr;
382        osg::Image* image = osgDB::readImageFile(filename);
383        if (image)
384        {
385            osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
386            stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
387            stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
388            stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
389           
390            osg::Vec3 width((float)(image->s())/(float)(image->t()),0.0f,0.0);
391            osg::Vec3 height(0.0f,0.0f,1.0f);
392            osg::Vec3 pos = (width+height)*-0.5f;
393
394            osg::Geometry* geometry = osg::createTexturedQuadGeometry(pos,width,height);
395            geometry->setStateSet(stateset.get());
396
397            osg::Geode* geode = new osg::Geode;
398            geode->addDrawable(geometry);
399
400            s_objectMap[filename] = geode;
401        }
402    }
403}
404
405void CatchableObject::setObject(const std::string& filename, const std::string& name, const osg::Vec3& center, float characterSize, const osg::Vec3& velocity)
406{
407    _radius = 0.5f*characterSize;
408    float Area = osg::PI*_radius*_radius;
409    float Volume = Area*_radius*4.0f/3.0f;
410
411    _velocity = velocity;
412    _mass = 1000.0*Volume;
413
414    if (s_objectMap.count(filename)!=0)
415    {
416        osg::PositionAttitudeTransform* scaleTransform = new osg::PositionAttitudeTransform;
417        scaleTransform->setScale(osg::Vec3(characterSize,characterSize,characterSize));
418        scaleTransform->addChild(s_objectMap[filename].get());
419
420        _object = new osg::PositionAttitudeTransform;
421        _object->setName(name);
422        _object->setPosition(center);
423        _object->addChild(scaleTransform);
424    }
425    else
426    {
427        osg::notify(osg::NOTICE)<<"CatchableObject::setObject("<<filename<<") not able to create catchable object."<<std::endl;
428    }
429}
430
431void CatchableObject::update(double dt)
432{
433    if (_stopped) return;
434
435    float Area = osg::PI*_radius*_radius;
436    float Volume = Area*_radius*4.0f/3.0f;
437
438    // compute force due to gravity + boyancy of displacing the fluid that the particle is emersed in.
439    osg::Vec3 force = _acceleration * (_mass - _density*Volume);
440
441    // compute force due to friction
442    osg::Vec3 relative_wind = _velocity-_wind;           
443    force -= relative_wind * Area * (_viscosityCoefficient + _densityCoefficeint*relative_wind.length());           
444
445    // divide force by mass to get acceleration.
446    _velocity += force*(dt/_mass);
447    _object->setPosition(_object->getPosition()+_velocity*dt);
448}
449
450bool CatchableObject::anyInside(const osg::Vec3& lower_left, const osg::Vec3& upper_right)
451{
452    osg::Vec3 pos = _object->getPosition();
453   
454    if (pos.x()+_radius < lower_left.x()) return false;
455    if (pos.x()-_radius > upper_right.x()) return false;
456    if (pos.z()+_radius < lower_left.z()) return false;
457    if (pos.z()-_radius > upper_right.z()) return false;
458
459    return true;
460}
461
462bool CatchableObject::centerInside(const osg::Vec3& center, float radius)
463{
464    osg::Vec3 delta = _object->getPosition() - center;
465    return (delta.length()<radius);
466}
467
468
469void CatchableObject::explode()
470{
471    osg::Vec3 position(0.0f,0.0f,0.0f);
472    osgParticle::ExplosionEffect* explosion = new osgParticle::ExplosionEffect(position, _radius);
473    osgParticle::ExplosionDebriEffect* explosionDebri = new osgParticle::ExplosionDebriEffect(position, _radius);
474    osgParticle::SmokeEffect* smoke = new osgParticle::SmokeEffect(position, _radius);
475    osgParticle::FireEffect* fire = new osgParticle::FireEffect(position, _radius);
476
477    explosion->setWind(_wind);
478    explosionDebri->setWind(_wind);
479    smoke->setWind(_wind);
480    fire->setWind(_wind);
481
482    _object->addChild(explosion);
483    _object->addChild(explosionDebri);
484    _object->addChild(smoke);
485    _object->addChild(fire);
486
487    _dangerous = true;
488
489}
490
491
492
493//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
494//
495class GameEventHandler : public osgGA::GUIEventHandler
496{
497public:
498
499    GameEventHandler();
500   
501    META_Object(osgStereImageApp,GameEventHandler);
502
503    virtual void accept(osgGA::GUIEventHandlerVisitor& v) { v.visit(*this); }
504
505    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
506   
507    virtual void getUsage(osg::ApplicationUsage& usage) const;
508   
509    osg::Matrix getCameraPosition();
510   
511    osg::Node* createScene();
512   
513    void setFOVY(float fovy) { _fovy = fovy; }
514    float getFOVY() const { return _fovy; }
515   
516    void createNewCatchable();
517   
518    void resetLevel()
519    {
520        _level = 0;
521        _levelSwitch->setSingleChildOn(_level);
522    }
523   
524    void nextLevel()
525    {
526        ++_level;
527        if (_level < _levelSwitch->getNumChildren())
528        {
529            _levelSwitch->setSingleChildOn(_level);
530        }
531    }
532   
533    bool gameComplete()
534    {
535        return _level >= _levelSwitch->getNumChildren();
536    }
537
538    enum Players
539    {
540        PLAYER_GIRL,
541        PLAYER_BOY
542    };
543
544    void addPlayer(Players player)
545    {
546        osg::Vec3 livesPosition;
547        osg::Vec3 catchesPosition;
548        if (_numberOfPlayers==0)
549        {
550            livesPosition = _originBaseLine+osg::Vec3(0.0f,-0.5f,0.0f);
551            catchesPosition = _originBaseLine+osg::Vec3(200.0f,-0.5f,0.0f);
552        }
553        else
554        {
555            livesPosition = _originBaseLine+osg::Vec3(900.0f,-0.5f,000.0f);
556            catchesPosition = _originBaseLine+osg::Vec3(1100.0f,-0.5f,0.0f);
557        }
558       
559        switch(player)
560        {
561            case PLAYER_GIRL:
562            {
563                std::string player_one = "Catch/girl.png";
564                osg::Vec3 catchPos(0.2, 0.57, 0.34);
565
566                _players[_numberOfPlayers].setCharacter(player_one,"girl", _originBaseLine + osg::Vec3(0.0f,-1.0f,0.0f), _widthBaseLine, catchPos, 0.5f);
567                _players[_numberOfPlayers].setLives(player_one,livesPosition, osg::Vec3(0.0f,0.0f,100.0f),3);
568                _players[_numberOfPlayers].setCatches("Catch/broach.png",catchesPosition, osg::Vec3(0.0f,0.0f,100.0f),10);
569
570                ++_numberOfPlayers;
571                break;
572            }
573            case PLAYER_BOY:
574            {
575                std::string player_two = "Catch/boy.png";
576                osg::Vec3 catchPos(0.8, 0.57, 0.34);
577
578                _players[_numberOfPlayers].setCharacter(player_two,"boy", _originBaseLine + osg::Vec3(0.0f,-2.0f,0.0f), _widthBaseLine, catchPos, 0.5f);
579                _players[_numberOfPlayers].setLives(player_two,livesPosition, osg::Vec3(0.0f,0.0f,100.0f),3);
580                _players[_numberOfPlayers].setCatches("Catch/broach.png",catchesPosition, osg::Vec3(0.0f,0.0f,100.0f),10);
581
582                 ++_numberOfPlayers;
583               break;
584            }
585        }               
586    }
587       
588       
589
590protected:
591
592    ~GameEventHandler() {}
593    GameEventHandler(const GameEventHandler&,const osg::CopyOp&) {}
594
595    osg::Vec3 _origin;
596    osg::Vec3 _width;
597    osg::Vec3 _height;
598    osg::Vec3 _originBaseLine;
599    osg::Vec3 _widthBaseLine;
600    float     _characterSize;
601   
602    float _fovy;
603
604    unsigned _level;
605   
606    float _chanceOfExplodingAtStart;
607    float _initialNumDropsPerSecond;
608   
609    osg::ref_ptr<osg::Group> _group;
610    osg::ref_ptr<osg::Switch> _levelSwitch;
611   
612    unsigned int _numberOfPlayers;
613    Character _players[2];
614
615    typedef std::list< osg::ref_ptr<CatchableObject> > CatchableObjectList;
616    CatchableObjectList _catchableObjects;
617   
618    FileList _backgroundFiles;
619    FileList _benignCatachables;
620
621    bool _leftKeyPressed;
622    bool _rightKeyPressed;
623   
624       
625};
626
627
628
629
630GameEventHandler::GameEventHandler()
631{
632    _origin.set(0.0f,0.0f,0.0f);
633    _width.set(1280.0f,0.0f,0.0f);
634    _height.set(0.0f,0.0f,1024.0f);
635    _widthBaseLine = _width*0.9f;
636    _originBaseLine = _origin+_width*0.5-_widthBaseLine*0.5f;
637    _characterSize = _width.length()*0.2f;
638
639    _numberOfPlayers = 0;
640    _level = 0;
641
642    _chanceOfExplodingAtStart = 0.1f;
643    _initialNumDropsPerSecond = 1.0f;
644
645    _leftKeyPressed=false;
646    _rightKeyPressed=false;
647
648    _backgroundFiles.push_back("Catch/sky1.JPG");
649    _backgroundFiles.push_back("Catch/sky2.JPG");
650    _backgroundFiles.push_back("Catch/sky3.JPG");
651    _backgroundFiles.push_back("Catch/farm.JPG");
652
653    _benignCatachables.push_back("Catch/a.png");
654    _benignCatachables.push_back("Catch/b.png");
655    _benignCatachables.push_back("Catch/c.png");
656    _benignCatachables.push_back("Catch/m.png");
657    _benignCatachables.push_back("Catch/n.png");
658    _benignCatachables.push_back("Catch/s.png");
659    _benignCatachables.push_back("Catch/t.png");
660    _benignCatachables.push_back("Catch/u.png");
661    _benignCatachables.push_back("Catch/ball.png");
662   
663    CatchableObject::setUpCatchablesMap(_benignCatachables);
664   
665   
666
667}
668
669bool GameEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
670{
671    switch(ea.getEventType())
672    {
673        case(osgGA::GUIEventAdapter::FRAME):
674        {
675            // move characters
676            if (_leftKeyPressed)
677            {
678                if (_numberOfPlayers>=2) _players[1].moveLeft();
679            }
680           
681            if (_rightKeyPressed)
682            {
683                if (_numberOfPlayers>=2) _players[1].moveRight();
684            }
685
686            static double previous_time = ea.time();
687            double dt = ea.time()-previous_time;
688            previous_time = ea.time();
689           
690            // move objects
691            for(CatchableObjectList::iterator itr=_catchableObjects.begin();
692                itr!=_catchableObjects.end();
693                ++itr)
694            {
695                (*itr)->update(dt);
696               
697                bool removeEntry = false;
698
699                for(unsigned int i=0;i<_numberOfPlayers;++i)
700                {
701                    if ((*itr)->dangerous())
702                    {
703                        if ((*itr)->anyInside(_players[i].getLowerLeft(),_players[i].getUpperRight()))
704                        {
705                            if (!_players[i].looseLife())
706                            {
707                                std::cout<<"Ouch you lost all your lives, Game Over!!"<<std::endl;
708                                exit(0);
709                            }
710                            removeEntry = true;
711                        }
712                    }
713                    else
714                    {
715                        if ((*itr)->centerInside(_players[i].getCurrentCenterOfBasket(),_players[i].getCurrentRadiusOfBasket()))
716                        {
717                            if (!_players[i].addCatch())
718                            {
719                                _players[i].resetCatches();
720                                nextLevel();
721                                if (gameComplete())
722                                {
723                                    std::cout<<"Congratulations you've completed the game!!"<<std::endl;
724                                    exit(0);
725                                }
726                            }
727                           
728                           
729                            removeEntry = true;
730                        }
731                    }
732                }
733
734                if (!(*itr)->anyInside(_origin, _origin+_width+_height) ||
735                    (*itr)->needToRemove(ea.time()) ||
736                    removeEntry)
737                {
738                    // need to remove
739                    // remove child from parents.
740                    osg::ref_ptr<osg::PositionAttitudeTransform> child = (*itr)->_object;
741                    osg::Node::ParentList parents = child->getParents();
742                    for(osg::Node::ParentList::iterator pitr=parents.begin();
743                        pitr!=parents.end();
744                        ++pitr)
745                    {
746                        (*pitr)->removeChild(child.get());
747                    }
748
749                    // remove child from catchable list
750                    itr = _catchableObjects.erase(itr);
751
752                }
753                else if ((*itr)->anyInside(_origin, _origin+_width) && !(*itr)->stopped())
754                {
755                    // hit base line
756                    (*itr)->explode();
757                    (*itr)->stop();
758                    (*itr)->setTimeToRemove(ea.time()+3.0);
759                }
760               
761            }
762             
763
764            // create new catchable objects
765            static double previousTime = ea.time();
766            double deltaTime = ea.time()-previousTime;
767            previousTime = ea.time();
768           
769            float numDropsPerSecond = _initialNumDropsPerSecond * (_level+1);
770            float r = (float)rand()/(float)RAND_MAX;
771            if (r < deltaTime*numDropsPerSecond)
772            {
773                createNewCatchable();
774            }
775
776
777
778        }
779        case(osgGA::GUIEventAdapter::KEYDOWN):
780        {
781            if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left)
782            {
783                _leftKeyPressed=true;
784                return true;
785            }
786            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
787            {
788                _rightKeyPressed=true;
789                return true;
790            }
791            else if (ea.getKey()==' ')
792            {
793                for(unsigned int i=0;i<_numberOfPlayers;++i)
794                {
795                    _players[i].reset();
796                }
797                return true;
798            }
799        }
800        case(osgGA::GUIEventAdapter::KEYUP):
801        {
802            if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left)
803            {
804                _leftKeyPressed=false;
805                return true;
806            }
807            else if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right)
808            {
809                _rightKeyPressed=false;
810                return true;
811            }
812        }
813        case(osgGA::GUIEventAdapter::DRAG):
814        case(osgGA::GUIEventAdapter::MOVE):
815        {
816            float px = (ea.getXnormalized()+1.0f)*0.5f;
817
818            if (_numberOfPlayers>=1) _players[0].moveTo(px);
819
820            return true;
821        }
822
823        default:
824            return false;
825    }
826}
827
828void GameEventHandler::getUsage(osg::ApplicationUsage&) const
829{
830}
831
832osg::Matrix GameEventHandler::getCameraPosition()
833{
834    osg::Matrix cameraPosition;
835    osg::Vec3 center = _origin+(_width+_height)*0.5f;
836   
837    float distance = _height.length()/(2.0f*tanf(_fovy*0.5f));
838   
839    cameraPosition.makeLookAt(center-osg::Vec3(0.0f,distance,0.0f),center,osg::Vec3(0.0f,0.0f,1.0f));
840    return cameraPosition;
841}
842
843osg::Node* GameEventHandler::createScene()
844{
845    _group = new osg::Group;
846
847    if (_numberOfPlayers==0)
848    {
849        addPlayer(PLAYER_GIRL);
850    }
851
852    for(unsigned int i=0;i<_numberOfPlayers;++i)
853    {
854        _group->addChild(_players[i]._character.get());
855        _group->addChild(_players[i]._livesSwitch.get());
856        _group->addChild(_players[i]._catchSwitch.get());
857    }   
858   
859    // background
860    {
861        _levelSwitch = new osg::Switch;
862       
863        for(FileList::const_iterator itr = _backgroundFiles.begin();
864            itr != _backgroundFiles.end();
865            ++itr)
866        {
867
868            osg::Image* image = osgDB::readImageFile(*itr);
869            if (image)
870            {
871                osg::Geometry* geometry = osg::createTexturedQuadGeometry(_origin,_width,_height);
872                osg::StateSet* stateset = geometry->getOrCreateStateSet();
873                stateset->setTextureAttributeAndModes(0,new osg::Texture2D(image),osg::StateAttribute::ON);
874
875                osg::Geode* geode = new osg::Geode;
876                geode->addDrawable(geometry);
877
878                _levelSwitch->addChild(geode);
879            }
880        }
881        _levelSwitch->setSingleChildOn(0);
882        _group->addChild(_levelSwitch.get());
883    }
884
885    return _group.get();
886}
887
888void GameEventHandler::createNewCatchable()
889{
890    if (_benignCatachables.empty()) return;
891
892    unsigned int catachableIndex = (unsigned int)((float)_benignCatachables.size()*(float)rand()/(float)RAND_MAX);
893    if (catachableIndex>=_benignCatachables.size()) catachableIndex = _benignCatachables.size()-1;
894   
895    const std::string& filename = _benignCatachables[catachableIndex];
896
897    float ratio = ((float)rand() / (float)RAND_MAX);
898    float size = 100.0f*((float)rand() / (float)RAND_MAX);
899    float angle = osg::PI*0.25f + 0.5f*osg::PI*((float)rand() / (float)RAND_MAX);
900    float speed = 200.0f*((float)rand() / (float)RAND_MAX);
901
902    CatchableObject* catchableObject = new CatchableObject;
903    osg::Vec3 position = _origin+_height+_width*ratio + osg::Vec3(0.0f,-0.7f,0.0f);
904    osg::Vec3 velocity(-cosf(angle)*speed,0.0f,-sinf(angle)*speed);
905    //std::cout<<"angle = "<<angle<<" velocity="<<velocity<<std::endl;
906    catchableObject->setObject(filename,"boy",position,size,velocity);
907    _catchableObjects.push_back(catchableObject);
908
909    float r = (float)rand() / (float)RAND_MAX;
910    if (r < _chanceOfExplodingAtStart)
911    {
912       catchableObject->explode();
913    }
914
915    _group->addChild(catchableObject->_object.get());
916}
917
918int main( int argc, char **argv )
919{
920
921    // use an ArgumentParser object to manage the program arguments.
922    osg::ArgumentParser arguments(&argc,argv);
923   
924    // set up the usage document, in case we need to print out how to use this program.
925    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use node masks to create stereo images.");
926    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file_left_eye image_file_right_eye");
927    arguments.getApplicationUsage()->addCommandLineOption("-d <float>","Time delay in sceonds between the display of successive image pairs when in auto advance mode.");
928    arguments.getApplicationUsage()->addCommandLineOption("-a","Enter auto advance of image pairs on start up.");
929    arguments.getApplicationUsage()->addCommandLineOption("-x <float>","Horizontal offset of left and right images.");
930    arguments.getApplicationUsage()->addCommandLineOption("-y <float>","Vertical offset of left and right images.");
931    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
932   
933
934    // construct the viewer.
935    osgProducer::Viewer viewer(arguments);
936
937    // set up the value with sensible default event handlers.
938    viewer.setUpViewer(osgProducer::Viewer::ESCAPE_SETS_DONE);
939
940    // register the handler to add keyboard and mosue handling.
941    GameEventHandler* seh = new GameEventHandler();
942    viewer.getEventHandlerList().push_front(seh);
943
944    while (arguments.read("--boy")) seh->addPlayer(GameEventHandler::PLAYER_BOY);
945    while (arguments.read("--girl")) seh->addPlayer(GameEventHandler::PLAYER_GIRL);
946   
947   
948
949    // get details on keyboard and mouse bindings used by the viewer.
950    viewer.getUsage(*arguments.getApplicationUsage());
951
952    // if user request help write it out to cout.
953    if (arguments.read("-h") || arguments.read("--help"))
954    {
955        arguments.getApplicationUsage()->write(std::cout);
956        return 1;
957    }
958
959    // any option left unread are converted into errors to write out later.
960    arguments.reportRemainingOptionsAsUnrecognized();
961
962    // report any errors if they have occured when parsing the program aguments.
963    if (arguments.errors())
964    {
965        arguments.writeErrorMessages(std::cout);
966        return 1;
967    }
968   
969    // now the windows have been realized we switch off the cursor to prevent it
970    // distracting the people seeing the stereo images.
971    float fovy = 1.0f;
972    for( unsigned int i = 0; i < viewer.getCameraConfig()->getNumberOfCameras(); i++ )
973    {
974        Producer::Camera* cam = viewer.getCameraConfig()->getCamera(i);
975        Producer::RenderSurface* rs = cam->getRenderSurface();
976        rs->useCursor(false);
977        fovy = osg::DegreesToRadians(cam->getLensVerticalFov());
978    }
979   
980    seh->setFOVY(fovy);
981   
982    // creat the scene from the file list.
983    osg::ref_ptr<osg::Node> rootNode = seh->createScene();
984
985    //osgDB::writeNodeFile(*rootNode,"test.osg");
986
987    // set the scene to render
988    viewer.setSceneData(rootNode.get());
989
990    // create the windows and run the threads.
991    viewer.realize();
992   
993    viewer.requestWarpPointer(0.5f,0.5f);
994       
995
996    while( !viewer.done() )
997    {
998        // wait for all cull and draw threads to complete.
999        viewer.sync();
1000
1001        // update the scene by traversing it with the the update visitor which will
1002        // call all node update callbacks and animations.
1003        viewer.update();
1004         
1005        viewer.setView(seh->getCameraPosition());
1006
1007        // fire off the cull and draw traversals of the scene.
1008        viewer.frame();
1009       
1010    }
1011   
1012    // wait for all cull and draw threads to complete before exit.
1013    viewer.sync();
1014   
1015    return 0;
1016}
Note: See TracBrowser for help on using the browser.