chip.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  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. //
  20. // CHIP.CPP
  21. //
  22. // Created on 1/31/96 JMI
  23. //
  24. //////////////////////////////////////////////////////////////////////
  25. //
  26. // Container class for a chip's sprite (x, y, z, etc.).
  27. //
  28. //////////////////////////////////////////////////////////////////////
  29. //////////////////////////////////////////////////////////////////////
  30. // Blue Includes.
  31. //////////////////////////////////////////////////////////////////////
  32. //#include "common/system.h"
  33. //////////////////////////////////////////////////////////////////////
  34. // Green Includes.
  35. //////////////////////////////////////////////////////////////////////
  36. //#include "BLiT/blit2d/blimage.h"
  37. #include "RSPiX.h"
  38. //////////////////////////////////////////////////////////////////////
  39. // Orange Includes.
  40. //////////////////////////////////////////////////////////////////////
  41. //#include "cdt/queue.h"
  42. #include "chip.h"
  43. //////////////////////////////////////////////////////////////////////
  44. // Macros.
  45. //////////////////////////////////////////////////////////////////////
  46. #define MAX_CHIPS 4096
  47. #define BASE (m_pimChip->lHeight)
  48. #define THICKNESS 0.50F
  49. //////////////////////////////////////////////////////////////////////
  50. // Typedefs.
  51. //////////////////////////////////////////////////////////////////////
  52. //////////////////////////////////////////////////////////////////////
  53. // Protos.
  54. //////////////////////////////////////////////////////////////////////
  55. //////////////////////////////////////////////////////////////////////
  56. // Module specific (static) vars.
  57. //////////////////////////////////////////////////////////////////////
  58. RSList<CChip, float> CChip::ms_slistChips; // List of all
  59. // chips sorted by
  60. // each chip's Z
  61. // position.
  62. RImage* CChip::ms_pimView = NULL; // Background for all chips.
  63. RImage* CChip::ms_pimStack = NULL; // Stack for all chips.
  64. //////////////////////////////////////////////////////////////////////
  65. // Functions.
  66. //////////////////////////////////////////////////////////////////////
  67. //////////////////////////////////////////////////////////////////////
  68. // Con/Destruction.
  69. //////////////////////////////////////////////////////////////////////
  70. //////////////////////////////////////////////////////////////////////
  71. //
  72. // Default constructor.
  73. // Returns nothing.
  74. //
  75. //////////////////////////////////////////////////////////////////////
  76. CChip::CChip()
  77. {
  78. Init();
  79. if (ms_slistChips.Insert(this, &m_fZ) == 0)
  80. {
  81. }
  82. else
  83. {
  84. TRACE("CChip(): Unable to Insert this into list.\n");
  85. }
  86. }
  87. //////////////////////////////////////////////////////////////////////
  88. //
  89. // Destructor.
  90. // Returns nothing.
  91. //
  92. //////////////////////////////////////////////////////////////////////
  93. CChip::~CChip()
  94. {
  95. Reset();
  96. if (ms_slistChips.Remove(this) == 0)
  97. {
  98. }
  99. else
  100. {
  101. TRACE("CChip(): Unable to Remove this from list.\n");
  102. }
  103. }
  104. //////////////////////////////////////////////////////////////////////
  105. // Methods.
  106. //////////////////////////////////////////////////////////////////////
  107. //////////////////////////////////////////////////////////////////////
  108. //
  109. // Move this chip to the new location, erasing the old.
  110. // Returns nothing.
  111. //
  112. //////////////////////////////////////////////////////////////////////
  113. void CChip::SetPosition(long lX, long lY, long lZ)
  114. {
  115. float fOldZ = m_fZ;
  116. m_fX = (float)lX;
  117. m_fY = (float)lY;
  118. m_fZ = (float)lZ;
  119. // If the z position changed . . .
  120. if (fOldZ != m_fZ)
  121. {
  122. // We must reposition this item.
  123. ms_slistChips.Reposition(this);
  124. }
  125. }
  126. //////////////////////////////////////////////////////////////////////
  127. //
  128. // Slide this chip on update to the new location.
  129. // lRate is the magnitude of the vector directing the
  130. // chip.
  131. // You may call this when the chip is already sliding to redirect it.
  132. // Returns 0 if successfully started.
  133. //
  134. //////////////////////////////////////////////////////////////////////
  135. short CChip::Slide(long lX, long lY, long lZ, long lRate)
  136. {
  137. short sRes = 0; // Assume success.
  138. // Store destination position.
  139. m_sDestX = (short)lX;
  140. m_sDestY = (short)lY;
  141. m_sDestZ = (short)lZ;
  142. m_sRate = (short)lRate;
  143. // Success.
  144. m_sSliding = TRUE;
  145. return sRes;
  146. }
  147. //////////////////////////////////////////////////////////////////////
  148. //
  149. // Reset this chip. Stop sliding, if doing so.
  150. // Initialize/Release all members.
  151. //
  152. //////////////////////////////////////////////////////////////////////
  153. void CChip::Reset(void)
  154. {
  155. Init();
  156. }
  157. //////////////////////////////////////////////////////////////////////
  158. //
  159. // Update movement.
  160. // Returns 0 normally, 1 if chip destroyed.
  161. //
  162. //////////////////////////////////////////////////////////////////////
  163. short CChip::Update(void)
  164. {
  165. short sDeleted = 0; // Assume normal ops.
  166. if (m_sSliding == TRUE)
  167. {
  168. m_fX += ((float)m_sDestX - m_fX) / (float)m_sRate;
  169. m_fY += ((float)m_sDestY - m_fY) / (float)m_sRate;
  170. m_fZ += ((float)m_sDestZ - m_fZ) / (float)m_sRate;
  171. m_sRate--;
  172. ASSERT(m_sRate >= 0);
  173. if ( (short)m_fX == m_sDestX
  174. && (short)m_fY == m_sDestY
  175. && (short)m_fZ == m_sDestZ)
  176. {
  177. // Done.
  178. m_sSliding = FALSE;
  179. // Stack if necessary.
  180. sDeleted = Stack();
  181. }
  182. }
  183. return sDeleted;
  184. }
  185. //////////////////////////////////////////////////////////////////////
  186. //
  187. // Called to draw this chip.
  188. //
  189. //////////////////////////////////////////////////////////////////////
  190. void CChip::Draw(void)
  191. {
  192. ASSERT(ms_pimView != NULL);
  193. ASSERT(m_pimChip != NULL);
  194. // If this is merely a chip . . .
  195. if (m_sNumChips == 1)
  196. {
  197. // Put'er there! NOTE: ItoBKD is a real time macro containing
  198. // merely 2 dereferences, worst case.
  199. rspBlit(m_pimChip, ms_pimView, m_fX, m_fY);
  200. // BLT_FItoBKD(m_pimChip, ms_pimView, (short)m_fX, (short)m_fY);
  201. }
  202. else
  203. {
  204. // Otherwise, display a stack.
  205. short sHeight = (short)(THICKNESS * (float)GetSize());
  206. // The smallest stack should look like a stack.
  207. if (sHeight < 1)
  208. {
  209. sHeight = 1;
  210. }
  211. for (short s = 0; s < sHeight; s++)
  212. {
  213. // BLT_FItoBKD(m_pimChip, ms_pimView, (short)m_fX, (short)m_fY - s);
  214. rspBlit(m_pimChip, ms_pimView, m_fX, m_fY - s);
  215. }
  216. }
  217. }
  218. //////////////////////////////////////////////////////////////////////
  219. //
  220. // Called to update all sliding chips.
  221. // Technically, we should go through the list twice. Once to move the
  222. // chips and rearrange them in the list and once to blt them.
  223. // We cannot rearrange them as we go through the list or we could end
  224. // up processing a chip twice or not at all. This indicates going
  225. // through the list three times:
  226. // 1) Move chips and set a flag to rearrange.
  227. // 2) Rearrange.
  228. // 3) Blt.
  229. // OR
  230. // we could go through the list once adding all the ones to be re-
  231. // arranged to a queue. Reprocess only those, rearranging as
  232. // necessary and then traverse the list and blt:
  233. // 1) Move chips and add those with new Z positions to a queue.
  234. // 2) Empty queue rearranging queued chips only.
  235. // 3) Blt chips.
  236. //
  237. //////////////////////////////////////////////////////////////////////
  238. void CChip::Critical(void)
  239. {
  240. RQueue<CChip, MAX_CHIPS> qChips;
  241. // Step 1: Traverse the Z sorted list updating all chips and
  242. // adding those that change their Z position to a queue of chips
  243. // to be repositioned.
  244. CChip* pchip = ms_slistChips.GetHead();
  245. float fOldZ;
  246. while (pchip != NULL)
  247. {
  248. fOldZ = pchip->m_fZ;
  249. // If not deleted during update . . .
  250. if (pchip->Update() == 0)
  251. {
  252. // If this chip changed its Z position . . .
  253. if (fOldZ != pchip->m_fZ)
  254. {
  255. // Add it to the queue of chips to be resorted.
  256. qChips.EnQ(pchip);
  257. }
  258. }
  259. // Get the next chip to move.
  260. pchip = ms_slistChips.GetNext();
  261. }
  262. // Step 2: Empty the queue resorting each chip.
  263. pchip = qChips.DeQ();
  264. while (pchip != NULL)
  265. {
  266. // Reposition this chip in the sorted list since its Z position
  267. // changed.
  268. ms_slistChips.Reposition(pchip);
  269. pchip = qChips.DeQ();
  270. }
  271. // Step 3: Blt the chips in order.
  272. pchip = ms_slistChips.GetHead();
  273. while (pchip != NULL)
  274. {
  275. pchip->Draw();
  276. pchip = ms_slistChips.GetNext();
  277. }
  278. }
  279. //////////////////////////////////////////////////////////////////////
  280. //
  281. // Destroy all current chips.
  282. //
  283. //////////////////////////////////////////////////////////////////////
  284. void CChip::DeleteAll(void)
  285. {
  286. CChip* pchip = ms_slistChips.GetHead();
  287. while (pchip != NULL)
  288. {
  289. // Someday a chip may have data to allocate.
  290. pchip->Reset();
  291. // Destructor pulls off of list.
  292. delete pchip;
  293. pchip = ms_slistChips.GetNext();
  294. }
  295. }
  296. //////////////////////////////////////////////////////////////////////
  297. //
  298. // Stack chip if necessary.
  299. // Returns 0 normally, 1 if chip destroyed.
  300. //
  301. //////////////////////////////////////////////////////////////////////
  302. short CChip::Stack(void)
  303. {
  304. short sDeleted = 0; // Assume normal ops.
  305. if (m_sStackable != FALSE)
  306. {
  307. // If we are near a chip that's not sliding . . .
  308. CChip* pchip = IsColliding(FALSE);
  309. if (pchip != NULL)
  310. {
  311. // Add this chip/stack to that stack.
  312. pchip->Add(this);
  313. sDeleted = TRUE;
  314. // It's important that we delete this chip and
  315. // add to the other as, if we are in one of
  316. // the Critical loops, Remove()ing another chip
  317. // from the list of chips will make that chip
  318. // the current and screw up the loop's next call
  319. // to GetNext().
  320. // Destroy this chip (it is reflected in the new
  321. // size of pchip's stack).
  322. delete this;
  323. }
  324. }
  325. return sDeleted;
  326. }
  327. //////////////////////////////////////////////////////////////////////
  328. //
  329. // Add to this stack.
  330. // Returns 0 on success.
  331. //
  332. //////////////////////////////////////////////////////////////////////
  333. short CChip::Add(CChip* pchip)
  334. {
  335. short sRes = 0; // Assume success.
  336. // Take stack's size and add to this one's.
  337. m_sNumChips += pchip->GetSize();
  338. return sRes;
  339. }
  340. //////////////////////////////////////////////////////////////////////
  341. //
  342. // Remove sNum chips from this stack.
  343. // Returns chip/stack on success; NULL on error.
  344. //
  345. //////////////////////////////////////////////////////////////////////
  346. CChip* CChip::Sub(short sNum)
  347. {
  348. CChip* pchip = NULL; // Assume failure.
  349. // If we have sNum to give up . . .
  350. if (sNum < GetSize())
  351. {
  352. // Create a new chip/stack for these.
  353. pchip = new CChip;
  354. // Make it empty for now.
  355. pchip->SetSize(0);
  356. }
  357. else
  358. {
  359. if (sNum == GetSize())
  360. {
  361. // Use this chip.
  362. pchip = this;
  363. }
  364. }
  365. // If successful . . .
  366. if (pchip != NULL)
  367. {
  368. // Add to new stack.
  369. pchip->SetSize(pchip->GetSize() + sNum);
  370. // Remove from this.
  371. SetSize(GetSize() - sNum);
  372. // Some attributes that should be copied.
  373. pchip->SetPosition((long)m_fX, (long)m_fY, (long)m_fZ);
  374. pchip->SetChipImage(GetChipImage());
  375. }
  376. return pchip;
  377. }
  378. //////////////////////////////////////////////////////////////////////
  379. // Querries.
  380. //////////////////////////////////////////////////////////////////////
  381. //////////////////////////////////////////////////////////////////////
  382. //
  383. // Returns the first chip found to be colliding
  384. // with this chip. If sTop is TRUE, the highest,
  385. // the one with the greatest Y, is found.
  386. //
  387. //////////////////////////////////////////////////////////////////////
  388. CChip* CChip::IsColliding(short sTop/* = FALSE*/)
  389. {
  390. CChip* pchip = NULL; // Assume not found.
  391. CChip* pchipHighest = NULL; // If sTop is TRUE, this is used
  392. // to store the chip with the
  393. // lowest Y.
  394. for (short i = 0; i < 2 && (pchip == NULL || sTop == TRUE); i++)
  395. {
  396. // Search back from this one . . .
  397. pchip = (i == 0 ? ms_slistChips.GetPrev(this)
  398. : ms_slistChips.GetNext(this));
  399. while (pchip != NULL && pchip != this)
  400. {
  401. // Is it outside the Z range?
  402. // NOTE: If this check stops the search, it can screw up in the
  403. // event that another chip has a different size.
  404. if ( pchip->m_fZ + (float)pchip->m_pimChip->m_sHeight < m_fZ
  405. || pchip->m_fZ > m_fZ + (float)m_pimChip->m_sHeight)
  406. {
  407. // Outside.
  408. pchip = NULL;
  409. }
  410. else
  411. {
  412. // Is it outside the X range?
  413. // NOTE: this check has the same limitation as above.
  414. if ( pchip->m_fX + pchip->m_pimChip->m_sWidth < m_fX
  415. || pchip->m_fX > m_fX + (float)m_pimChip->m_sWidth)
  416. {
  417. // Outside.
  418. }
  419. else
  420. {
  421. if (pchip->m_sStackable != FALSE)
  422. {
  423. // If not looking for the highest . . .
  424. if (sTop == FALSE)
  425. {
  426. // We're done.
  427. break;
  428. }
  429. else
  430. {
  431. if (pchipHighest == NULL)
  432. {
  433. pchipHighest = pchip;
  434. }
  435. else
  436. {
  437. if (pchip->m_fY < pchipHighest->m_fY)
  438. {
  439. pchipHighest = pchip;
  440. }
  441. }
  442. }
  443. }
  444. else
  445. {
  446. // Can't use a stackable chip.
  447. }
  448. }
  449. pchip = (i == 0 ? ms_slistChips.GetPrev()
  450. : ms_slistChips.GetNext() );
  451. }
  452. }
  453. }
  454. // If we're searching for the highest and we found one . . .
  455. if (sTop == TRUE && pchipHighest != NULL)
  456. {
  457. pchip = pchipHighest;
  458. }
  459. return pchip;
  460. }
  461. //////////////////////////////////////////////////////////////////////
  462. //
  463. // Returns the first chip/stack in the given rectangle.
  464. // Returns NULL if none found.
  465. // (static)
  466. //
  467. //////////////////////////////////////////////////////////////////////
  468. CChip* CChip::GetChipIn(long lX, long lY, long lW, long lH)
  469. {
  470. CChip* pchip = ms_slistChips.GetHead();
  471. while (pchip != NULL)
  472. {
  473. if ( (long)pchip->m_fX < lX
  474. || (long)pchip->m_fX > lX + lW
  475. || (long)pchip->m_fY < lY
  476. || (long)pchip->m_fY > lY + lH)
  477. {
  478. // No match.
  479. pchip = ms_slistChips.GetNext();
  480. }
  481. else
  482. {
  483. // Found one.
  484. break;
  485. }
  486. }
  487. return pchip;
  488. }
  489. //////////////////////////////////////////////////////////////////////
  490. // Internal.
  491. //////////////////////////////////////////////////////////////////////
  492. //////////////////////////////////////////////////////////////////////
  493. //
  494. // Initialize all members regardless of their current values.
  495. //
  496. //////////////////////////////////////////////////////////////////////
  497. void CChip::Init(void)
  498. {
  499. m_fX = 0.0F;
  500. m_fY = 0.0F;
  501. m_fZ = 0.0F;
  502. m_sDestX = 0;
  503. m_sDestY = 0;
  504. m_sDestZ = 0;
  505. m_sRate = 0;
  506. m_pimChip = NULL;
  507. m_sSliding = FALSE;
  508. m_sStackable = TRUE;
  509. m_sNumChips = 1;
  510. }
  511. //////////////////////////////////////////////////////////////////////
  512. // EOF
  513. //////////////////////////////////////////////////////////////////////