home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / IKLOWNS / CGCHAR.CPP < prev    next >
C/C++ Source or Header  |  1996-08-28  |  9KB  |  353 lines

  1. /*===========================================================================*\
  2. |
  3. |  File:        cgchar.cpp
  4. |
  5. |  Description: 
  6. |       
  7. |-----------------------------------------------------------------------------
  8. |
  9. |  Copyright (C) 1995-1996 Microsoft Corporation.  All Rights Reserved.
  10. |
  11. |  Written by Moss Bay Engineering, Inc. under contract to Microsoft Corporation
  12. |
  13. \*===========================================================================*/
  14.  
  15. /**************************************************************************
  16.  
  17.     (C) Copyright 1995-1996 Microsoft Corp.  All rights reserved.
  18.  
  19.     You have a royalty-free right to use, modify, reproduce and 
  20.     distribute the Sample Files (and/or any modified version) in 
  21.     any way you find useful, provided that you agree that 
  22.     Microsoft has no warranty obligations or liability for any 
  23.     Sample Application Files which are modified. 
  24.  
  25.     we do not recomend you base your game on IKlowns, start with one of
  26.     the other simpler sample apps in the GDK
  27.  
  28.  **************************************************************************/
  29.  
  30. #include <windows.h>
  31. #ifdef __WATCOMC__
  32. #include <mem.h>
  33. #else
  34. #include <memory.h>
  35. #endif
  36. #include "cgdebug.h"
  37. #include "cgglobl.h"
  38. #include "cgtimer.h"
  39. #include "cginput.h"
  40. #include "cgchar.h"
  41. #include "cgchdll.h"
  42. #include "cgchrint.h"
  43. #include "cgload.h"
  44. #include "cgremote.h"
  45. #include "strrec.h"
  46.  
  47. extern void dbgprintf(char *, ...);
  48. extern CLoadingScreen *gLoadingScreen;
  49.  
  50. static int DefaultCharacterAction (CGameCharacter *me, CGameLevel *level)
  51. {
  52.     // move to next sprite sequence...
  53.     me->NextSprite(level->GetFrameTime());
  54.  
  55.     // always stays in state 0 ...
  56.     return(0);
  57. }
  58.  
  59. static int DefaultCharacterCollide (CGameCharacter *me, CGameCharacter *other, CGameLevel *level)
  60. {
  61.     // what to do if we collided????
  62.     return(ACTION_COMPLETED);
  63. }
  64.  
  65. /*---------------------------------------------------------------------------*\
  66. |
  67. |       Class CGameCharacter
  68. |
  69. |  DESCRIPTION:
  70. |
  71. |
  72. |
  73. \*---------------------------------------------------------------------------*/
  74. CGameCharacter::CGameCharacter(
  75.     char* pFileName,
  76.     char* pCharName,
  77.     char* pGraphicKey,
  78.     CGameLevel *pLevel,
  79.     int minz,
  80.     int maxz,
  81.     int startx,
  82.     int starty,
  83.     void *pNewObjID,
  84.     char *pRemoteName
  85.     ) : CGameGraphic( minz ),
  86.         mpActions( NULL ),
  87.         mpName( NULL ),
  88.         mNumActions( 0 ),
  89.         mpCurAction( NULL ),
  90.         mCurSubX( 0 ),
  91.         mCurSubY( 0 ),
  92.         mVelocityX( 0 ),
  93.         mVelocityY( 0 ),
  94.         mLastTime( -1 )
  95. {
  96.     static DWORD gObjInstance=0;
  97.     // hook into the character DLL (or built-in) functionality, if present
  98.     // note: if nothing is found, then we'll use *default* actions!
  99.     mpLevel = pLevel;
  100.     mpName = new char[lstrlen( pCharName ) + 1];
  101.     lstrcpy( mpName, pCharName );
  102.  
  103.     mpCharInfo = FindCharInfo(pCharName);
  104.     if (mpCharInfo)
  105.     {
  106.         mpCharInfo->Create(this, pLevel);
  107.         pCollideFunc = mpCharInfo->Collide;
  108.         mNumActions = mpCharInfo->NumSequences;
  109.     }
  110.     else
  111.     {
  112.         pActFunc = DefaultCharacterAction;
  113.         pCollideFunc = DefaultCharacterCollide;
  114.         mNumActions = 1;
  115.     }
  116.  
  117.     // now that we know how many actions there are, allocate our array 
  118.     mpActions = new CGameAction *[mNumActions];
  119.  
  120.     char    *actionBuf;
  121.     char    defAction[] = "";       // no default action names
  122.  
  123.     if (mpCharInfo)
  124.     {
  125.         int ix = 0;
  126.         for ( ix = 0; ix < mNumActions ; ix++ ) 
  127.         {
  128.             if (gLoadingScreen != NULL)
  129.                 gLoadingScreen->Update();
  130.  
  131.             mpActions[ix] = new CGameAction( pFileName, &(mpCharInfo->Sequences[ix])
  132.             , (DWORD)this );
  133.         }
  134.     }
  135.     else
  136.     {
  137.         actionBuf = new char [32 * mNumActions];
  138.         GetPrivateProfileString( 
  139.             pCharName,
  140.             NULL,       // grab all the key names
  141.             defAction,
  142.             actionBuf,
  143.             32 * mNumActions,
  144.             pFileName
  145.              );
  146.  
  147.         int ix = 0;
  148.         for ( char *pAction = actionBuf; *pAction && ( ix < mNumActions ); pAction++, ix++ ) {
  149.             if (gLoadingScreen != NULL)
  150.                 gLoadingScreen->Update();
  151.             mpActions[ix] = new CGameAction( pFileName, pAction
  152.             , (DWORD)this );
  153.             pAction += lstrlen( pAction );  // move beyond terminator
  154.         }
  155.  
  156.         delete [] actionBuf;
  157.     }
  158.  
  159.     // Initialize remote stuff
  160.     pObjID = (REMOTE_OBJECT *)pNewObjID;
  161.     pActionQueue = NULL;
  162.     fRemote = FALSE;
  163.     if (mpCharInfo)
  164.     {
  165.         if (pObjID != NULL)
  166.         {
  167.             fRemote = TRUE;
  168.             pActFunc = mpCharInfo->RemoteAction;
  169.             
  170.             // Create an action queue
  171.             pActionQueue = CreateRemoteObjectQueue(pObjID, (void *)this);
  172.  
  173.         } else {
  174.             if (mpCharInfo->RemoteAction != NULL)
  175.             {
  176.                 if (pRemoteName == NULL)
  177.                     pRemoteName = pCharName;
  178.  
  179.                 pObjID = CreateRemotePeers(pRemoteName, gObjInstance++);
  180.             }
  181.             pActFunc = mpCharInfo->Action;
  182.         }
  183.     }
  184.  
  185.     mMaxZ = maxz;
  186.     mMinZ = minz;
  187.     mCurZ = (mMaxZ+mMinZ)/2;
  188.  
  189.     mpCurAction = mpActions[0];
  190.     curState = -1;
  191.     MoveTo(startx, starty);
  192. }
  193.  
  194. CGameCharacter::~CGameCharacter()
  195. {
  196.     if (fRemote)
  197.     {
  198.         // Get rid of the action queue
  199.         DestroyRemoteObjectQueue(pObjID);
  200.     }
  201.     else 
  202.     {
  203.             DestroyRemotePeer(pObjID);
  204.     }
  205.  
  206.     // delete all the action objects
  207.     for ( ; mNumActions > 0; mNumActions-- ) 
  208.     {
  209.         delete  mpActions[mNumActions - 1];
  210.     }
  211.  
  212.     delete[] mpActions;
  213.     delete[] mpName;
  214. }
  215.  
  216. void CGameCharacter::Update(
  217.     CGameLevel* pLevel,
  218.     CGameUpdateList* pList      // we add to this if we move
  219.     )
  220. {
  221.     if (mpNext)
  222.         mpNext->Update(pLevel, pList);
  223.  
  224.     CGameAction* mpPrevAction = mpCurAction;
  225.  
  226.     int newState = (pActFunc)(this, pLevel);
  227.  
  228.     // set new state
  229.     if (newState != -1)
  230.     {
  231.         // don't change state if out of bounds!
  232.         if (newState >= mNumActions)
  233.         {
  234.             newState = curState;
  235.         }
  236.  
  237.         if (newState >= 0)
  238.             mpCurAction = mpActions[newState];
  239.     }
  240.  
  241.     // See if this is a new action we've entered into.
  242.     if (newState != curState)
  243.     {
  244.         mpPrevAction->DeActivate();
  245.         curState = newState;
  246.         if (curState != -1 && curState != -2)
  247.         {
  248.             mpCurAction->Activate();
  249.         }
  250.     }
  251.  
  252.     //if (mpCurAction != NULL)
  253.     mpCurAction->Update(pLevel->World2ScreenX(SUB2WORLD(mCurSubX), mXParallax));
  254.  
  255.     if (newState == -1)
  256.     {
  257.         // kill me
  258.         Destroy(this, pLevel);
  259.         pLevel->Remove(this);
  260.     }
  261. }
  262.  
  263. // display the character in its position on given screen with given screen offset
  264. void
  265. CGameCharacter::Render(
  266.     CGameLevel* pLevel,
  267.     CGameScreen* pScreen,
  268.     CGameUpdateList* pList
  269.     )
  270. {
  271.     if (mpNext)
  272.     {
  273.         // recurse down the list to get background filled in
  274.         mpNext->Render(pLevel, pScreen, pList);
  275.     }
  276.  
  277.     RECT update;
  278.  
  279.     // only draw if we're in the invalid list:
  280.     if (IntersectRect( &update, pList->GetDirtyRect(), &mRect))
  281.     {
  282.         mpCurAction->Render(
  283.                 pScreen,
  284.                 pLevel->World2ScreenX(SUB2WORLD(mCurSubX), mXParallax),
  285.                 pLevel->World2ScreenY(SUB2WORLD(mCurSubY), mYParallax),
  286.                 FALSE,  // don't ever reverse the image
  287.                 FALSE,
  288.                 pList->GetDirtyRect()
  289.                 );
  290.     }
  291. }   
  292.  
  293. void
  294. CGameCharacter::MoveTo( int worldX, int worldY )
  295. {
  296.     mpLevel->AddInvalidRect(&mRect);
  297.  
  298.     mCurSubX = WORLD2SUB(worldX);
  299.     mCurSubY = WORLD2SUB(worldY);
  300.  
  301.     mRect.left = mpLevel->World2ScreenX(worldX, mXParallax);
  302.     mRect.top = mpLevel->World2ScreenY(worldY, mYParallax);
  303.     mRect.right = mRect.left + GetCurWidth() - 1;
  304.     mRect.bottom = mRect.top + GetCurHeight() - 1;
  305.  
  306.     mpLevel->AddInvalidRect(&mRect);
  307. }
  308.  
  309. int
  310. CGameCharacter::NextSprite(
  311.     int time,   // current game time
  312.     BOOL wrap   // should sequence wrap around?
  313.     )
  314. {
  315.     mpLevel->AddInvalidRect(&mRect);
  316.     int result = mpCurAction->NextSprite(time, wrap);
  317.  
  318.     // need to recalculate screen position in case screen moved
  319.     mRect.left = mpLevel->World2ScreenX(SUB2WORLD(mCurSubX), mXParallax);
  320.     mRect.top = mpLevel->World2ScreenY(SUB2WORLD(mCurSubY), mYParallax);
  321.     mRect.right = mRect.left + GetCurWidth() - 1;
  322.     mRect.bottom = mRect.top + GetCurHeight() - 1;
  323.  
  324.     mpLevel->AddInvalidRect(&mRect);
  325.  
  326.     return result;
  327. }
  328.  
  329. int CGameCharacter::GetRemoteAction(
  330.     void *&Data,
  331.     DWORD &DataSize
  332. )
  333. {
  334.     return(GetNextRemoteAction(pActionQueue, Data, DataSize));
  335. }   
  336.  
  337. int CGameCharacter::TransmitRemoteAction(
  338.     int action, 
  339.     void *Data, 
  340.     DWORD DataSize
  341. )
  342. {
  343.     SendRemoteAction(pObjID, action, Data, DataSize);
  344.     return(0);
  345. }   
  346.  
  347. void CGameCharacter::ReleaseRemoteAction(
  348.     void    *Data
  349. )
  350. {
  351.     ReleaseRemoteData(Data);
  352. }
  353.