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

Revision 4280, 30.1 kB (checked in by robert, 9 years ago)

Updates to osgcatch game to allow different types of falling objects

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