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.

792 lines
16 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (c) 1995 - 1997 Microsoft Corporation. All Rights Reserved.
  4. * Copyright (C) 1994-1995 ATI Technologies Inc. All Rights Reserved.
  5. *
  6. * File: sprite.c
  7. * Content: sprite manipulation functions
  8. *
  9. ***************************************************************************/
  10. #include "foxbear.h"
  11. /*
  12. * CreateSprite
  13. */
  14. HSPRITE *CreateSprite (
  15. USHORT bitmapCount,
  16. LONG x,
  17. LONG y,
  18. USHORT width,
  19. USHORT height,
  20. USHORT xmax,
  21. USHORT ymax,
  22. SHORT as,
  23. BOOL active )
  24. {
  25. HSPRITE *hSprite;
  26. USHORT i;
  27. hSprite = MemAlloc( sizeof (HSPRITE) );
  28. if( hSprite == NULL )
  29. {
  30. ErrorMessage( "hSprite in CreateSprite" );
  31. }
  32. hSprite->hSBM = CMemAlloc( bitmapCount, sizeof (HSPRITE_BM) );
  33. if( hSprite->hSBM == NULL )
  34. {
  35. MemFree( hSprite );
  36. ErrorMessage( "hSprite->hSBM in CreateSprite" );
  37. }
  38. hSprite->active = active;
  39. hSprite->bitmapCount = bitmapCount;
  40. hSprite->x = x;
  41. hSprite->y = y;
  42. hSprite->width = width;
  43. hSprite->height = height;
  44. hSprite->xv = 0;
  45. hSprite->yv = 0;
  46. hSprite->xa = 0;
  47. hSprite->ya = 0;
  48. hSprite->xmax = xmax;
  49. hSprite->ymax = ymax;
  50. hSprite->absSwitch = as;
  51. hSprite->relSwitch = 0;
  52. hSprite->switchType = HOR;
  53. hSprite->switchForward = TRUE;
  54. hSprite->switchDone = FALSE;
  55. for( i = 0; i < bitmapCount; ++i )
  56. {
  57. hSprite->hSBM[i].hBM = NULL;
  58. }
  59. return hSprite;
  60. } /* CreateSprite */
  61. /*
  62. * BitBltSprite
  63. */
  64. BOOL BitBltSprite (
  65. HSPRITE *hSprite,
  66. GFX_HBM hBM,
  67. ACTION action,
  68. DIRECTION direction,
  69. SHORT x,
  70. SHORT y,
  71. USHORT w,
  72. USHORT h )
  73. {
  74. USHORT count;
  75. if( hSprite == NULL )
  76. {
  77. ErrorMessage( "hSprite in BitBltSprite" );
  78. }
  79. if( hBM == NULL )
  80. {
  81. ErrorMessage( "hBM in BitBltSprite" );
  82. }
  83. if( (x >= hSprite->width) || (y >= hSprite->height) )
  84. {
  85. ErrorMessage( "x or y in BitBltSprite" );
  86. }
  87. count = 0;
  88. while( hSprite->hSBM[count].hBM != NULL )
  89. {
  90. count++;
  91. if( count >= hSprite->bitmapCount )
  92. {
  93. ErrorMessage( "Bitmap overflow in BitBltSprite" );
  94. }
  95. }
  96. hSprite->hSBM[count].hBM = hBM;
  97. hSprite->hSBM[count].action = action;
  98. hSprite->hSBM[count].direction = direction;
  99. hSprite->hSBM[count].x = x;
  100. hSprite->hSBM[count].y = y;
  101. hSprite->hSBM[count].width = w;
  102. hSprite->hSBM[count].height = h;
  103. return TRUE;
  104. } /* BitBltSprite */
  105. /*
  106. * SetSpriteAction
  107. */
  108. BOOL SetSpriteAction ( HSPRITE *hSprite, ACTION action, DIRECTION direction )
  109. {
  110. USHORT c;
  111. c = 0;
  112. if( direction == SAME )
  113. {
  114. direction = hSprite->currentDirection;
  115. }
  116. while( (hSprite->hSBM[c].action != action) || (hSprite->hSBM[c].direction != direction) )
  117. {
  118. ++c;
  119. }
  120. hSprite->currentAction = action;
  121. hSprite->currentDirection = direction;
  122. hSprite->currentBitmap = c;
  123. hSprite->relSwitch = 0;
  124. return TRUE;
  125. } /* SetSpriteAction */
  126. /*
  127. * ChangeSpriteDirection
  128. */
  129. BOOL ChangeSpriteDirection( HSPRITE *hSprite )
  130. {
  131. DIRECTION direction;
  132. if( hSprite->currentDirection == RIGHT )
  133. {
  134. direction = LEFT;
  135. }
  136. else
  137. {
  138. direction = RIGHT;
  139. }
  140. SetSpriteAction( hSprite, hSprite->currentAction, direction );
  141. return TRUE;
  142. } /* ChangeSpriteDirection */
  143. /*
  144. * GetSpriteAction
  145. */
  146. ACTION GetSpriteAction( HSPRITE *hSprite )
  147. {
  148. return hSprite->currentAction;
  149. } /* GetSpriteAction */
  150. /*
  151. * GetSpriteDirection
  152. */
  153. DIRECTION GetSpriteDirection( HSPRITE *hSprite )
  154. {
  155. return hSprite->currentDirection;
  156. } /* GetSpriteDirection */
  157. /*
  158. * SetSpriteActive
  159. */
  160. BOOL SetSpriteActive( HSPRITE *hSprite, BOOL active )
  161. {
  162. hSprite->active = active;
  163. if( active == FALSE )
  164. {
  165. hSprite->xv = 0;
  166. hSprite->yv = 0;
  167. hSprite->xa = 0;
  168. hSprite->ya = 0;
  169. }
  170. return TRUE;
  171. } /* SetSpriteActive */
  172. /*
  173. * GetSpriteActive
  174. */
  175. BOOL GetSpriteActive( HSPRITE *hSprite )
  176. {
  177. return hSprite->active;
  178. } /* GetSpriteActive */
  179. /*
  180. * SetSpriteVelX
  181. */
  182. BOOL SetSpriteVelX( HSPRITE *hSprite, LONG xv, POSITION position )
  183. {
  184. if( hSprite->active == FALSE )
  185. {
  186. return FALSE;
  187. }
  188. if( position == P_ABSOLUTE )
  189. {
  190. hSprite->xv = xv;
  191. }
  192. else if( position == P_RELATIVE )
  193. {
  194. hSprite->xv += xv;
  195. }
  196. return TRUE;
  197. } /* SetSpriteVelX */
  198. /*
  199. * GetSpriteVelX
  200. */
  201. LONG GetSpriteVelX( HSPRITE *hSprite )
  202. {
  203. return hSprite->xv;
  204. } /* GetSpriteVelX */
  205. /*
  206. * SetSpriteVelY
  207. */
  208. BOOL SetSpriteVelY( HSPRITE *hSprite, LONG yv, POSITION position )
  209. {
  210. if( hSprite->active == FALSE )
  211. {
  212. return FALSE;
  213. }
  214. if( position == P_ABSOLUTE )
  215. {
  216. hSprite->yv = yv;
  217. }
  218. else if( position == P_RELATIVE )
  219. {
  220. hSprite->yv += yv;
  221. }
  222. return TRUE;
  223. } /* SetSpriteVelY */
  224. /*
  225. * GetSpriteVelY
  226. */
  227. LONG GetSpriteVelY( HSPRITE *hSprite )
  228. {
  229. return hSprite->yv;
  230. } /* GetSpriteVelY */
  231. /*
  232. * SetSpriteAccX
  233. */
  234. BOOL SetSpriteAccX ( HSPRITE *hSprite, LONG xa, POSITION position )
  235. {
  236. if( position == P_ABSOLUTE )
  237. {
  238. hSprite->xa = xa;
  239. }
  240. else if( position == P_RELATIVE )
  241. {
  242. hSprite->xa += xa;
  243. }
  244. return TRUE;
  245. } /* SetSpriteAccX */
  246. /*
  247. * GetSpriteAccX
  248. */
  249. LONG GetSpriteAccX( HSPRITE *hSprite )
  250. {
  251. return hSprite->xa;
  252. } /* GetSpriteAccX */
  253. /*
  254. * SetSpriteAccY
  255. */
  256. BOOL SetSpriteAccY ( HSPRITE *hSprite, LONG ya, POSITION position )
  257. {
  258. if( position == P_ABSOLUTE )
  259. {
  260. hSprite->ya = ya;
  261. }
  262. else if( position == P_RELATIVE )
  263. {
  264. hSprite->ya += ya;
  265. }
  266. return TRUE;
  267. } /* SetSpriteAccY */
  268. /*
  269. * GetSpriteAccY
  270. */
  271. LONG GetSpriteAccY( HSPRITE *hSprite )
  272. {
  273. return hSprite->ya;
  274. } /* GetSpriteAccY */
  275. /*
  276. * SetSpriteX
  277. */
  278. BOOL SetSpriteX( HSPRITE *hSprite, LONG x, POSITION position )
  279. {
  280. if( hSprite->active == FALSE )
  281. {
  282. return FALSE;
  283. }
  284. if( position == P_AUTOMATIC )
  285. {
  286. hSprite->xv += hSprite->xa;
  287. hSprite->x += hSprite->xv;
  288. }
  289. else if( position == P_ABSOLUTE )
  290. {
  291. hSprite->x = x;
  292. }
  293. else if( position == P_RELATIVE )
  294. {
  295. hSprite->x += x;
  296. }
  297. if( hSprite->x < 0 )
  298. {
  299. hSprite->x += hSprite->xmax << 16;
  300. }
  301. else if( hSprite->x >= hSprite->xmax << 16 )
  302. {
  303. hSprite->x -= hSprite->xmax << 16;
  304. }
  305. return TRUE;
  306. } /* SetSpriteX */
  307. /*
  308. * GetSpriteX
  309. */
  310. LONG GetSpriteX( HSPRITE *hSprite )
  311. {
  312. return hSprite->x;
  313. } /* GetSpriteX */
  314. /*
  315. * SetSpriteY
  316. */
  317. BOOL SetSpriteY ( HSPRITE *hSprite, LONG y, POSITION position )
  318. {
  319. if( hSprite->active == FALSE )
  320. {
  321. return FALSE;
  322. }
  323. if( position == P_AUTOMATIC )
  324. {
  325. hSprite->yv += hSprite->ya;
  326. hSprite->y += hSprite->yv;
  327. }
  328. else if( position == P_ABSOLUTE )
  329. {
  330. hSprite->y = y;
  331. }
  332. else if( position == P_RELATIVE )
  333. {
  334. hSprite->y += y;
  335. }
  336. if( hSprite->y < 0 )
  337. {
  338. hSprite->y += hSprite->ymax << 16;
  339. }
  340. else if( hSprite->y >= hSprite->ymax << 16 )
  341. {
  342. hSprite->y -= hSprite->ymax << 16;
  343. }
  344. return TRUE;
  345. } /* SetSpriteY */
  346. /*
  347. * GetSpriteY
  348. */
  349. LONG GetSpriteY( HSPRITE *hSprite )
  350. {
  351. return hSprite->y;
  352. } /* GetSpriteY */
  353. /*
  354. * SetSpriteSwitch
  355. */
  356. BOOL SetSpriteSwitch ( HSPRITE *hSprite, LONG absSwitch, POSITION position )
  357. {
  358. if( position == P_ABSOLUTE )
  359. {
  360. hSprite->absSwitch = absSwitch;
  361. }
  362. else if( position == P_RELATIVE )
  363. {
  364. hSprite->absSwitch += absSwitch;
  365. }
  366. return TRUE;
  367. } /* SetSpriteSwitch */
  368. /*
  369. * IncrementSpriteSwitch
  370. */
  371. BOOL IncrementSpriteSwitch ( HSPRITE *hSprite, LONG n )
  372. {
  373. hSprite->relSwitch += n;
  374. return TRUE;
  375. } /* IncrementSpriteSwitch */
  376. /*
  377. * SetSpriteSwitchType
  378. */
  379. BOOL SetSpriteSwitchType( HSPRITE *hSprite, SWITCHING switchType )
  380. {
  381. hSprite->switchType = switchType;
  382. hSprite->relSwitch = 0;
  383. return TRUE;
  384. } /* SetSpriteSwitchType */
  385. /*
  386. * GetSpriteSwitchType
  387. */
  388. SWITCHING GetSpriteSwitchType ( HSPRITE *hSprite )
  389. {
  390. return hSprite->switchType;
  391. } /* GetSpriteSwitchType */
  392. /*
  393. * SetSpriteSwitchForward
  394. */
  395. BOOL SetSpriteSwitchForward( HSPRITE *hSprite, BOOL switchForward )
  396. {
  397. hSprite->switchForward = switchForward;
  398. return TRUE;
  399. } /* SetSpriteSwitchForward */
  400. /*
  401. * GetSpriteSwitchForward
  402. */
  403. BOOL GetSpriteSwitchForward( HSPRITE *hSprite )
  404. {
  405. return hSprite->switchForward;
  406. } /* GetSpriteSwitchForward */
  407. /*
  408. * SetSpriteSwitchDone
  409. */
  410. BOOL SetSpriteSwitchDone( HSPRITE *hSprite, BOOL switchDone )
  411. {
  412. hSprite->switchDone = switchDone;
  413. return TRUE;
  414. } /* SetSpriteSwitchDone */
  415. /*
  416. * GetSpriteSwitchDone
  417. */
  418. BOOL GetSpriteSwitchDone( HSPRITE *hSprite )
  419. {
  420. return hSprite->switchDone;
  421. } /* GetSpriteSwitchDone */
  422. /*
  423. * SetSpriteBitmap
  424. */
  425. BOOL SetSpriteBitmap ( HSPRITE *hSprite, USHORT currentBitmap )
  426. {
  427. USHORT c;
  428. c = 0;
  429. while( (hSprite->currentAction != hSprite->hSBM[c].action) ||
  430. (hSprite->currentDirection != hSprite->hSBM[c].direction) )
  431. {
  432. ++c;
  433. }
  434. hSprite->currentBitmap = c + currentBitmap;
  435. return TRUE;
  436. } /* SetSpriteBitmap */
  437. /*
  438. * GetSpriteBitmap
  439. */
  440. USHORT GetSpriteBitmap( HSPRITE *hSprite )
  441. {
  442. USHORT count;
  443. count = 0;
  444. while( (hSprite->currentAction != hSprite->hSBM[count].action) ||
  445. (hSprite->currentDirection != hSprite->hSBM[count].direction) )
  446. {
  447. ++count;
  448. }
  449. return hSprite->currentBitmap - count;
  450. } /* GetSpriteBitmap */
  451. /*
  452. * advanceSpriteBitmap
  453. */
  454. static BOOL advanceSpriteBitmap( HSPRITE *hSprite )
  455. {
  456. SHORT c;
  457. SHORT n;
  458. ACTION curAct;
  459. ACTION act;
  460. DIRECTION curDir;
  461. DIRECTION dir;
  462. curAct = hSprite->currentAction;
  463. curDir = hSprite->currentDirection;
  464. //
  465. // See if we're cycling forward or backward though the images.
  466. //
  467. if( hSprite->switchForward ) // Are we cycling forward?
  468. {
  469. c = hSprite->currentBitmap + 1;
  470. // Does the next image exceed the number of images we have?
  471. if( c >= hSprite->bitmapCount )
  472. {
  473. // if the next image is past the end of the list,
  474. // we need to set it to the start of the series.
  475. SetSpriteBitmap( hSprite, 0 );
  476. c = hSprite->currentBitmap;
  477. }
  478. else
  479. {
  480. act = hSprite->hSBM[c].action;
  481. dir = hSprite->hSBM[c].direction;
  482. // By examining the action and direction fields we can tell
  483. // if we've past the current series of images and entered
  484. // another series.
  485. if( (curAct != act) || (curDir != dir) )
  486. {
  487. SetSpriteBitmap( hSprite, 0 );
  488. }
  489. else // We're still in the series, use the next image.
  490. {
  491. hSprite->currentBitmap = c;
  492. }
  493. }
  494. }
  495. else //cycling backwards
  496. {
  497. c = hSprite->currentBitmap - 1;
  498. if( c < 0 ) // Is the next image past the beginning of the list?
  499. {
  500. n = 0;
  501. // Find the last bitmap in the series
  502. while( (n <= hSprite->bitmapCount) &&
  503. (curAct == hSprite->hSBM[n].action) &&
  504. (curDir == hSprite->hSBM[n].direction) )
  505. {
  506. ++n;
  507. }
  508. hSprite->currentBitmap = n - 1;
  509. }
  510. else
  511. {
  512. act = hSprite->hSBM[c].action;
  513. dir = hSprite->hSBM[c].direction;
  514. // Is the next image past the of the series
  515. if( (curAct != act) || (curDir != dir) )
  516. {
  517. n = c + 1;
  518. while( (n <= hSprite->bitmapCount) &&
  519. (curAct == hSprite->hSBM[n].action) &&
  520. (curDir == hSprite->hSBM[n].direction) )
  521. {
  522. ++n;
  523. }
  524. hSprite->currentBitmap = n - 1;
  525. }
  526. else // The next image is fine, use it.
  527. {
  528. hSprite->currentBitmap = c;
  529. }
  530. }
  531. }
  532. return TRUE;
  533. } /* advanceSpriteBitmap */
  534. /*
  535. * DisplaySprite
  536. */
  537. BOOL DisplaySprite ( GFX_HBM hBuffer, HSPRITE *hSprite, LONG xPlane )
  538. {
  539. USHORT count;
  540. SHORT left;
  541. SHORT right;
  542. SHORT shortx;
  543. SHORT shorty;
  544. SHORT planex;
  545. POINT src;
  546. RECT dst;
  547. if( hSprite->active == FALSE )
  548. {
  549. return FALSE;
  550. }
  551. count = hSprite->currentBitmap;
  552. shortx = (SHORT) (hSprite->x >> 16);
  553. shorty = (SHORT) (hSprite->y >> 16);
  554. planex = (SHORT) (xPlane >> 16);
  555. src.x = 0;
  556. src.y = 0;
  557. if( shortx < planex - C_SCREEN_W )
  558. {
  559. shortx += hSprite->xmax;
  560. }
  561. else if( shortx >= planex + C_SCREEN_W )
  562. {
  563. shortx -= hSprite->xmax;
  564. }
  565. left = shortx - planex;
  566. if( hSprite->currentDirection == RIGHT )
  567. {
  568. left += hSprite->hSBM[count].x;
  569. }
  570. else
  571. {
  572. left += hSprite->width - hSprite->hSBM[count].x - hSprite->hSBM[count].width;
  573. }
  574. right = left + hSprite->hSBM[count].width;
  575. if( left > C_SCREEN_W )
  576. {
  577. left = C_SCREEN_W;
  578. }
  579. else if( left < 0 )
  580. {
  581. src.x = -left;
  582. left = 0;
  583. }
  584. if( right > C_SCREEN_W )
  585. {
  586. right = C_SCREEN_W;
  587. }
  588. else if( right < 0 )
  589. {
  590. right = 0;
  591. }
  592. dst.left = left;
  593. dst.right = right;
  594. dst.top = shorty + hSprite->hSBM[count].y;
  595. dst.bottom = dst.top + hSprite->hSBM[count].height;
  596. gfxBlt(&dst,hSprite->hSBM[count].hBM,&src);
  597. if( hSprite->switchType == HOR )
  598. {
  599. hSprite->relSwitch += abs(hSprite->xv);
  600. if( hSprite->relSwitch >= hSprite->absSwitch )
  601. {
  602. hSprite->relSwitch = 0;
  603. advanceSpriteBitmap( hSprite );
  604. }
  605. }
  606. else if( hSprite->switchType == VER )
  607. {
  608. hSprite->relSwitch += abs(hSprite->yv);
  609. if( hSprite->relSwitch >= hSprite->absSwitch )
  610. {
  611. hSprite->relSwitch = 0;
  612. advanceSpriteBitmap( hSprite );
  613. if( GetSpriteBitmap( hSprite ) == 0 )
  614. {
  615. SetSpriteSwitchDone( hSprite, TRUE );
  616. }
  617. }
  618. }
  619. else if( hSprite->switchType == TIMESWITCH )
  620. {
  621. hSprite->relSwitch += C_UNIT;
  622. if( hSprite->relSwitch >= hSprite->absSwitch )
  623. {
  624. hSprite->relSwitch = 0;
  625. advanceSpriteBitmap( hSprite );
  626. if( GetSpriteBitmap( hSprite ) == 0 )
  627. {
  628. SetSpriteSwitchDone( hSprite, TRUE );
  629. }
  630. }
  631. }
  632. return TRUE;
  633. } /* DisplaySprite */
  634. /*
  635. * DestroySprite
  636. */
  637. BOOL DestroySprite ( HSPRITE *hSprite )
  638. {
  639. USHORT i;
  640. if( hSprite == NULL )
  641. {
  642. ErrorMessage( "hSprite in DestroySprite" );
  643. }
  644. if( hSprite->hSBM == NULL )
  645. {
  646. ErrorMessage( "hSprite->hSBM in DestroySprite" );
  647. }
  648. for( i = 0; i < hSprite->bitmapCount; ++i )
  649. {
  650. if( !gfxDestroyBitmap( hSprite->hSBM[i].hBM ) )
  651. {
  652. ErrorMessage( "gfxDestroyBitmap (hBM) in DestroySprite" );
  653. }
  654. }
  655. MemFree( hSprite->hSBM );
  656. MemFree( hSprite );
  657. return TRUE;
  658. } /* DestroySprite */