smash.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. //-------------------------------------------------
  19. // smash.h (grid based edition)
  20. // Project: Postal
  21. //
  22. // History:
  23. // 05/26/97 JRD Started.
  24. //
  25. // 06/04/97 JRD Integrated with Postal for testing using NEW_SMASH project
  26. // setting so dependent files could still work with old smash
  27. //
  28. // 06/20/97 JRD Removed backwards smash compatibility
  29. //
  30. // 07/03/97 JRD Added an incremental tagged search to eliminate redundant
  31. // parts. Implemented a system of ray tracking accross the grid.
  32. //
  33. // 07/05/97 JRD Fixed MANY bugs in the line collision algorithms. Added clipping.
  34. // Handled special cases of near vertical lines and vertical clipping.
  35. //
  36. // 07/07/97 JRD Used a new class to implement fat smash objects without impacting
  37. // performance - CFatSmash.
  38. //
  39. // 07/08/97 JMI Added debug ASSERTs for "bridge's out" condition to help
  40. // BRH us catch which CThings don't remove their smash(es).
  41. // Also, added release mode protection against "bridge's out"
  42. // condition.
  43. // Also, added bits for flags and flag bases.
  44. // Also, moved definition of ~CSmash() into smash.cpp b/c
  45. // of circular dependency (a Philips chain of command of
  46. // sorts) between smashatorium and realm.
  47. // Also, moved CSmash b/c Bill thinks it's better to keep
  48. // the destructor with the constructor or ease of findage.
  49. //
  50. // 07/10/97 JRD Finally copleted and debugged ful support for Fat Smash
  51. // objects. The main criteria in determining what size is
  52. // "fat", is that "fat" objects shouldn't move very often.
  53. // NOTE that the n2 collision space in the new smash is
  54. // equivalent to NINE smash tiles, so if the tile size is
  55. // 72, the collision areas will be 216 x 216! So be careful!
  56. //
  57. // 08/08/97 BRH Added a QuickCheck that checks for collision between two
  58. // given smashes. This function computes the collision
  59. // based only on the distance and the radius so it doesn't
  60. // use the grid at all. It provides a convenient way to
  61. // check to see if the weapon you are launching has cleared
  62. // your own smash region before arming it, as used in the
  63. // rockets and heatseekers.
  64. //
  65. // 08/12/97 BRH Added a bit for ducking so that missiles won't hit you.
  66. //
  67. // 08/14/97 BRH Added bits for special barrels that can't be destroyed
  68. // by enemy weapons, only CDude weapons.
  69. //
  70. // 08/18/97 BRH Renamed Mext as Next.
  71. //
  72. // 09/02/97 JMI Added Sentry bit.
  73. //
  74. // 09/03/97 JMI Added Civilian bit.
  75. //
  76. ////////////////////////////////////////////////////////////////////////////////
  77. ////////////////////////////////////////////////////////////////////////////////
  78. // NOTE: CURRENT USER LEVEL CHANGE FROM OLD SMASHATORIUM: You must pass
  79. // four parameters to allocate a CSmashatorium (there is no default anymore.)
  80. // These parameters are the world X and Z size, and a grid size larger than
  81. // any smash region.
  82. ////////////////////////////////////////////////////////////////////////////////
  83. // The new smashatorium attempts to partition lists of objects by location
  84. // Currently, each grid location only maintains a single hodge podge list as
  85. // the old Smash. This may be enhanced (memory permitting) to split into
  86. // multiple lists by type, or into multiple smashatoriums fo different grid
  87. // sizes so static objects could be contained in a fine grid.
  88. ////////////////////////////////////////////////////////////////////////////////
  89. //
  90. // The current model demands that objects in the smashatorium exist in no more
  91. // than four grid locations simultaneously. Large smash objects used to detect
  92. // objects-within-a-distance are hooked as a special type of smashee and use
  93. // different collision routines. Similarly, line collisions need higher level
  94. // logic to march through the grid. In short, it is a completely new
  95. // Smashatorium masquerading through the old API.
  96. //
  97. // If you MUST install a large object in the smash, it should be one that
  98. // rarely if ever moves. If so, it can now be supported by a CFatSmash Object.
  99. //
  100. ////////////////////////////////////////////////////////////////////////////////
  101. //
  102. // The current Smashatorium "HIERARCHY OF OBJECTS" :
  103. //
  104. // CSmashLink -> A 128-bit struct which is the manipulation block for the grid.
  105. // It currently points back to it's CSmash parent and it's old grid
  106. // location. For efficiency, we could redundantly store the
  107. // smash bits here.
  108. //
  109. // CFatSmash -> An extention to CSmash that holds an overflow of CSmashLinks
  110. // for illegally big objects.
  111. //
  112. // CSmash -> One of more of these is held by actual game objects. It contains
  113. // a pointer back to the thing parent, a spherical collision region,
  114. // the smash bits, and four SmashLinks to track the corners of the
  115. // objects in the Smashatorium Grid.
  116. //
  117. // CSmashatoriumList -> manages each grid's linked list. The grid is a 2d array
  118. // of these nodes.
  119. //
  120. // CSmashatorium -> Hold the grid and world clipping info. Handles all the user
  121. // functions. Holds the state for the sequential checking state.
  122. //
  123. ////////////////////////////////////////////////////////////////////////////////
  124. #ifndef SMASH_H
  125. #define SMASH_H
  126. #include "RSPiX.h"
  127. #include "thing.h" // we are tying the nodes back to the things
  128. #define NEW_SMASH // We'll risk it!
  129. ////////////////////////////////////////////////////////////////////////////////
  130. // FORWARD DECLARATIONS
  131. ////////////////////////////////////////////////////////////////////////////////
  132. class CSmashLink;
  133. class CSmash;
  134. class CSmashatoriumList;
  135. class CSmashatorium;
  136. class CFatSmash;
  137. ////////////////////////////////////////////////////////////////////////////////
  138. // CSmashLink -> the node used in all the Smashatorium lists:
  139. ////////////////////////////////////////////////////////////////////////////////
  140. class CSmashLink
  141. {
  142. public:
  143. //---------------------------------------------------------------------------
  144. CSmashLink* m_pPrev; // The link
  145. CSmashLink* m_pNext;
  146. CSmash* m_pParent; // Access to bits
  147. CSmashatoriumList* m_pLast; // Where did it reside?
  148. // Might be prudent to store smash bits in here.
  149. //---------------------------------------------------------------------------
  150. void Erase()
  151. {
  152. m_pPrev = m_pNext = NULL;
  153. m_pLast = NULL;
  154. m_pParent = NULL;
  155. }
  156. CSmashLink() { Erase(); }
  157. ~CSmashLink()
  158. {
  159. ASSERT(m_pPrev == NULL);
  160. ASSERT(m_pNext == NULL);
  161. ASSERT(m_pLast == NULL);
  162. Erase();
  163. }
  164. };
  165. ////////////////////////////////////////////////////////////////////////////////
  166. // CFatSmash -> An extension to CSmash used for tracking oversized objects in
  167. // the Smashatorium:
  168. ////////////////////////////////////////////////////////////////////////////////
  169. class CFatSmash
  170. {
  171. public:
  172. CSmash* m_pParent; // Backwards pointer
  173. //--------------------------------------------------------------------
  174. short m_sClipX; // In tile relative to this fat
  175. short m_sClipY; // shows active grid based on clipping
  176. short m_sClipW; // Links outside of this region should
  177. short m_sClipH; // have NULL list pointers
  178. //--------------------------------------------------------------------
  179. short m_sW; // Actual size (in grids)
  180. short m_sH; // Actual Size (in grids)
  181. //--------------------------------------------------------------------
  182. short m_sNumGrids; // For convenience
  183. CSmashLink* m_pLinks; // 1D representation
  184. CSmashLink* m_pFirstLink; // offset into pLinks...
  185. //--------------------------------------------------------------------
  186. CSmashatoriumList* m_pClippedGrid;// Start Grid in 'torium
  187. long m_lX; // See if it's moved!
  188. long m_lY;
  189. //--------------------------------------------------------------------
  190. void Erase();
  191. void Destroy();
  192. CFatSmash() { Erase(); }
  193. ~CFatSmash() { Destroy(); Erase(); }
  194. short Alloc(short sNumGrids);
  195. };
  196. ////////////////////////////////////////////////////////////////////////////////
  197. // CSmash: The user level object which describe the collision region:
  198. ////////////////////////////////////////////////////////////////////////////////
  199. class CSmash
  200. {
  201. //---------------------------------------------------------------------------
  202. // Friends
  203. //---------------------------------------------------------------------------
  204. // friend class CSmashatorium; // do I need this?
  205. //---------------------------------------------------------------------------
  206. // Types, enums, etc.
  207. //---------------------------------------------------------------------------
  208. public:
  209. typedef U32 Bits;
  210. // Available bits for classifying a CSmash
  211. enum
  212. {
  213. Good = 0x00000001,
  214. Bad = 0x00000002,
  215. Character = 0x00000004,
  216. Projectile = 0x00000008,
  217. Misc = 0x00000010,
  218. Dead = 0x00000020,
  219. Barrel = 0x00000040,
  220. Mine = 0x00000080,
  221. Bouy = 0x00000100,
  222. Fire = 0x00000200,
  223. AlmostDead = 0x00000400,
  224. Pylon = 0x00000800,
  225. PowerUp = 0x00001000,
  226. Flag = 0x00002000,
  227. FlagBase = 0x00004000,
  228. Ducking = 0x00008000,
  229. SpecialBarrel = 0x00010000,
  230. Sentry = 0x00020000,
  231. Civilian = 0x00040000
  232. };
  233. //---------------------------------------------------------------------------
  234. // Variables
  235. //---------------------------------------------------------------------------
  236. public:
  237. Bits m_bits; // Bits indicating CSmash's classification
  238. CThing* m_pThing; // Pointer to parental thing
  239. RSphericalRegion m_sphere; // Will eventually be a base class like "CRegion"
  240. short m_sInGrid; // short cut to tell if in a grid...
  241. //---- these remain separate for fater access, since compilers SUCK
  242. long m_lSearchTagCode; // By using a 32bit value, we don't need to untag!
  243. CSmashLink m_link1;
  244. CSmashLink m_link2;
  245. CSmashLink m_link3;
  246. CSmashLink m_link4;
  247. CFatSmash* m_pFat; // Used in special case of fat smash object
  248. //---------------------------------------------------------------------------
  249. // Functions
  250. //---------------------------------------------------------------------------
  251. public:
  252. void Erase()
  253. {
  254. m_bits = 0;
  255. m_sInGrid = FALSE;
  256. m_link1.Erase(); // Clear these out...
  257. m_link2.Erase();
  258. m_link3.Erase();
  259. m_link4.Erase();
  260. m_lSearchTagCode = 0; // Not searched upon!
  261. m_pFat = NULL;
  262. }
  263. CSmash();
  264. ~CSmash();
  265. };
  266. ///////////////////////////////////////////////////////////////////////////////////
  267. // CSmashatoriumList -> the node used in the Smashatorium Grid to hold each list
  268. ///////////////////////////////////////////////////////////////////////////////////
  269. class CSmashatoriumList
  270. {
  271. public:
  272. //---------------------------------------------------------------------------
  273. CSmashLink m_slHead; // permanent imbedded bookends!
  274. CSmashLink m_slTail; // permanent imbedded bookends!
  275. short m_sNum;
  276. //---------------------------------------------------------------------------
  277. void Erase() // will NOT free any of the nodes in the list!
  278. {
  279. m_sNum = 0;
  280. m_slHead.m_pNext = &m_slTail;
  281. m_slTail.m_pPrev = &m_slHead;
  282. m_slHead.m_pPrev = m_slTail.m_pNext = NULL;
  283. }
  284. CSmashatoriumList() { Erase(); }
  285. ~CSmashatoriumList()
  286. {
  287. Erase();
  288. // The book ends are never Remove()'d so we clean them up explicitly here.
  289. m_slHead.Erase();
  290. m_slTail.Erase();
  291. }
  292. };
  293. ///////////////////////////////////////////////////////////////////////////////////
  294. // CSmashatorium -> Master of it all -> "the collision engine of the 90's!"
  295. ///////////////////////////////////////////////////////////////////////////////////
  296. class CSmashatorium
  297. {
  298. public:
  299. //---------------------------------------------------------------------------
  300. short m_sWorldW; // for general logic
  301. short m_sWorldH;
  302. short m_sClipW; // For clipping border
  303. short m_sClipH;
  304. short m_sGridW; // NOT TileW -> this is the NUMBER of nodes!
  305. short m_sGridH;
  306. short m_sTileW; // For catching size errors
  307. short m_sTileH;
  308. CSmashatoriumList *m_pGrid; // actually a 2d array
  309. //------------------- ACCESS VARIABLES:
  310. short *m_psAccessX; // m_sWorldW in size
  311. short *m_psAccessY; // m_sWorldH in size
  312. CSmashatoriumList **m_ppslAccessY; // m_sWorldH in size
  313. short *m_psClipX; // m_sWorldW + 2 Tiles in size
  314. short *m_psClipY; // m_sWorldH + 2 Tiles in size
  315. CSmashatoriumList **m_ppslClipY; // m_sWorldH + 2 Tiles in size
  316. //------------------- SEARCHING STATE INFORMATION: (QuickCheck info)
  317. // This must also handle large regions!
  318. // The design is largely for backwards compatibility.
  319. CSmash* m_pSmasher; // NULL if search NOT in progress
  320. CSmashLink* m_pCurrentSmashee; //
  321. CSmash::Bits m_include;
  322. CSmash::Bits m_dontcare;
  323. CSmash::Bits m_exclude;
  324. CSmashatoriumList *m_pCurrentList;
  325. short m_sCurrentListX;
  326. short m_sCurrentListY;
  327. short m_sSearchW; // base 1 !
  328. short m_sSearchH; // base 1 !
  329. long m_lCurrentSearchCode; // change it for each search
  330. short m_sNumInSmash; // Used for debugging
  331. short m_sMaxNumInSmash; // Used for debugging
  332. //---------------------------------------------------------------------------
  333. // Update the specified CSmash. If it isn't already in the smashatorium, it
  334. // is automatically added. Whenever the CSmash is modified, this must be
  335. // called before using the smashotorium to check for collisions!
  336. // This version of the update is less efficient, as it always searches
  337. // four quadrants, and usually the desired object is only in one of the
  338. // four. But I am trying it because it offers very fast updates.
  339. void Update(CSmash* pSmash); // In: CSmash to be updated
  340. //---------------------------------------------------------------------------
  341. void Erase() // does NOT deallocate anything!
  342. {
  343. m_sWorldW = m_sWorldH = m_sGridW = m_sGridH =
  344. m_sClipW = m_sClipH = m_sTileW = m_sTileH = 0;
  345. m_psAccessX = m_psAccessY = m_psClipX = m_psClipY = NULL;
  346. m_pGrid = NULL;
  347. m_ppslAccessY = m_ppslClipY = NULL;
  348. m_lCurrentSearchCode = 1; // zero is NOT a valid search key!
  349. m_sNumInSmash = m_sMaxNumInSmash = 0;
  350. }
  351. void Destroy()
  352. {
  353. if (m_pGrid) delete [] m_pGrid;
  354. if (m_psAccessX) free (m_psAccessX);
  355. if (m_psAccessY) free (m_psAccessY);
  356. if (m_ppslAccessY) free (m_ppslAccessY);
  357. Erase();
  358. }
  359. short Alloc(short sWorldW,short sWorldH,short sTileW,short sTileH);
  360. // Lower Level Inline!
  361. // These are done multiple times for a true remove
  362. void RemoveLimb(CSmashatoriumList* pList,CSmashLink* pLink);
  363. // This is on a per object level:
  364. void Remove(CSmash* pSmash);
  365. // This is on a per object level:
  366. // Used for fat objects
  367. void RemoveFat(CFatSmash* pFatSmash);
  368. // Insert at tail...
  369. // Lower level inline
  370. void AddLimb(CSmashatoriumList* pList, CSmashLink* pLink);
  371. // Higher Level -> add an entire CSmash into the 'torium
  372. // User calls Update, which checks for clipping
  373. // This routine ASSUMES not clipped out!
  374. void Add(CSmash* pSmash,CSmashatoriumList *pList);
  375. // Higher Level -> add an entire CSmash into the 'torium
  376. // User calls Update, which checks for clipping
  377. // This routine ASSUMES not clipped out!
  378. // Used for fat objects
  379. void AddFat(CFatSmash* pFatSmash);
  380. //===========================================================================
  381. // Currently stubs for now...
  382. //===========================================================================
  383. // Reset QuickCheckNext() using the specified parameters.
  384. // Begin a multicall collision search based on a smashee
  385. //
  386. void QuickCheckReset( // Returns true if collision detected, false otherwise
  387. CSmash* pSmasher, // In: CSmash to check
  388. CSmash::Bits include, // In: Bits that must be 1 to collide with a given CSmash
  389. CSmash::Bits dontcare, // In: Bits that you don't care about
  390. CSmash::Bits exclude); // In: Bits that must be 0 to collide with a given CSmash
  391. // Reset QuickCheckNext() using the specified paramters.
  392. void QuickCheckReset( // Returns true if collision detected, false otherwise
  393. CSmash::Bits include, // In: Bits, of which, one must be set to collide with a given CSmash
  394. CSmash::Bits dontcare, // In: Bits that you don't care about
  395. CSmash::Bits exclude); // In: Bits that must be 0 to collide with a given CSmash
  396. CSmash *GetNextSmash(); // Internal - used to aid in Next searches
  397. // Returns the next object being collided with, using the parameters that were
  398. // passed to QuickCheckReset(). This will return all the objects being collided
  399. // with in an arbitrary order. Other functions will someday return the objects
  400. // in some particular order. The function will return false when there are no
  401. // more colisions.
  402. bool QuickCheckNext( // Returns true if collision detected, false otherwise
  403. R3DLine* pline, // In: Line segment to collide against.
  404. CSmash** pSmashee = 0, // Out: Thing being smashed into if any (unless 0)
  405. CSmash* pSmasher = 0); // Out: Smash that should be excluded from search.
  406. // Returns true if collision detected, false otherwise
  407. // Out: Thing being smashed into if any (unless 0)
  408. bool QuickCheckNext(CSmash** pSmashee = 0);
  409. // Determine whether specified CSmash is colliding with anything, and
  410. // if so, (optionally) return the first thing it's colliding with. If
  411. // you want to know about all things being collided with or otherwise
  412. // want more control, use a CSmashatorium::Finder object.
  413. bool QuickCheck( // Returns true if collision detected, false otherwise
  414. CSmash* pSmasher, // In: CSmash to check
  415. CSmash::Bits include, // In: Bits that must be 1 to collide with a given CSmash
  416. CSmash::Bits dontcare, // In: Bits that you don't care about
  417. CSmash::Bits exclude, // In: Bits that must be 0 to collide with a given CSmash
  418. CSmash** pSmashee = 0); // Out: Thing being smashed into if any (unless 0)
  419. bool QuickCheckClosest( // Returns true if collision detected, false otherwise
  420. CSmash* pSmasher, // In: CSmash to check
  421. CSmash::Bits include, // In: Bits that must be 1 to collide with a given CSmash
  422. CSmash::Bits dontcare, // In: Bits that you don't care about
  423. CSmash::Bits exclude, // In: Bits that must be 0 to collide with a given CSmash
  424. CSmash** pSmashee);
  425. // Determine whether specified R3DLine is colliding with anything, and
  426. // if so, (optionally) return the first thing it's colliding with. If
  427. // you want to know about all things being collided with or otherwise
  428. // want more control, use a CSmashatorium::Finder object.
  429. bool QuickCheck( // Returns true if collision detected, false otherwise
  430. R3DLine* pLine, // In: Line to check
  431. CSmash::Bits include, // In: Bits that must be 1 to collide with a given CSmash
  432. CSmash::Bits dontcare, // In: Bits that you don't care about
  433. CSmash::Bits exclude, // In: Bits that must be 0 to collide with a given CSmash
  434. CSmash** pSmashee = 0, // Out: Thing being smashed into if any (unless 0)
  435. CSmash* pSmasher = 0); // Out: Smash that should be excluded from search.
  436. // Determine whether the two smashes have collided. This is based purely on
  437. // the distance between them and their radius so it doesn't have to check
  438. // the grid at all.
  439. bool QuickCheck( // Returns true if collision detected, false otherwise
  440. CSmash* pSmasher, // In: One input smash
  441. CSmash* pSmashee) // In: Second input smash
  442. {
  443. return (ABS2(pSmasher->m_sphere.sphere.X - pSmashee->m_sphere.sphere.X,
  444. pSmasher->m_sphere.sphere.Y - pSmashee->m_sphere.sphere.Y,
  445. pSmasher->m_sphere.sphere.Z - pSmashee->m_sphere.sphere.Z) <
  446. ((pSmasher->m_sphere.sphere.lRadius + pSmashee->m_sphere.sphere.lRadius) *
  447. (pSmasher->m_sphere.sphere.lRadius + pSmashee->m_sphere.sphere.lRadius)));
  448. }
  449. // Determine whether specified R3DLine is colliding with anything, and
  450. // if so, (optionally) return the closest (from start of segment) thing
  451. // it's colliding with. If you want to know about all things being
  452. // collided with or otherwise want more control, use a
  453. // CSmashatorium::Finder object.
  454. bool QuickCheckClosest( // Returns true if collision detected, false otherwise
  455. R3DLine* pline, // In: Line to check
  456. CSmash::Bits include, // In: Bits that must be 1 to collide with a given CSmash
  457. CSmash::Bits dontcare, // In: Bits that you don't care about
  458. CSmash::Bits exclude, // In: Bits that must be 0 to collide with a given CSmash
  459. CSmash** pSmashee, // Out: Thing being smashed into if any.
  460. CSmash* pSmasher = 0); // Out: Smash that should be excluded from search.
  461. // Does a 2d XZ collision between two spheres.
  462. short CollideCyl(CSmash* pSmashee,RSphere* pSphere);
  463. // Does a 2d XZ collision between a sphere and a line
  464. short CollideCyl(CSmash* pSmashee,R3DLine* pLine);
  465. //---------------------------------------------------------------------------
  466. CSmashatorium() { Erase(); } // Needed for defaul construction
  467. void Debug(); // Used for a plethora of things.
  468. // Reset does NOT DEALLOCATE any portion of the Smashatorium.
  469. // It is just a short cut to reset each of the grid's
  470. // SmashLists. But Each Smash must reset it's own Links!
  471. //
  472. void Reset(void);
  473. CSmashatorium(short sWorldW,short sWorldH,short sTileW,short sTileH)
  474. { Erase(); Alloc(sWorldW,sWorldH,sTileW,sTileH); }
  475. ~CSmashatorium() { Destroy(); }
  476. };
  477. //-------------------------------------------------
  478. #endif
  479. /* This update saves search space, but is too slow on update
  480. void Update(CSmash* pSmash) // In: CSmash to be updated
  481. {
  482. ASSERT(pSmash);
  483. // ASSUME THAT THE OBJECT IS GRID SIZED!
  484. //---------------------------------------------------------------
  485. // (1) Cast the sphere into a 2 point square
  486. RSphere* pSphere = &(pSmash->m_sphere->sphere);
  487. long lR = pSphere->lRadius;
  488. long x1,x2,y1,y2;
  489. x1 = x2 = pSphere->X;
  490. y1 = y2 = pSphere->Z;
  491. x1 -= lR;
  492. x2 += lR;
  493. y1 -= lR;
  494. y2 += lR;
  495. ///////////////////////////////////
  496. // (2) Catch the case of clipping:
  497. if ( (x1 < 0) || (y1 < 0) || (x2 >= m_sWorldW) || (y2 >= m_sWorldH) )
  498. {
  499. // Handle partial clipping
  500. ASSERT(0);
  501. return; // NYI!
  502. }
  503. ///////////////////////////////////
  504. // No clip case
  505. // (3) process each of the four corners:
  506. CSmashatoriumList **pCurrent = NULL;
  507. //-------------------------------------------------------------
  508. pCurrent = m_ppslAccessY[y1] + m_psAccessX[x1];
  509. if (m_link1.m_pLast && (pCurrent != m_link1.m_pLast) )
  510. {
  511. ////////////// Pull the old out of the list!
  512. Remove(m_link1.m_pLast);
  513. }
  514. m_link1.m_pLast = pCurrent; // NOT YET INSTALLED THOUGH!
  515. //-------------------------------------------------------------
  516. //-------------------------------------------------------------
  517. pCurrent = m_ppslAccessY[y1] + m_psAccessX[x2];
  518. if (m_link2.m_pLast && (pCurrent != m_link2.m_pLast) )
  519. {
  520. ////////////// Pull the old out of the list!
  521. Remove(m_link2.m_pLast);
  522. }
  523. m_link2.m_pLast = pCurrent; // NOT YET INSTALLED THOUGH!
  524. //-------------------------------------------------------------
  525. //-------------------------------------------------------------
  526. pCurrent = m_ppslAccessY[y2] + m_psAccessX[x1];
  527. if (m_link3.m_pLast && (pCurrent != m_link3.m_pLast) )
  528. {
  529. ////////////// Pull the old out of the list!
  530. Remove(m_link3.m_pLast);
  531. }
  532. m_link3.m_pLast = pCurrent; // NOT YET INSTALLED THOUGH!
  533. //-------------------------------------------------------------
  534. //-------------------------------------------------------------
  535. pCurrent = m_ppslAccessY[y2] + m_psAccessX[x2];
  536. if (m_link4.m_pLast && (pCurrent != m_link4.m_pLast) )
  537. {
  538. ////////////// Pull the old out of the list!
  539. Remove(m_link4.m_pLast);
  540. }
  541. m_link4.m_pLast = pCurrent; // NOT YET INSTALLED THOUGH!
  542. //-------------------------------------------------------------
  543. //**************************************************
  544. // there is an error here! There could have been a
  545. // quadrant which did not CHANGE (so was not removed),
  546. // but is now REDUNDANT. Think about combining these
  547. // sections!
  548. //**************************************************
  549. // (4) Check for redundancies before installing:
  550. // USE a NULL pointer to signify redundancy
  551. if (m_link2.m_pLast == m_link3.m_pLast)
  552. {
  553. // all four in same region, 3 redundant:
  554. m_link2.m_pLast = m_link3.m_pLast = m_link4.m_pLast = NULL;
  555. }
  556. else if (m_link1.m_pLast == m_link3.m_pLast)
  557. {
  558. // vertically redundant:
  559. m_link3.m_pLast = m_link4.m_pLast = NULL;
  560. }
  561. else if (m_link1.m_pLast == m_link2.m_pLast)
  562. {
  563. // horizontally redundant:
  564. m_link2.m_pLast = m_link4.m_pLast = NULL;
  565. }
  566. // Link them all in if not redundant
  567. if (m_link1.m_pLast) Add(m_link1.m_pLast,&m_link1);
  568. if (m_link2.m_pLast) Add(m_link2.m_pLast,&m_link1);
  569. if (m_link3.m_pLast) Add(m_link3.m_pLast,&m_link1);
  570. if (m_link4.m_pLast) Add(m_link4.m_pLast,&m_link1);
  571. }
  572. */