Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

321 lines
7.8 KiB

  1. /*************************************************
  2. * sprite.cpp *
  3. * *
  4. * Copyright (C) 1995-1999 Microsoft Inc. *
  5. * *
  6. *************************************************/
  7. // sprite.cpp : implementation file
  8. //
  9. #include "stdafx.h"
  10. #include "dib.h"
  11. #include "spriteno.h"
  12. #include "sprite.h"
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char BASED_CODE THIS_FILE[] = __FILE__;
  16. #endif
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CSprite
  19. IMPLEMENT_SERIAL(CSprite, CDIB, 0 /* schema number*/ )
  20. CSprite::CSprite()
  21. {
  22. m_x = 0;
  23. m_y = 0;
  24. m_z = 50;
  25. m_bTransIndex = 0;
  26. m_pNotifyObj = NULL;
  27. }
  28. CSprite::~CSprite()
  29. {
  30. }
  31. // Set the initial state of the sprite from its DIB image
  32. void CSprite::Initialize()
  33. {
  34. // Get the address of the top, left pixel
  35. BYTE* p = (BYTE*)GetPixelAddress(0, 0);
  36. ASSERT(p);
  37. if ( p == NULL )
  38. {
  39. m_bTransIndex = 0;
  40. return;
  41. }
  42. // get the pixel value and save it
  43. m_bTransIndex = *p;
  44. }
  45. /////////////////////////////////////////////////////////////////////////////
  46. // CSprite serialization
  47. void CSprite::Serialize(CArchive& ar)
  48. {
  49. CDIB::Serialize(ar);
  50. if (ar.IsStoring()) {
  51. ar << (DWORD) m_x;
  52. ar << (DWORD) m_y;
  53. ar << (DWORD) m_z;
  54. } else {
  55. DWORD dw;
  56. ar >> dw; m_x = (int) dw;
  57. ar >> dw; m_y = (int) dw;
  58. ar >> dw; m_z = (int) dw;
  59. // now generate the other parameters from the DIB
  60. Initialize();
  61. }
  62. }
  63. /////////////////////////////////////////////////////////////////////////////
  64. // CSprite commands
  65. // Render a sprite to a DIB
  66. void CSprite::Render(CDIB* pDIB, CRect* pClipRect)
  67. {
  68. ASSERT(pDIB);
  69. // Get the sprite rectangle
  70. CRect rcDraw;
  71. GetRect(&rcDraw);
  72. // If a clip rectangle was supplied, see if the sprite
  73. // is visible in the rectangle
  74. if (pClipRect) {
  75. if (!rcDraw.IntersectRect(pClipRect, &rcDraw)) {
  76. return; // not visible
  77. }
  78. }
  79. // Copy the image of the sprite
  80. CopyBits(pDIB, // dest DIB
  81. rcDraw.left, // dest x
  82. rcDraw.top, // dest y
  83. rcDraw.right - rcDraw.left, // width
  84. rcDraw.bottom - rcDraw.top, // height
  85. rcDraw.left - m_x, // source x
  86. rcDraw.top - m_y, // source y
  87. PALETTEINDEX(m_bTransIndex)); // trans color index
  88. }
  89. void PrintRGB(CDIB* pDib,int n)
  90. {
  91. RGBQUAD *prgb = pDib->GetClrTabAddress();
  92. TRACE("%d>(%d,%d,%d)\n",n,prgb[n].rgbBlue, prgb[n].rgbGreen, prgb[n].rgbRed);
  93. }
  94. void Copy(CDIB* pdibSrc,CDIB* pdibDest,
  95. int xd, int yd,
  96. int w, int h,
  97. int xs, int ys,
  98. COLORREF clrTrans)
  99. {
  100. ASSERT(pdibDest);
  101. // test for strange cases
  102. if (w == 0 || h == 0) return;
  103. // get pointers to the start points in the source
  104. // and destination DIBs. Note that this will be the bottom left
  105. // corner of the DIB as the scan lines are reversed in memory
  106. BYTE* pSrc = (BYTE*)(pdibSrc->GetPixelAddress(xs, ys + h - 1));
  107. ASSERT(pSrc);
  108. BYTE* pDest = (BYTE*)pdibDest->GetPixelAddress(xd, yd + h - 1);
  109. ASSERT(pDest);
  110. // get the scan line widths of each DIB
  111. int iScanS = pdibSrc->StorageWidth();
  112. int iScanD = pdibDest->StorageWidth();
  113. RGBQUAD *prgbSrc = pdibSrc->GetClrTabAddress();
  114. RGBQUAD *prgbDest = pdibDest->GetClrTabAddress();
  115. {
  116. // copy lines with transparency
  117. // We only accept a PALETTEINDEX description
  118. // for the color definition
  119. BYTE bTransClr = LOBYTE(LOWORD(clrTrans));
  120. int iSinc = iScanS - w; // source inc value
  121. int iDinc = iScanD - w; // dest inc value
  122. int iCount;
  123. BYTE pixel;
  124. while (h--) {
  125. iCount = w; // no of pixels to scan
  126. while (iCount--) {
  127. pixel = *pSrc++;
  128. // only copy pixel if not transparent
  129. if (pixel != bTransClr) {
  130. {
  131. *pDest++ = 1;
  132. }
  133. } else {
  134. pDest++;
  135. }
  136. }
  137. // move on to the next line
  138. pSrc += iSinc;
  139. pDest += iDinc;
  140. }
  141. }
  142. }
  143. void CSprite::Coverage(CDIB* pDIB)
  144. {
  145. ASSERT(pDIB);
  146. // Get the sprite rectangle
  147. CRect rcDraw;
  148. GetRect(&rcDraw);
  149. // Copy the image of the sprite
  150. Copy(this,pDIB, // dest DIB
  151. 0, // dest x
  152. 0, // dest y
  153. DibWidth(), // width
  154. DibHeight(), // height
  155. 0, // source x
  156. 0, // source y
  157. PALETTEINDEX(m_bTransIndex)); // trans color index
  158. }
  159. // Load a sprite image from a disk file
  160. BOOL CSprite::Load(CBitmap* pBmp)
  161. {
  162. if (!CDIB::Load(pBmp)) {
  163. return FALSE;
  164. }
  165. Initialize();
  166. return TRUE;
  167. }
  168. BOOL CSprite::Load(char* pszFileName)
  169. {
  170. if (!CDIB::Load(pszFileName)) {
  171. return FALSE;
  172. }
  173. Initialize();
  174. /*
  175. {
  176. BYTE* pBits = NULL;
  177. HBITMAP hBmp;
  178. CDC* pDC = GetDC();
  179. hBmp = CreateDIBSection(pDC->GetSafeHdc(),
  180. pBmpInfo,
  181. DIB_PAL_COLORS,
  182. (VOID **) &pBits,
  183. NULL,
  184. 0);
  185. ReleaseDC(pDC);
  186. Create(GetWidth
  187. }
  188. */
  189. return TRUE;
  190. }
  191. // Load a sprite image from a disk file
  192. BOOL CSprite::Load(CFile *fp)
  193. {
  194. if (!CDIB::Load(fp)) {
  195. return FALSE;
  196. }
  197. Initialize();
  198. return TRUE;
  199. }
  200. // Map colors to palette
  201. BOOL CSprite::MapColorsToPalette(CPalette *pPal)
  202. {
  203. BOOL bResult = CDIB::MapColorsToPalette(pPal);
  204. // get the transparency info again
  205. // Note: local call only don't any derived class
  206. CSprite::Initialize();
  207. return bResult;
  208. }
  209. // get the bounding rectangle
  210. void CSprite::GetRect(CRect* pRect)
  211. {
  212. ASSERT(pRect);
  213. pRect->left = m_x;
  214. pRect->top = m_y;
  215. pRect->right = m_x + GetWidth();
  216. pRect->bottom = m_y + GetHeight();
  217. }
  218. // Test for a hit in a non-transparent area
  219. BOOL CSprite::HitTest(CPoint point)
  220. {
  221. // Test if the point is inside the sprite rectangle
  222. if ((point.x > m_x)
  223. && (point.x < m_x + GetWidth())
  224. && (point.y > m_y)
  225. && (point.y < m_y + GetHeight())) {
  226. // See if this point is transparent by testing to
  227. // see if the pixel value is the same as the top
  228. // left corner value. Note that top left of the
  229. // image is bottom left in the DIB.
  230. BYTE* p = (BYTE*)GetPixelAddress(point.x - m_x, point.y - m_y);
  231. if (( p != NULL ) && (*p != m_bTransIndex) ) {
  232. return TRUE; // hit
  233. }
  234. }
  235. return FALSE;
  236. }
  237. void CSprite::Disappear()
  238. {
  239. CRect rcOld;
  240. GetRect(&rcOld);
  241. if (m_pNotifyObj)
  242. {
  243. m_pNotifyObj->Change(this,
  244. CSpriteNotifyObj::IMAGE,
  245. &rcOld,
  246. NULL);
  247. }
  248. }
  249. // set a new x,y position
  250. void CSprite::SetPosition(int x, int y)
  251. {
  252. // Save the current position
  253. CRect rcOld;
  254. GetRect(&rcOld);
  255. // move to new position
  256. m_x = x;
  257. m_y = y;
  258. CRect rcNew;
  259. GetRect(&rcNew);
  260. // notify that we have moved from our old position to
  261. // our new position
  262. if (m_pNotifyObj) {
  263. m_pNotifyObj->Change(this,
  264. CSpriteNotifyObj::POSITION,
  265. &rcOld,
  266. &rcNew);
  267. }
  268. }
  269. // Set a new Z order
  270. void CSprite::SetZ(int z)
  271. {
  272. if (m_z != z) {
  273. m_z = z;
  274. // See if we have to notify anyone
  275. if (m_pNotifyObj) {
  276. CRect rc;
  277. GetRect(&rc);
  278. m_pNotifyObj->Change(this,
  279. CSpriteNotifyObj::ZORDER,
  280. &rc);
  281. }
  282. }
  283. }