Sprite.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:9k
源码类别:

游戏

开发平台:

Visual C++

  1. // Sprite.cpp: implementation of the CSprite class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include <list>
  5. #include <algorithm>
  6. #include <assert.h>
  7. #include "DSUtil.h"
  8. #include "ddutil.h"
  9. #include "Sprite.h"
  10. using namespace std;
  11. extern CSoundManager* g_pSoundManager;
  12. //////////////////////////////////////////////////////////////////////
  13. // Construction/Destruction
  14. //////////////////////////////////////////////////////////////////////
  15. CSprite::CSprite():m_pfnDead(0),m_pfnKill(0)
  16. {
  17. m_Anim.m_bIsAnimBiDir = true;
  18. ::ZeroMemory(&m_CurrState, sizeof(SSTATE));
  19. }
  20. CSprite::~CSprite()
  21. {
  22. Destroy();
  23. }
  24. ////////////////////////////////////////////////////////////////////////
  25. // Create the sprite by giving it the Surface containing all the sprite
  26. // images.
  27. // Type is for storing game specific information like, this sprite is an
  28. // enemy or friend or food, etc.
  29. // Set the dimensions of the sprite
  30. /////////////////////////////////////////////////////////////////////////
  31. void CSprite::CreateSprite(CSurface** ppSurface, long nType,long nHeight, long nWidth)
  32. {
  33. m_ppSurface = ppSurface;
  34. m_nType = nType;
  35. m_Anim.m_nHeight = nHeight;
  36. m_Anim.m_nWidth = nWidth;
  37. }
  38. ///////////////////////////////////////////////////////////////////////////
  39. // Add a new state for the sprite
  40. // State could be like WALKING_UP or WALKING_DOWN or SHOOTING
  41. // Since sprite will have different animation sequence based on there state
  42. // this function can be used to give all the different things a sprite can do.
  43. // Parameters:
  44. //   nState is a user define value used to identify the state
  45. //   ptFrame is the x,y for of the first frame in the surface. 
  46. //             Since the dimentions are fixed we don't need that info here
  47. //   nNoOfFrames is the total animations frames this state has
  48. //   nDelay is to control the animation speed.
  49. //////////////////////////////////////////////////////////////////////////////
  50. void CSprite::AddState(long nState, POINT ptFrame, long nNoOfFrames, long nDelay, RECT* prcBound, LPTSTR pszSound, bool bLoopSound)
  51. {
  52. SSTATE State;
  53. State.m_nState = nState;
  54. State.m_ptFirstFrame = ptFrame;
  55. State.m_nNoOfFrames = nNoOfFrames;
  56. State.m_nDelay = nDelay;
  57. State.m_bLoopSound = bLoopSound;
  58. State.m_pSound=NULL;
  59. if (prcBound == NULL) {
  60. State.m_rcBounding.top = State.m_rcBounding.left=0;
  61. State.m_rcBounding.bottom=m_Anim.m_nHeight ;
  62. State.m_rcBounding.right= m_Anim.m_nWidth ;
  63. } else {
  64. State.m_rcBounding =*prcBound;
  65. }
  66. if (pszSound) {
  67. // Load the wave file into a DirectSound buffer
  68. g_pSoundManager->Create( &State.m_pSound, pszSound, 0, GUID_NULL );
  69. }
  70. m_StateList.push_back(State);
  71. }
  72. /////////////////////////////////////////////////////////////////////////
  73. // Check if the give rectangle intersects with any part of the sprite
  74. // This is used for collusion detection.
  75. ////////////////////////////////////////////////////////////////////////
  76. bool CSprite::IsHit(RECT rcRect)
  77. {
  78. if (m_CurrState.m_nState == ST_DEAD || m_CurrState.m_nState == ST_KILL)
  79. return false;
  80. RECT rcIntersect;
  81. RECT rcSprite= GetBoundingRect(m_ptLocation);
  82. return (::IntersectRect(&rcIntersect, &rcSprite, &rcRect) != 0);
  83. }
  84. ////////////////////////////////////////////////////////////////////////
  85. // Move sprite to new location
  86. ////////////////////////////////////////////////////////////////////////
  87. void CSprite::MoveTo(POINT ptNewLoc)
  88. {
  89. m_ptLocation = ptNewLoc;
  90. }
  91. ////////////////////////////////////////////////////////////////////
  92. // helper function of STL find 
  93. ///////////////////////////////////////////////////////////////////
  94. bool CSprite::SSTATE::operator==( const long& nState)
  95. {
  96. return m_nState == nState;
  97. }
  98. //////////////////////////////////////////////////////////////////
  99. // Set the state of the sprite
  100. //////////////////////////////////////////////////////////////////
  101. void CSprite::SetState(long nState, bool bForceState)
  102. {
  103. if (m_CurrState.m_nState == nState)
  104. return;
  105. if (m_CurrState.m_nState == ST_KILL && bForceState == false)
  106. return;
  107. if (m_CurrState.m_pSound) {
  108. m_CurrState.m_pSound->Stop();
  109. }
  110. if(nState == ST_KILL && m_pfnKill) {
  111. if (((*m_pfnKill)(this)) == false)
  112. return;
  113. }
  114. list<SSTATE>::iterator iState = find(m_StateList.begin(), m_StateList.end(), nState);
  115. assert(*iState == nState);
  116. m_CurrState = *iState;
  117. m_Anim.m_nCurrFrame = 0;
  118. m_Anim.m_nCurrDelay = m_CurrState.m_nDelay;
  119. m_Anim.m_bIsAnimForward = true;
  120. if (m_CurrState.m_pSound) {
  121. DWORD dwFlags = m_CurrState.m_bLoopSound ? DSBPLAY_LOOPING : 0L;
  122. m_CurrState.m_pSound->Play( 0, dwFlags ) ;
  123. }
  124. }
  125. void CSprite::Update()
  126. {
  127. if (m_CurrState.m_nState == ST_DEAD) 
  128. return;
  129. // If m_Movement.m_nPathFindDelay = 0 then path is only updated
  130. // when a collision occurs.
  131. if (m_Movement.m_pfnFindPath && m_Movement.m_nPathFindDelay != 0) {
  132. if (m_Movement.m_nCurrPathFindDelay) {
  133. --m_Movement.m_nCurrPathFindDelay;
  134. } else {
  135. m_Movement.m_nCurrPathFindDelay = m_Movement.m_nPathFindDelay;
  136. (*m_Movement.m_pfnFindPath)(this);
  137. }
  138. }
  139. if (m_CurrState.m_nState == ST_KILL) {
  140. m_Movement.m_dx =0;
  141. m_Movement.m_dy =0;
  142. }
  143. if (m_Movement.m_pfnCollision) {
  144. if (m_Movement.m_nCurrMoveDelay)
  145. --m_Movement.m_nCurrMoveDelay;
  146. else {
  147. m_Movement.m_nCurrMoveDelay = m_Movement.m_nMoveDelay;
  148. POINT pt = m_ptLocation;
  149. pt.x += m_Movement.m_dx;
  150. pt.y += m_Movement.m_dy;
  151. // Check for collision at the new location
  152. // If is has collided  call path find function 
  153. // for new direction.
  154. if ((*m_Movement.m_pfnCollision)(GetBoundingRect(pt))) {
  155. if (m_Movement.m_pfnFindPath) {
  156. (*m_Movement.m_pfnFindPath)(this);
  157. }
  158. } else {
  159. m_ptLocation = pt;
  160. }
  161. }
  162. }
  163. if (m_Anim.m_nCurrDelay) {
  164. --m_Anim.m_nCurrDelay;
  165. return;
  166. }
  167. m_Anim.m_nCurrDelay = m_CurrState.m_nDelay;
  168. if (m_CurrState.m_nNoOfFrames == 1) {
  169. if (m_CurrState.m_nState == ST_KILL) {
  170. m_CurrState.m_nState = ST_DEAD;
  171. if (m_pfnDead) 
  172. (*m_pfnDead)(this);
  173. }
  174. return;
  175. }
  176. if (m_Anim.m_bIsAnimBiDir) {
  177. if (m_Anim.m_bIsAnimForward) {
  178. if ( m_Anim.m_nCurrFrame == m_CurrState.m_nNoOfFrames - 1) {
  179. m_Anim.m_bIsAnimForward = false;
  180. if (m_CurrState.m_nState == ST_KILL) {
  181. m_CurrState.m_nState = ST_DEAD;
  182. if (m_pfnDead)  {
  183. (*m_pfnDead)(this);
  184. return;
  185. }
  186. }
  187. --m_Anim.m_nCurrFrame;
  188. }
  189. else
  190. ++m_Anim.m_nCurrFrame;  // Move to the last frame
  191. } else {
  192. if ( m_Anim.m_nCurrFrame == 0) {
  193. m_Anim.m_bIsAnimForward = true;
  194. ++m_Anim.m_nCurrFrame;
  195. }
  196. else
  197. --m_Anim.m_nCurrFrame;
  198. }
  199. } else {
  200. if ( ++m_Anim.m_nCurrFrame == m_CurrState.m_nNoOfFrames) {
  201. m_Anim.m_nCurrFrame = 0;
  202. if (m_CurrState.m_nState == ST_KILL) {
  203. m_CurrState.m_nState = ST_DEAD;
  204. if (m_pfnDead) 
  205. (*m_pfnDead)(this);
  206. }
  207. }
  208. }
  209. }
  210. void CSprite::Draw(LPDIRECTDRAWSURFACE7 pdds)
  211. {
  212. if (m_CurrState.m_nState == ST_DEAD)
  213. return;
  214. RECT rcFrame = { m_CurrState.m_ptFirstFrame.x + (m_Anim.m_nCurrFrame * m_Anim.m_nWidth), 
  215. m_CurrState.m_ptFirstFrame.y,
  216. m_CurrState.m_ptFirstFrame.x + (m_Anim.m_nCurrFrame * m_Anim.m_nWidth) + m_Anim.m_nWidth,
  217. m_CurrState.m_ptFirstFrame.y + m_Anim.m_nHeight };
  218. if (m_Movement.m_nInvulnerable)
  219. m_Movement.m_nInvulnerable--;
  220. if ((m_Movement.m_nInvulnerable % 2)==0) {
  221. pdds->BltFast(m_ptLocation.x, m_ptLocation.y, (*m_ppSurface)->GetDDrawSurface(), &rcFrame, DDBLTFAST_SRCCOLORKEY);
  222. }
  223. if (m_bDrawBorder) {
  224. CSurface Surface;
  225. rcFrame.left = m_ptLocation.x; rcFrame.top = m_ptLocation.y ; 
  226. rcFrame.right= m_ptLocation.x + m_Anim.m_nWidth; rcFrame.bottom =m_ptLocation.y + m_Anim.m_nHeight;
  227. Surface.Create(pdds);
  228. Surface.DrawRect(rcFrame, RGB(0,255,0));
  229. Surface.DrawRect(GetBoundingRect(m_ptLocation), RGB(0,255,0));
  230. }
  231. }
  232. RECT CSprite::GetRect()
  233. {
  234. RECT rcRect = { m_ptLocation.x, m_ptLocation.y, m_ptLocation.x + m_Anim.m_nWidth, m_ptLocation.y + m_Anim.m_nHeight };
  235. return rcRect;
  236. }
  237. void CSprite::MoveTo(long nX, long nY)
  238. {
  239. m_ptLocation.x = nX;
  240. m_ptLocation.y = nY;
  241. }
  242. long& CSprite::GetState()
  243. {
  244. return m_CurrState.m_nState;
  245. }
  246. void CSprite::EnableBorder(bool bDraw)
  247. {
  248. m_bDrawBorder = bDraw;
  249. }
  250. void CSprite::SetAnimBiDir(bool bIsAnimBiDir)
  251. {
  252. m_Anim.m_bIsAnimBiDir = bIsAnimBiDir;
  253. }
  254. RECT CSprite::GetBoundingRect(POINT &ptLoc)
  255. {
  256. RECT rcBound;
  257. rcBound.left =  ptLoc.x + m_CurrState.m_rcBounding.left; 
  258. rcBound.top  = ptLoc.y + m_CurrState.m_rcBounding.top; 
  259. rcBound.right = rcBound.left + m_CurrState.m_rcBounding.right;
  260. rcBound.bottom= rcBound.top + m_CurrState.m_rcBounding.bottom ;
  261. return rcBound;
  262. }
  263. const long& CSprite::GetType()
  264. {
  265. return m_nType;
  266. }
  267. void CSprite::Destroy()
  268. {
  269. list<SSTATE>::iterator iState;
  270.     for ( iState = m_StateList.begin(); iState != m_StateList.end(); iState++) {
  271. if (iState->m_pSound) {
  272. delete iState->m_pSound;
  273. iState->m_pSound = NULL;
  274. }
  275. }
  276.    m_StateList.erase(m_StateList.begin(),m_StateList.end());
  277. }