src/tron/zone/zZone.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023   
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #include "rSDL.h"
00029 
00030 #include "zone/zZone.h"
00031 #include "eFloor.h"
00032 #include "eTimer.h"
00033 #include "eGrid.h"
00034 #include "gCycle.h"
00035 #include "gGame.h"
00036 //#include "eTeam.h"
00037 //#include "ePlayer.h"
00038 #include "rRender.h"
00039 #include "nConfig.h"
00040 #include "tString.h"
00041 #include "rScreen.h"
00042 #include "eSoundMixer.h"
00043 #include "tPolynomial.h"
00044 
00045 
00046 #include <time.h>
00047 #include <map>
00048 #include <algorithm>
00049 #include <functional>
00050 #include <deque>
00051 #include <iterator>
00052 
00053 #include "gWinZone.h"
00054 
00055 std::deque<zZone *> sz_Zones;
00056 
00057 // number of segments to render a zone with
00058 static const int sg_segments = 11;
00059 
00060 // *******************************************************************************
00061 // *
00062 // *   EvaluateFunctionNow
00063 // *
00064 // *******************************************************************************
00069 // *******************************************************************************
00070 
00071 inline REAL zZone::EvaluateFunctionNow( tFunction const & f ) const
00072 {
00073     return f( lastTime - referenceTime_ );
00074 }
00075 
00076 // *******************************************************************************
00077 // *
00078 // *   SetFunctionNow
00079 // *
00080 // *******************************************************************************
00085 // *******************************************************************************
00086 
00087 inline void zZone::SetFunctionNow( tFunction & f, REAL value ) const
00088 {
00089     f.SetOffset( value + f.GetSlope() * ( referenceTime_ - lastTime ) );
00090 }
00091 
00092 // *******************************************************************************
00093 // *
00094 // *    zZone
00095 // *
00096 // *******************************************************************************
00101 // *******************************************************************************
00102 zZone::zZone( eGrid * grid )
00103         :eNetGameObject( grid, eCoord(0,0), eCoord(0,0), NULL, true ),
00104         //        rotation_(1,0),
00105         effectGroupEnter(),
00106         effectGroupInside(),
00107         effectGroupLeave(),
00108         effectGroupOutside(),
00109         playersInside(),
00110         playersOutside(),
00111         oldFortressAutomaticAssignmentBehavior_(false),
00112         name_()
00113 {
00114     // store creation time
00115     referenceTime_ = createTime_ = lastTime = 0;
00116 
00117     // add to game grid
00118     this->AddToList();
00119 
00120     sz_Zones.push_back(this);
00121 
00122     // initialize position functions
00123     //    SetPosition( pos );
00124     eSoundMixer* mixer = eSoundMixer::GetMixer();
00125     mixer->PushButton(ZONE_SPAWN, pos);
00126 }
00127 
00128 static nVersionFeature sz_ShapedZones(20);
00129 
00130 // *******************************************************************************
00131 // *
00132 // *    zZone
00133 // *
00134 // *******************************************************************************
00138 // *******************************************************************************
00139 
00140 zZone::zZone( nMessage & m )
00141         :eNetGameObject( m ),
00142         //rotation_(1,0),
00143         playersInside(),
00144         playersOutside(),
00145         oldFortressAutomaticAssignmentBehavior_(false),
00146         name_()
00147 {
00148     // read creation time
00149     m >> createTime_;
00150     referenceTime_ = lastTime = createTime_;
00151 
00152     // initialize color to white, ReadSync will fill in the true value if available
00153     //    color_.r_ = color_.g_ = color_.b_ = 1.0f;
00154 
00155     // add to game grid
00156     this->AddToList();
00157 
00158     sz_Zones.push_back(this);
00159 
00160     // initialize position functions
00161     //    SetPosition( pos );
00162     eSoundMixer* mixer = eSoundMixer::GetMixer();
00163     mixer->PushButton(ZONE_SPAWN, pos);
00164 
00165 
00166     /*
00167     shape = zShapePtr(new zShapeCircle(Grid(), ID()));
00168 
00169     tFunction asdf = tFunction();
00170     asdf.SetSlope(0.0);
00171     asdf.SetOffset(100.0);
00172     shape->setPosX(asdf);
00173     shape->setPosY(asdf);
00174     shape->setScale(asdf);
00175     shape->setRotation(asdf);
00176     shape->setScale(asdf);
00177     shape->setColor(rColor(0.7, 0.0, 0.7));
00178     zShapeCircle *circle = dynamic_cast<zShapeCircle *>( (zShape*)shape );
00179 
00180     circle->emulatingOldZone_ = true;
00181     */
00182 
00183     /*
00184     if (!m.End() && sz_ShapedZones.Supported() ) 
00185       {
00186         // Factory to make the shapes
00187         // HACK 
00188         // This makes them static for the life of the zone
00189         // rather than to re-send them all at each updates
00190         typedef zShape* (*shapeFactory)(nMessage &);
00191         std::map<tString, shapeFactory> shapes;
00192         // Build the list of supported shapes
00193         shapes[tString("circle")] = zShapeCircle::create;
00194         shapes[tString("polygon")] = zShapePolygon::create;
00195 
00196         // Get the name of the shape from the network
00197         tString shapeName;
00198         m >> shapeName;
00199         
00200         std::map<tString, shapeFactory>::const_iterator iterShapeFactory;
00201         // Build that shape if it is available
00202         if((iterShapeFactory = shapes.find(shapeName)) != shapes.end()) 
00203           {
00204             shape = zShapePtr((*(iterShapeFactory->second))(m));
00205           }
00206       }
00207     else
00208       {
00209         // Didnt receive a shape information. Assume we are talking to a 0.2.8- server
00210         shape = zShapePtr(new zShapeCircle());
00211         shape->setPosX(posx_);
00212         shape->setPosY(posy_);
00213         shape->setScale(scale_);
00214         tPolynomial<nMessage> tpRotationSpeed(2);
00215         tpRotationSpeed[0] = rotationSpeed_.GetOffset();
00216         tpRotationSpeed[0] = rotationSpeed_.GetOffset();
00217         shape->setRotation2(tpRotationSpeed);
00218         shape->setScale(scale_);
00219         shape->setColor(color_);
00220         
00221         emulateOldZoneShape = true;
00222       }
00223 */
00224 
00225 }
00226 
00227 // *******************************************************************************
00228 // *
00229 // *    ~zZone
00230 // *
00231 // *******************************************************************************
00234 // *******************************************************************************
00235 
00236 zZone::~zZone( void )
00237 {
00238     RemoveFromZoneList();
00239 }
00240 
00241 void zZone::RemoveFromGame(void) {
00242     RemoveFromZoneList();
00243     eNetGameObject::RemoveFromGame();
00244 }
00245 
00246 void zZone::RemoveFromZoneList(void) {
00247     std::deque<zZone *>::iterator pos_found =
00248         std::find_if(
00249             sz_Zones.begin(),
00250             sz_Zones.end(),
00251             std::bind2nd(
00252                 std::equal_to<zZone *>(),
00253                 this)
00254         );
00255     if(pos_found != sz_Zones.end())
00256         sz_Zones.erase(pos_found);
00257 }
00258 
00259 // *******************************************************************************
00260 // *
00261 // *    WriteCreate
00262 // *
00263 // *******************************************************************************
00267 // *******************************************************************************
00268 
00269 void zZone::WriteCreate( nMessage & m )
00270 {
00271     // delegate
00272     eNetGameObject::WriteCreate( m );
00273 
00274     m << createTime_;
00275 
00276     /*
00277     if(!emulateOldZoneShape && sz_ShapedZones.Supported() )
00278       shape->WriteCreate( m );
00279     */
00280 }
00281 
00282 // *******************************************************************************
00283 // *
00284 // *    WriteSync
00285 // *
00286 // *******************************************************************************
00290 // *******************************************************************************
00291 
00292 void zZone::WriteSync( nMessage & m )
00293 {
00294     // delegate
00295     eNetGameObject::WriteSync( m );
00296 
00297     /*
00298     // write color
00299     m << color_.r_;
00300     m << color_.g_;
00301     m << color_.b_;
00302 
00303     // write reference time and functions
00304     m << referenceTime_;
00305     m << posx_;
00306     m << posy_;
00307     m << scale_;
00308 
00309     // write rotation speed
00310     m << rotationSpeed_;
00311     */
00312 
00313     // Simply populate the message with semi-meaningful data
00314     m << shape->getColor().r_;
00315     m << shape->getColor().g_;
00316     m << shape->getColor().b_;
00317 
00318     m << referenceTime_;
00319 
00320     m << shape->getPosX();
00321     m << shape->getPosY();
00322     m << shape->getScale();
00323     // shape->getRotation no longer exist. Fake it!
00324     tFunction tfFakedRotation;
00325     m << tfFakedRotation;
00326 
00327     m << shape->ID();
00328 }
00329 
00330 // *******************************************************************************
00331 // *
00332 // *    ReadSync
00333 // *
00334 // *******************************************************************************
00338 // *******************************************************************************
00339 
00340 void zZone::ReadSync( nMessage & m )
00341 {
00342     // delegage
00343     eNetGameObject::ReadSync( m );
00344 
00345     if(shape && shape->isEmulatingOldZone())
00346     {
00347         // read color
00348         rColor aColor(0.0, 0.7, 0.5);
00349         if (!m.End())
00350         {
00351             m >> aColor.r_;
00352             m >> aColor.g_;
00353             m >> aColor.b_;
00354         }
00355         se_MakeColorValid(aColor.r_, aColor.g_, aColor.b_, 1.0f);
00356         shape->setColor(aColor);
00357 
00358         // read reference time and functions
00359         if (!m.End())
00360         {
00361             m >> referenceTime_;
00362             shape->setReferenceTime(referenceTime_);
00363             if (!m.End())
00364             {
00365                 tFunction aFunc;
00366                 m >> aFunc;
00367                 shape->setPosX(aFunc);
00368                 m >> aFunc;
00369                 shape->setPosY(aFunc);
00370                 m >> aFunc;
00371                 shape->setScale(aFunc);
00372             }
00373         }
00374         else
00375         {
00376             // Uses values from the eNetGameObject
00377             referenceTime_ = createTime_;
00378             shape->setReferenceTime(referenceTime_);
00379 
00380             tFunction aFunc;
00381             aFunc.SetOffset( pos.x );
00382             aFunc.SetSlope( 0 );
00383             shape->setPosX( aFunc );
00384 
00385             aFunc.SetOffset( pos.y );
00386             aFunc.SetSlope( 0 );
00387             shape->setPosY( aFunc );
00388 
00389             aFunc.SetOffset( sg_initialSize );
00390             aFunc.SetSlope( sg_expansionSpeed );
00391             shape->setScale( aFunc );
00392         }
00393 
00394         // read rotation speed
00395         tFunction rotationSpeed;
00396         if (!m.End())
00397         {
00398             m >> rotationSpeed;
00399         }
00400         else
00401         {
00402             // set fixed values
00403             rotationSpeed.SetOffset( .3f );
00404             rotationSpeed.SetSlope( 0.0f );
00405         }
00406         tPolynomial<nMessage> tpRotationSpeed(2);
00407         tpRotationSpeed[0] = rotationSpeed.GetOffset();
00408         tpRotationSpeed[1] = rotationSpeed.GetSlope();
00409         shape->setRotation2(tpRotationSpeed);
00410     }
00411     else
00412     {
00413         bool b;
00414 
00415         //        while(!m.End() ) { m >> b;}
00416 
00417         int count=44-16;
00418         // Discard the information
00419         while(!m.End() && count-->0) { m >> b;}
00420         unsigned short shapeID;
00421         m >> shapeID;
00422         if(sn_netObjects[shapeID]) {
00423             // zShape *asdf = dynamic_cast<zShape*>(&*sn_netObjects[shapeID]);
00424             shape = zShapePtr( dynamic_cast<zShape*>(&*sn_netObjects[shapeID]) );
00425         }
00426 
00427     }
00428 }
00429 
00430 // *******************************************************************************
00431 // *
00432 // *    Timestep
00433 // *
00434 // *******************************************************************************
00438 // *******************************************************************************
00439 
00440 bool zZone::Timestep( REAL time )
00441 {
00442     if(0 != shape) {
00443         shape->TimeStep( time );
00444     }
00445     /*
00446        if(!emulateOldZoneShape) {
00447            shape->TimeStep( time );
00448        }
00449        else { // Old representation of zone
00450        // rotate
00451        REAL speed = GetRotationSpeed();
00452        REAL angle = ( time - lastTime ) * speed;
00453        // angle /= ( 1 + 2 * 3.14159 * angle/sg_segments );
00454        rotation_ = rotation_.Turn( cos( angle ), sin( angle ) );
00455 
00456        // move to new position
00457        REAL dt = time - referenceTime_;
00458        Move( eCoord( posx_( dt ), posy_( dt ) ), lastTime, time );
00459        
00460 
00461        // kill this zone if it shrunk down to zero scale
00462        if ( GetExpansionSpeed() < 0 && GetScale() <= 0 )
00463        {
00464            OnVanish();
00465            return true;
00466        }
00467        }
00468        // update time
00469        */
00470     lastTime = time;
00471 
00472     return false;
00473 }
00474 
00475 // *******************************************************************************
00476 // *
00477 // *    OnVanish
00478 // *
00479 // *******************************************************************************
00482 // *******************************************************************************
00483 
00484 void zZone::OnVanish( void )
00485 {
00486 }
00487 
00488 // *******************************************************************************
00489 // *
00490 // *    InteractWith
00491 // *
00492 // *******************************************************************************
00498 // *******************************************************************************
00499 
00500 void zZone::InteractWith( eGameObject * target, REAL time, int recursion )
00501 {
00502     gCycle* prey = dynamic_cast< gCycle* >( target );
00503     if ( prey && 0 != shape)
00504     {
00505         if ( prey->Player() && prey->Alive() )
00506         {
00507             // Is the player inside or outside the zone
00508             if ( shape->isInteracting(target) == true )
00509             {
00510                 // If the player is not on the "inside" list, then he was outside
00511                 std::set<ePlayerNetID *>::iterator iter;
00512                 if ((iter = playersInside.find(prey->Player()) ) == playersInside.end()) {
00513                     playersInside.insert(prey->Player());
00514 
00515                     // Should the player not be marked as being outside
00516                     // avoid the OnEnter transition. This happens at game
00517                     // start-up for example, when players are neither inside nor outside
00518                     if( playersOutside.find(prey->Player()) != playersOutside.end() )
00519                     {
00520                         // Passing from outside to inside triggers the OnEnter event
00521                         OnEnter( prey, time );
00522                     }
00523                     // The player is no longer outside
00524                     playersOutside.erase(prey->Player());
00525                 }
00526                 // Being inside gives the OnInside event
00527                 OnInside( prey, time );
00528             }
00529             else {
00530                 // If the player is not on the "outside" list, then he was inside
00531                 std::set<ePlayerNetID *>::iterator iter;
00532                 if ((iter = playersOutside.find(prey->Player())) == playersOutside.end()) {
00533                     playersOutside.insert(prey->Player());
00534 
00535                     // Should the player not be marked as being inside
00536                     // avoid OnLeave transition. This happens at game
00537                     // start-up for example, when players are neither inside nor outside
00538                     if( playersInside.find(prey->Player()) != playersInside.end() )
00539                     {
00540                         // Passing from inside to outside triggers the OnLeave event
00541                         OnLeave( prey, time );
00542                     }
00543                     // The player is no longer inside
00544                     playersInside.erase(prey->Player());
00545                 }
00546                 // Being inside gives the OnOutside event
00547                 OnOutside( prey, time );
00548             }
00549         }
00550     }
00551 }
00552 
00553 REAL asdf[] = {0, 1};
00554 tPolynomial<nMessage> tpOne(asdf, sizeof(asdf)/sizeof(asdf[0]));
00555 // *******************************************************************************
00556 // *
00557 // *    OnEnter
00558 // *
00559 // *******************************************************************************
00564 // *******************************************************************************
00565 void zZone::OnEnter( gCycle * target, REAL time )
00566 {
00567     Triggerer triggerer;
00568     triggerer.who = target;
00569     triggerer.positive = _ignore;
00570     triggerer.marked = _ignore;
00571 
00572     zEffectGroupPtrs::const_iterator iter;
00573     for (iter = effectGroupEnter.begin();
00574             iter != effectGroupEnter.end();
00575             ++iter)
00576     {
00577         (*iter)->apply(triggerer, time, tpOne);
00578     }
00579 }
00580 
00581 void zZone::OnInside( gCycle * target, REAL time )
00582 {
00583     Triggerer triggerer;
00584     triggerer.who = target;
00585     triggerer.positive = _ignore;
00586     triggerer.marked = _ignore;
00587 
00588     zEffectGroupPtrs::const_iterator iter;
00589     for (iter = effectGroupInside.begin();
00590             iter != effectGroupInside.end();
00591             ++iter)
00592     {
00593         (*iter)->apply(triggerer, time, tpOne);
00594     }
00595 }
00596 void zZone::OnLeave( gCycle * target, REAL time )
00597 {
00598     Triggerer triggerer;
00599     triggerer.who = target;
00600     triggerer.positive = _ignore;
00601     triggerer.marked = _ignore;
00602 
00603     zEffectGroupPtrs::const_iterator iter;
00604     for (iter = effectGroupLeave.begin();
00605             iter != effectGroupLeave.end();
00606             ++iter)
00607     {
00608         (*iter)->apply(triggerer, time, tpOne);
00609     }
00610 }
00611 void zZone::OnOutside( gCycle * target, REAL time )
00612 {
00613     Triggerer triggerer;
00614     triggerer.who = target;
00615     triggerer.positive = _ignore;
00616     triggerer.marked = _ignore;
00617 
00618     zEffectGroupPtrs::const_iterator iter;
00619     for (iter = effectGroupOutside.begin();
00620             iter != effectGroupOutside.end();
00621             ++iter)
00622     {
00623         (*iter)->apply(triggerer, time, tpOne);
00624     }
00625 }
00626 
00627 // the zone's network initializator
00628 static nNOInitialisator<zZone> zone_init(341,"zonev2");
00629 
00630 // *******************************************************************************
00631 // *
00632 // *    CreatorDescriptor
00633 // *
00634 // *******************************************************************************
00638 // *******************************************************************************
00639 
00640 nDescriptor & zZone::CreatorDescriptor( void ) const
00641 {
00642     return zone_init;
00643 }
00644 
00645 /*
00646 // *******************************************************************************
00647 // *
00648 // *    Scale
00649 // *
00650 // *******************************************************************************
00654 // *******************************************************************************
00655 
00656 REAL zZone::Scale( void ) const
00657 {
00658     //    return GetScale();
00659     return shape->getScale();
00660 }
00661 */
00662 
00663 // *******************************************************************************
00664 // *
00665 // *    Render
00666 // *
00667 // *******************************************************************************
00671 // *******************************************************************************
00672 
00673 void zZone::Render( const eCamera * cam )
00674 {
00675     if (shape)
00676         shape->render(cam);
00677 }
00678 
00679 void zZone::Render2D( tCoord scale ) const {
00680     if (shape)
00681         shape->render2d(scale);
00682 }
00683 
00684 
00685 // *******************************************************************************
00686 // *
00687 // *    GetPosition
00688 // *
00689 // *******************************************************************************
00693 // *******************************************************************************
00694 
00695 eCoord zZone::GetPosition( void ) const
00696 {
00697     // HACK, to be implemented later and differently
00698     // Should get this info from the shape, not the zone
00699     eCoord ret;
00700     GetPosition( ret );
00701     return ret;
00702 }
00703 
00704 // *******************************************************************************
00705 // *
00706 // *    GetPosition
00707 // *
00708 // *******************************************************************************
00713 // *******************************************************************************
00714 
00715 zZone const & zZone::GetPosition( eCoord & position ) const
00716 {
00717     if(0 != shape) {
00718         position.x = EvaluateFunctionNow( shape->getPosX() );
00719         position.y = EvaluateFunctionNow( shape->getPosY() );
00720     }
00721     return *this;
00722 }
00723 
00724 // *******************************************************************************
00725 // *
00726 // *    GetScale
00727 // *
00728 // *******************************************************************************
00732 // *******************************************************************************
00733 
00734 REAL zZone::GetScale( void ) const
00735 {
00736     //    REAL ret = EvaluateFunctionNow( this->scale_ );
00737     //    ret = ret > 0 ? ret : 0;
00738 
00739 
00740     // HACK, to be implemented later and differently
00741     // Should get this info from the shape, not the zone
00742     REAL scale = 0.0;
00743     if(0 != shape) {
00744         scale = EvaluateFunctionNow( shape->getScale() ) ;
00745     }
00746     return scale;
00747 }
00748 
00749 // *******************************************************************************
00750 // *
00751 // *    SetReferenceTime
00752 // *
00753 // *******************************************************************************
00756 // *******************************************************************************
00757 
00758 void zZone::SetReferenceTime( void )
00759 {
00760     // set offsets to current values
00761     /*
00762       this->posx_.SetOffset( EvaluateFunctionNow( this->posx_ ) );
00763       this->posy_.SetOffset( EvaluateFunctionNow( this->posy_ ) );
00764       this->scale_.SetOffset( EvaluateFunctionNow( this->scale_ ) );
00765       this->rotationSpeed_.SetOffset( EvaluateFunctionNow( this->rotationSpeed_ ) );
00766     */
00767     // reset time
00768     this->referenceTime_ = lastTime;
00769 }
00770 
00771 // *******************************************************************************
00772 // *
00773 // *    GetRotation
00774 // *
00775 // *******************************************************************************
00779 // *******************************************************************************
00780 
00781 tCoord const zZone::GetRotation( void ) const
00782 {
00783     // HACK, to be implemented later and differently
00784     // Should get this info from the shape, not the zone
00785     return tCoord(0.0, 0.0);
00786 }
00787 
00788 // *******************************************************************************
00789 // *
00790 // *    GetColor
00791 // *
00792 // *******************************************************************************
00796 // *******************************************************************************
00797 
00798 rColor const  zZone::GetColor( void ) const
00799 {
00800     rColor color;
00801     if(0 != shape) {
00802         color = shape->getColor();
00803     }
00804     return color;
00805 }
00806 

Generated on Sat Mar 15 22:56:13 2008 for Armagetron Advanced by  doxygen 1.5.4