Counter Strike : Global Offensive Source Code
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.

1689 lines
39 KiB

  1. //
  2. // Bomber By Kazys Stepanas
  3. //
  4. //--------------------------------------------------------------------------------------------------
  5. // Globals.
  6. //--------------------------------------------------------------------------------------------------
  7. global bgCol = CA.B_BLACK;
  8. global quit = false;
  9. global lastTouchedBlock = -1;
  10. global player;
  11. global gameLevel = 1;
  12. global blocks = table(count = 0);
  13. global powerups = table(count = 0);
  14. global enemies = table(count = 0);
  15. global blockDeadZone = table(x1 = 31, y1 = 8, x2 = 39, y2 = 14);
  16. global enemyDeadZone = table(x1 = 22, y1 = 7, x2 = 45, y2 = 16);
  17. // Thing types.
  18. global T_Space = 0;
  19. global T_Player = 1;
  20. global T_Bomb = 2;
  21. global T_Explosion = 3;
  22. global T_Block = 4;
  23. global T_Grid = 5;
  24. global T_Powerup = 6;
  25. global T_Enemy = 7;
  26. // Powerup types.
  27. global PT_Bomb = 1;
  28. global PT_Size = 2;
  29. global PT_Life = 3;
  30. // Dead zone types.
  31. global DT_None = 0;
  32. global DT_Block = 1;
  33. global DT_Enemy = 2;
  34. //--------------------------------------------------------------------------------------------------
  35. // Grid control.
  36. //--------------------------------------------------------------------------------------------------
  37. global grid = table(startX = 0, startY = 0, spaceX = 1, spaceY = 1, rows = 0, cols = 0);
  38. //--------------------------------------------------------------------------------------------------
  39. // Constants
  40. //--------------------------------------------------------------------------------------------------
  41. global screen = table(w = 80, h = 23);
  42. global statusY = 24;
  43. global bombFuse = 1.25;
  44. global explodeTime = 0.75;
  45. global explodeCycle = 0.05;
  46. global maxPlayerBombs = 10;
  47. global maxPlayerSize = 5;
  48. global maxPowerups = 20;
  49. global maxLives = 5;
  50. global startLives = 3;
  51. global scoreBlock = 10;
  52. global scoreNME = 50;
  53. global nmeMoveTime = 1.0;
  54. global powerupChance = 40;
  55. global maxLevel = 10;
  56. global maxBlockHits = 3;
  57. //--------------------------------------------------------------------------------------------------
  58. // Graphics
  59. //--------------------------------------------------------------------------------------------------
  60. global playerPix = "\2";
  61. global playerDeadPix = "\5";
  62. global bombPix = "\15";
  63. global expPix = "+";
  64. global gridPix = "\178";
  65. global block1Pix = "\176";
  66. global block2Pix = "\177";
  67. global block3Pix = "\219";
  68. global nmePix = "\232";
  69. global lifePix = "\3";
  70. global bombSizePix = "#";
  71. global bombExtraPix = "*";
  72. global spacePix = " ";
  73. //--------------------------------------------------------------------------------------------------
  74. // Colours
  75. //--------------------------------------------------------------------------------------------------
  76. global bgColour = 0;
  77. global fgColour = CA.F_RED | CA.F_GREEN;
  78. global playerColour = CA.F_GREEN | CA.F_BLUE;// | CA.F_INTENSITY;
  79. global gridColour = CA.F_RED;
  80. global blockColour = CA.F_RED | CA.F_GREEN | CA.F_INTENSITY;
  81. global nmeColour = CA.F_RED | CA.F_BLUE;
  82. global powerupColour = CA.F_GREEN | CA.F_INTENSITY;
  83. global puLifeColour = CA.F_RED;
  84. global statusColour = CA.F_RED | CA.F_GREEN;
  85. global bombColour = CA.F_BLUE | CA.F_INTENSITY;
  86. global expColourCount = 5;
  87. global expColours = array(expColourCount);
  88. global readyColour = CA.F_RED;
  89. expColours[0] = CA.F_RED | CA.F_INTENSITY;
  90. expColours[1] = CA.F_BLUE|CA.F_RED;
  91. expColours[2] = CA.F_RED|CA.F_GREEN | CA.F_INTENSITY;
  92. expColours[3] = CA.F_RED;
  93. expColours[4] = CA.F_RED|CA.F_GREEN;
  94. //--------------------------------------------------------------------------------------------------
  95. //--------------------------------------------------------------------------------------------------
  96. global IsPointWithin = function(a_ptx, a_pty, a_rx1, a_ry1, a_rx2, a_ry2)
  97. {
  98. return (a_ptx >= a_rx1 and a_ptx <= a_rx2 and a_pty >= a_ry1 and a_pty <= a_ry2);
  99. };
  100. global OverlapRect = function(a_r1x1, a_r1y1, a_r1x2, a_r1y2, a_r2x1, a_r2y1, a_r2x2, a_r2y2)
  101. {
  102. // Test one rect against the other.
  103. if (IsPointWithin(a_r2x1, a_r2y1, a_r1x1, a_r1y1, a_r1x2, a_r1y2) or
  104. IsPointWithin(a_r2x1, a_r2y2, a_r1x1, a_r1y1, a_r1x2, a_r1y2) or
  105. IsPointWithin(a_r2x2, a_r2y2, a_r1x1, a_r1y1, a_r1x2, a_r1y2) or
  106. IsPointWithin(a_r2x2, a_r2y1, a_r1x1, a_r1y1, a_r1x2, a_r1y2))
  107. {
  108. return true;
  109. }
  110. // Test the other rect.
  111. if (IsPointWithin(a_r1x1, a_r1y1, a_r2x1, a_r2y1, a_r2x2, a_r2y2) or
  112. IsPointWithin(a_r1x1, a_r1y2, a_r2x1, a_r2y1, a_r2x2, a_r2y2) or
  113. IsPointWithin(a_r1x2, a_r1y2, a_r2x1, a_r2y1, a_r2x2, a_r2y2) or
  114. IsPointWithin(a_r1x2, a_r1y1, a_r2x1, a_r2y1, a_r2x2, a_r2y2))
  115. {
  116. return true;
  117. }
  118. return false;
  119. };
  120. global ScreenClampX = function(a_x)
  121. {
  122. if (a_x < 0)
  123. {
  124. return 0;
  125. }
  126. else if (a_x >= screen.w)
  127. {
  128. return screen.w-1;
  129. }
  130. return a_x;
  131. };
  132. global ScreenClampY = function(a_y)
  133. {
  134. if (a_y < 0)
  135. {
  136. return 0;
  137. }
  138. else if (a_y >= screen.h)
  139. {
  140. return screen.h-1;
  141. }
  142. return a_y;
  143. };
  144. global ScreenClamp = function()
  145. {
  146. .x = ScreenClampX(.x);
  147. .y = ScreenClampY(.y);
  148. };
  149. global BombAt = function(a_x, a_y)
  150. {
  151. for (i = 0; i < player.nextBomb; i=i+1)
  152. {
  153. bomb = player.bombs[i];
  154. if (bomb.x == a_x and bomb.y == a_y)
  155. {
  156. return true;
  157. }
  158. }
  159. return false;
  160. };
  161. global PointOverlap = function(a_x1, a_y1, a_x2, a_y2)
  162. {
  163. return IsPointWithin(.x, .y, a_x1, a_y1, a_x2, a_y2);
  164. };
  165. //--------------------------------------------------------------------------------------------------
  166. // Player object.
  167. //--------------------------------------------------------------------------------------------------
  168. global Player = function()
  169. {
  170. newPlayer = table(x = -1, y = -1);
  171. newPlayer.bombSize = 1;
  172. newPlayer.bombFuse = bombFuse;
  173. newPlayer.bombs = array(maxPlayerBombs);
  174. newPlayer.maxBombs = 1;
  175. newPlayer.nextBomb = 0;
  176. newPlayer.threadId = -1;
  177. newPlayer.lastCanMoveThing = null;
  178. newPlayer.dead = false;
  179. newPlayer.lives = startLives;
  180. newPlayer.score = 0;
  181. newPlayer.threadId = -1;
  182. //------------------------------------
  183. //------------------------------------
  184. newPlayer.Draw = function()
  185. {
  186. CATTRIB(bgColour | playerColour);
  187. if (!.dead)
  188. {
  189. XYTEXT(.x, .y, playerPix);
  190. }
  191. else
  192. {
  193. XYTEXT(.x, .y, playerDeadPix);
  194. }
  195. };
  196. //------------------------------------
  197. //------------------------------------
  198. newPlayer.DrawStatus = function()
  199. {
  200. CATTRIB(bgColour | puLifeColour | CA.F_INTENSITY);
  201. XYTEXT(0, statusY, format("%s : %d ", lifePix, .lives));
  202. CATTRIB(bgColour | powerupColour);
  203. XYTEXT(10, statusY, format("%s : %d ", bombExtraPix, .maxBombs));
  204. XYTEXT(20, statusY, format("%s : %d ", bombSizePix, .bombSize));
  205. CATTRIB(bgColour | statusColour);
  206. XYTEXT(50, statusY, format("Score : %d ", .score));
  207. };
  208. newPlayer.AddScore = function(a_add)
  209. {
  210. .score = .score + a_add;
  211. .DrawStatus();
  212. };
  213. //------------------------------------
  214. //------------------------------------
  215. newPlayer.CanMove = function(a_x, a_y)
  216. {
  217. thing = GetThingAt(a_x, a_y, false);
  218. .lastCanMoveThing = thing;
  219. return thing.type == T_Space or thing.type == T_Explosion or
  220. thing.type == T_Powerup or thing.type == T_Enemy;
  221. };
  222. //------------------------------------
  223. //------------------------------------
  224. newPlayer.Move = function(a_dx, a_dy)
  225. {
  226. if (!.dead)
  227. {
  228. oldX = .x;
  229. oldY = .y;
  230. newX = ScreenClampX(.x + a_dx);
  231. newY = ScreenClampY(.y + a_dy);
  232. if (.CanMove(newX, newY))
  233. {
  234. .x = newX;
  235. .y = newY;
  236. if (.lastCanMoveThing.type == T_Powerup)
  237. {
  238. .lastCanMoveThing.thing.Pickup();
  239. }
  240. else if (.lastCanMoveThing.type == T_Explosion or .lastCanMoveThing.type == T_Enemy)
  241. {
  242. .Kill();
  243. }
  244. RefreshXY(oldX, oldY);
  245. RefreshXY(.x, .y);
  246. }
  247. }
  248. };
  249. //------------------------------------
  250. //------------------------------------
  251. newPlayer.Kill = function()
  252. {
  253. .dead = true;
  254. RefreshXY(.x, .y);
  255. };
  256. //------------------------------------
  257. //------------------------------------
  258. newPlayer.DropBomb = function()
  259. {
  260. if (!.dead and .nextBomb < .maxBombs and !BombAt(.x, .y))
  261. {
  262. newBomb = Bomb(.x, .y, .bombSize, .bombFuse, this);
  263. .bombs[.nextBomb] = newBomb;
  264. .nextBomb = .nextBomb + 1;
  265. newBomb.Draw();
  266. }
  267. };
  268. //------------------------------------
  269. //------------------------------------
  270. newPlayer.FreeBomb = function(a_bomb)
  271. {
  272. found = false;
  273. limit = .nextBomb;
  274. for (i = 0; i < limit; i=i+1)
  275. {
  276. if (.bombs[i] == a_bomb)
  277. {
  278. found = true;
  279. .nextBomb = .nextBomb - 1;
  280. }
  281. if (found)
  282. {
  283. if (i+1 < limit)
  284. {
  285. .bombs[i] = .bombs[i+1];
  286. }
  287. else
  288. {
  289. .bombs[i] = null;
  290. }
  291. }
  292. }
  293. };
  294. //------------------------------------
  295. //------------------------------------
  296. newPlayer.StartThread = function()
  297. {
  298. this:stateSet(.IdleState);
  299. };
  300. //------------------------------------
  301. //------------------------------------
  302. newPlayer.IdleState = function()
  303. {
  304. while (!quit)
  305. {
  306. pressed = false;
  307. if (ISPRESSED(38))
  308. {
  309. .Move(0, -1);
  310. pressed = true;
  311. }
  312. else if (ISPRESSED(40))
  313. {
  314. .Move(0, 1);
  315. pressed = true;
  316. }
  317. else if (ISPRESSED(39))
  318. {
  319. .Move(1, 0);
  320. pressed = true;
  321. }
  322. else if (ISPRESSED(37))
  323. {
  324. .Move(-1, 0);
  325. pressed = true;
  326. }
  327. else if (ISPRESSED(' '))
  328. {
  329. .DropBomb();
  330. pressed = true;
  331. }
  332. if (pressed)
  333. {
  334. sleep(0.075);
  335. }
  336. else if (.dead)
  337. {
  338. this:stateSet(.DeadState);
  339. }
  340. else
  341. {
  342. yield();
  343. }
  344. }
  345. };
  346. //------------------------------------
  347. //------------------------------------
  348. newPlayer.DeadState = function()
  349. {
  350. sleep(explodeTime);
  351. if (.lives > 0)
  352. {
  353. .lives = .lives - 1;
  354. }
  355. if (.maxBombs > 1)
  356. {
  357. .maxBombs = .maxBombs - 1;
  358. }
  359. if (.bombSize > 1)
  360. {
  361. .bombSize = .bombSize - 1;
  362. }
  363. .DrawStatus();
  364. while (!quit)
  365. {
  366. if (.lives > 0 and ISPRESSED(' '))
  367. {
  368. while (!quit)
  369. {
  370. pos = .GetStartPos();
  371. thing = GetThingAt(pos.x, pos.y, false);
  372. if (thing.type == T_Enemy)
  373. {
  374. thing.thing.Kill();
  375. }
  376. sleep(0.2);
  377. oldX = .x;
  378. oldY = .y;
  379. .x = pos.x;
  380. .y = pos.y;
  381. .dead = false;
  382. RefreshXY(oldX, oldY);
  383. RefreshXY(.x, .y);
  384. this:stateSet(.IdleState);
  385. }
  386. }
  387. yield();
  388. }
  389. };
  390. //------------------------------------
  391. //------------------------------------
  392. newPlayer.Overlap = PointOverlap;
  393. //------------------------------------
  394. //------------------------------------
  395. newPlayer.Cheat = function()
  396. {
  397. .lives = 5;
  398. .maxBombs = 10;
  399. .bombSize = 5;
  400. .DrawStatus();
  401. };
  402. newPlayer.GetStartPos = function()
  403. {
  404. // Position near centre.
  405. ptx = grid.startX + (grid.rows/2)*grid.spaceX;
  406. pty = grid.startY + (grid.cols/2)*grid.spaceY;
  407. return table(x = ptx, y = pty);
  408. };
  409. pos = newPlayer.GetStartPos();
  410. newPlayer.x = pos.x;
  411. newPlayer.y = pos.y;
  412. newPlayer.Start = function()
  413. {
  414. .threadId = this:thread(.StartThread);
  415. };
  416. newPlayer.Stop = function()
  417. {
  418. threadKill(.threadId);
  419. };
  420. return newPlayer;
  421. };
  422. //--------------------------------------------------------------------------------------------------
  423. // Bomb object.
  424. //--------------------------------------------------------------------------------------------------
  425. global Bomb = function(a_x, a_y, a_size, a_fuse, a_owner)
  426. {
  427. newBomb = table(x = a_x, y = a_y, size = a_size, fuse = a_fuse, owner = a_owner);
  428. newBomb.explode = false;
  429. newBomb.expMinX = 0;
  430. newBomb.expMaxX = 0;
  431. newBomb.expMinY = 0;
  432. newBomb.expMaxY = 0;
  433. newBomb.visible = true;
  434. newBomb.threadId = -1;
  435. newBomb.CountDown = function()
  436. {
  437. this:stateSet(.FuseState);
  438. };
  439. newBomb.Explode = function()
  440. {
  441. this:stateSetOnThread(.threadId, .ExplodeState);
  442. };
  443. newBomb.FuseState = function()
  444. {
  445. sleep(.fuse);
  446. this:stateSet(.ExplodeState);
  447. };
  448. newBomb.ExplodeState = function()
  449. {
  450. .expMinX = ScreenClampX(.x - .size);
  451. .expMaxX = ScreenClampX(.x + .size);
  452. .expMinY = ScreenClampY(.y - .size);
  453. .expMaxY = ScreenClampY(.y + .size);
  454. .explode = true;
  455. .visible = false;
  456. .KillStuff();
  457. .visible = true;
  458. .Draw();
  459. count = 1+g_count;
  460. inc = explodeCycle/explodeTime;
  461. for (i = 0; i < explodeTime; i = i + inc)
  462. {
  463. sleep(explodeCycle);
  464. .Draw();
  465. }
  466. .visible = false;
  467. RefreshRect(.expMinX, .expMinY, .expMaxX - .expMinX + 1, .expMaxY - .expMinY + 1);
  468. if (.owner != null)
  469. {
  470. .owner.FreeBomb(this);
  471. }
  472. exit();
  473. };
  474. newBomb.KillStuff = function()
  475. {
  476. // Kill stuff.
  477. for (x = .x; x >= .expMinX; x=x-1)
  478. {
  479. if (!.TryKill(GetThingAt(x, .y, true)))
  480. {
  481. .expMinX = x;
  482. break;
  483. }
  484. }
  485. for (x = .x+1; x <= .expMaxX; x=x+1)
  486. {
  487. if (!.TryKill(GetThingAt(x, .y, true)))
  488. {
  489. .expMaxX = x;
  490. break;
  491. }
  492. }
  493. for (y = .y; y >= .expMinY; y=y-1)
  494. {
  495. if (!.TryKill(GetThingAt(.x, y, true)))
  496. {
  497. .expMinY = y;
  498. break;
  499. }
  500. }
  501. for (y = .y+1; y <= .expMaxY; y=y+1)
  502. {
  503. if (!.TryKill(GetThingAt(.x, y, true)))
  504. {
  505. .expMaxY = y;
  506. break;
  507. }
  508. }
  509. };
  510. newBomb.TryKill = function(a_thing)
  511. {
  512. if (a_thing.type == T_Block)
  513. {
  514. a_thing.thing.Kill();
  515. return false;
  516. }
  517. else if (a_thing.type == T_Bomb and a_thing.thing != this)
  518. {
  519. a_thing.thing.Explode();
  520. }
  521. else if (a_thing.type == T_Player or a_thing.type == T_Enemy)
  522. {
  523. a_thing.thing.Kill();
  524. }
  525. return true;
  526. };
  527. newBomb.Draw = function()
  528. {
  529. if (.visible)
  530. {
  531. if (.explode)
  532. {
  533. CATTRIB(bgColour | expColours[randint(0, expColourCount)]);
  534. for (x = .expMinX; x <= .expMaxX; x=x+1)
  535. {
  536. if (IsSpaceOnGrid(x, .y))
  537. {
  538. XYTEXT(x, .y, expPix);
  539. }
  540. }
  541. for (y = .expMinY; y <= .expMaxY; y=y+1)
  542. {
  543. if (IsSpaceOnGrid(.x, y))
  544. {
  545. XYTEXT(.x, y, expPix);
  546. }
  547. }
  548. }
  549. else
  550. {
  551. CATTRIB(bgColour | bombColour);
  552. XYTEXT(.x, .y, bombPix);
  553. }
  554. }
  555. };
  556. newBomb.Overlap = function(a_x1, a_y1, a_x2, a_y2)
  557. {
  558. if (.explode)
  559. {
  560. return OverlapRect(.expMinX, .y, .expMaxX, .y+1, a_x1, a_y1, a_x2, a_y2) and OverlapRect(.x, .expMinY, .x+1, .expMaxY, a_x1, a_y1, a_x2, a_y2);
  561. }
  562. return IsPointWithin(.x, .y, a_x1, a_y1, a_x2, a_y2);
  563. };
  564. newBomb.FuseThread = function()
  565. {
  566. sleep(.fuse);
  567. .Explode();
  568. };
  569. newBomb.threadId = newBomb:thread(newBomb.CountDown);
  570. newBomb:thread(newBomb.FuseThread);
  571. return newBomb;
  572. };
  573. //--------------------------------------------------------------------------------------------------
  574. // Block code.
  575. //--------------------------------------------------------------------------------------------------
  576. global Block = function(a_x, a_y)
  577. {
  578. newBlock = table(x = a_x, y = a_y, visible = true);
  579. newBlock.hits = 1;
  580. newBlock.Draw = function()
  581. {
  582. if (.visible)
  583. {
  584. CATTRIB(bgColour | blockColour);
  585. if (.hits == 3)
  586. {
  587. XYTEXT(.x, .y, block3Pix);
  588. }
  589. else if (.hits == 2)
  590. {
  591. XYTEXT(.x, .y, block2Pix);
  592. }
  593. else
  594. {
  595. XYTEXT(.x, .y, block1Pix);
  596. }
  597. }
  598. };
  599. newBlock.Overlap = PointOverlap;
  600. newBlock.KillThread = function()
  601. {
  602. yield();
  603. yield();
  604. if (.visible)
  605. {
  606. .visible = false;
  607. player.AddScore(scoreBlock);
  608. if (randint(0, 100) < powerupChance)
  609. {
  610. AddPowerup(.x, .y);
  611. }
  612. }
  613. };
  614. newBlock.Kill = function()
  615. {
  616. .hits = .hits - 1;
  617. if (.hits == 0)
  618. {
  619. this:thread(.KillThread);
  620. }
  621. RefreshXY(.x, .y);
  622. };
  623. return newBlock;
  624. };
  625. global CreateBlocks = function(a_num)
  626. {
  627. global maxBlockHits;
  628. global blocks = table(count = 0, blocks = array(a_num));
  629. for (i = 0; i < a_num; i=i+1)
  630. {
  631. pos = GetRandomFreePos(DT_Block, true);
  632. if (pos.x != -1 and pos.y != -1)
  633. {
  634. thing = GetThingAt(pos.x, pos.y, false);
  635. if (thing.type == DT_Block)
  636. {
  637. if (thing.thing.hits < maxBlockHits)
  638. {
  639. thing.thing.hits = thing.thing.hits + 1;
  640. }
  641. }
  642. else
  643. {
  644. blocks.blocks[i] = Block(pos.x, pos.y);
  645. blocks.count = i;
  646. }
  647. }
  648. }
  649. blocks.count = a_num;
  650. };
  651. //--------------------------------------------------------------------------------------------------
  652. // Powerup.
  653. //--------------------------------------------------------------------------------------------------
  654. global Powerup = function(a_x, a_y, a_type)
  655. {
  656. newPu = table(x = a_x, y = a_y, type = a_type);
  657. if (a_type == PT_Bomb)
  658. {
  659. newPu.Draw = function()
  660. {
  661. CATTRIB(bgColour | powerupColour);
  662. XYTEXT(.x, .y, bombExtraPix);
  663. };
  664. newPu.Pickup = function()
  665. {
  666. if (player.maxBombs < maxPlayerBombs)
  667. {
  668. player.maxBombs = player.maxBombs + 1;
  669. }
  670. player.DrawStatus();
  671. RemovePowerup(this);
  672. };
  673. }
  674. else if (a_type == PT_Size)
  675. {
  676. newPu.Draw = function()
  677. {
  678. CATTRIB(bgColour | powerupColour);
  679. XYTEXT(.x, .y, bombSizePix);
  680. };
  681. newPu.Pickup = function()
  682. {
  683. if (player.bombSize < maxPlayerSize)
  684. {
  685. player.bombSize = player.bombSize + 1;
  686. }
  687. player.DrawStatus();
  688. RemovePowerup(this);
  689. };
  690. }
  691. else if (a_type == PT_Life)
  692. {
  693. newPu.Draw = function()
  694. {
  695. CATTRIB(bgColour | puLifeColour);
  696. XYTEXT(.x, .y, lifePix);
  697. };
  698. newPu.Pickup = function()
  699. {
  700. if (player.lives < maxLives)
  701. {
  702. player.lives = player.lives + 1;
  703. }
  704. player.DrawStatus();
  705. RemovePowerup(this);
  706. };
  707. }
  708. else
  709. {
  710. newPu.Draw = function()
  711. {
  712. };
  713. newPu.Pickup = function()
  714. {
  715. RemovePowerup(this);
  716. };
  717. }
  718. newPu.Overlap = PointOverlap;
  719. return newPu;
  720. };
  721. //--------------------------------------------------------------------------------------------------
  722. // Powerup management.
  723. //--------------------------------------------------------------------------------------------------
  724. global RandomPowerupType = function()
  725. {
  726. int = randint(0, 100);
  727. if (int < 49)
  728. {
  729. return PT_Bomb;
  730. }
  731. if (int < 98)
  732. {
  733. return PT_Size;
  734. }
  735. return PT_Life;
  736. };
  737. global AddPowerup = function(a_x, a_y)
  738. {
  739. if (powerups.count < maxPowerups)
  740. {
  741. powerups.powerups[powerups.count] = Powerup(a_x, a_y, RandomPowerupType());
  742. powerups.count = powerups.count + 1;
  743. RefreshXY(a_x, a_y);
  744. }
  745. };
  746. global RemovePowerup = function(a_pu)
  747. {
  748. found = false;
  749. count = powerups.count;
  750. for (i = 0; i < count; i = i + 1)
  751. {
  752. if (powerups.powerups[i] == a_pu)
  753. {
  754. found = true;
  755. powerups.powerups[i] = null;
  756. powerups.count = powerups.count - 1;
  757. }
  758. if (found)
  759. {
  760. if (i+1 < count)
  761. {
  762. powerups.powerups[i] = powerups.powerups[i+1];
  763. }
  764. else
  765. {
  766. powerups.powerups[i] = null;
  767. }
  768. }
  769. }
  770. };
  771. global InitPowerups = function()
  772. {
  773. global powerups = table(count = 0, powerups = array(maxPowerups));
  774. };
  775. //--------------------------------------------------------------------------------------------------
  776. // Enemies.
  777. //--------------------------------------------------------------------------------------------------
  778. global CreateEnemies = function(a_num)
  779. {
  780. global enemies = table(count = 0, enemies = array(a_num));
  781. for (i = 0; i < a_num; i=i+1)
  782. {
  783. pos = GetRandomFreePos(DT_Enemy, false);
  784. if (pos.x != -1 and pos.y != -1)
  785. {
  786. enemies.enemies[i] = Enemy(pos.x, pos.y);
  787. enemies.count = i+1;
  788. }
  789. }
  790. };
  791. global Enemy = function(a_x, a_y)
  792. {
  793. newEnemy = table(x = a_x, y = a_y, dead = false);
  794. newEnemy.lastCanMoveThing = null;
  795. newEnemy.lastPos = table(x = a_x, y = a_y);
  796. newEnemy.threadId = -1;
  797. //------------------------------------
  798. //------------------------------------
  799. newEnemy.Draw = function()
  800. {
  801. if (!.dead)
  802. {
  803. CATTRIB(bgColour | nmeColour);
  804. XYTEXT(.x, .y, nmePix);
  805. }
  806. };
  807. //------------------------------------
  808. //------------------------------------
  809. newEnemy.Kill = function()
  810. {
  811. player.AddScore(scoreNME);
  812. .dead = true;
  813. if (randint(0, 100) < powerupChance)
  814. {
  815. AddPowerup(.x, .y);
  816. }
  817. RefreshXY(.x, .y);
  818. };
  819. //------------------------------------
  820. //------------------------------------
  821. newEnemy.Overlap = PointOverlap;
  822. //------------------------------------
  823. // Movement.
  824. //------------------------------------
  825. newEnemy.CanMove = function(a_x, a_y)
  826. {
  827. if (a_x < 0 or a_x >= screen.w or a_y < 0 or a_y > screen.h)
  828. {
  829. return false;
  830. }
  831. thing = GetThingAt(a_x, a_y, false);
  832. .lastCanMoveThing = thing;
  833. return thing.type == T_Space or thing.type == T_Exlposion or
  834. thing.type == T_Powerup or thing.type == T_Player;
  835. };
  836. //------------------------------------
  837. //------------------------------------
  838. newEnemy.MoveX = function()
  839. {
  840. // Is the player on the same column?
  841. if (.y == player.y)
  842. {
  843. // Are we within a grid spacing?
  844. if (player.x - .x <= grid.spaceX + 1)
  845. {
  846. if (.x < player.x)
  847. {
  848. start = .x+1;
  849. end = player.x+1;
  850. moveX = start;
  851. }
  852. else
  853. {
  854. start = player.x+1;
  855. end = .x;
  856. moveX = end-1;
  857. }
  858. // Do we have a clear path.
  859. moveOk = true;
  860. for (x = start; moveOk and x < end; x=x+1)
  861. {
  862. if (!.CanMove(x, .y))
  863. {
  864. moveOk = false;
  865. }
  866. }
  867. if (moveOk and .CanMove(moveX, .y))
  868. {
  869. .MoveTo(moveX, .y);
  870. return true;
  871. }
  872. }
  873. }
  874. mx = 1;
  875. if (player.x < .x)
  876. {
  877. mx = -1;
  878. }
  879. if ((.x+mx != .lastPos.x or .y != .lastPos.y) and .CanMove(.x+mx, .y))
  880. {
  881. .MoveTo(.x+mx, .y);
  882. return true;
  883. }
  884. return false;
  885. };
  886. //------------------------------------
  887. //------------------------------------
  888. newEnemy.MoveY = function()
  889. {
  890. // Is the player on the same row?
  891. if (.x == player.x)
  892. {
  893. // Are we within a grid spacing?
  894. if (player.y - .y <= grid.spaceY + 1)
  895. {
  896. if (.y < player.y)
  897. {
  898. start = .y+1;
  899. end = player.y+1;
  900. moveY = start;
  901. }
  902. else
  903. {
  904. start = player.y+1;
  905. end = .y;
  906. moveY = end-1;
  907. }
  908. // Do we have a clear path.
  909. moveOk = true;
  910. for (y = start; moveOk and y < end; y=y+1)
  911. {
  912. if (!.CanMove(.x, y))
  913. {
  914. moveOk = false;
  915. }
  916. }
  917. if (moveOk and .CanMove(.x, moveY))
  918. {
  919. .MoveTo(.x, moveY);
  920. return true;
  921. }
  922. }
  923. }
  924. my = 1;
  925. if (player.y < .y)
  926. {
  927. my = -1;
  928. }
  929. if ((.x != .lastPos.x or .y+my != .lastPos.y) and .CanMove(.x, .y+my))
  930. {
  931. .MoveTo(.x, .y+my);
  932. return true;
  933. }
  934. return false;
  935. };
  936. //------------------------------------
  937. //------------------------------------
  938. newEnemy.MoveTo = function(a_x, a_y)
  939. {
  940. .lastPos.x = .x;
  941. .lastPos.y = .y;
  942. thing = GetThingAt(a_x, a_y, false);
  943. .x = a_x;
  944. .y = a_y;
  945. if (thing.type == T_Player)
  946. {
  947. player.Kill();
  948. }
  949. else if (thing.type == T_Explosion)
  950. {
  951. .Kill();
  952. }
  953. RefreshXY(.lastPos.x, .lastPos.y);
  954. RefreshXY(.x, .y);
  955. };
  956. //------------------------------------
  957. //------------------------------------
  958. newEnemy.Move = function()
  959. {
  960. moved = false;
  961. if (!player.dead)
  962. {
  963. // Try move towards the player.
  964. preferX = abs(player.x - .x) > abs(player.y - .y);
  965. if (preferX)
  966. {
  967. moved = .MoveX();
  968. if (!moved)
  969. {
  970. moved = .MoveY();
  971. }
  972. }
  973. else
  974. {
  975. moved = .MoveY();
  976. if (!moved)
  977. {
  978. moved = .MoveX();
  979. }
  980. }
  981. // Try move away from the last position.
  982. if (!moved)
  983. {
  984. testX = 2*.x - .lastPos.x;
  985. testY = 2*.y - .lastPos.y;
  986. if (.CanMove(testX, testY))
  987. {
  988. .MoveTo(testX, testY);
  989. moved = true;
  990. }
  991. }
  992. }
  993. if (!moved and (.lastPos.x != .x or .lastPos.y != .y) and .CanMove(.lastPos.x, .lastPos.y))
  994. {
  995. .MoveTo(.lastPos.x, .lastPos.y);
  996. }
  997. };
  998. //------------------------------------
  999. // Thread functions and states.
  1000. //------------------------------------
  1001. newEnemy.Start = function()
  1002. {
  1003. .threadId = this:thread(.IdleState);
  1004. };
  1005. //------------------------------------
  1006. //------------------------------------
  1007. newEnemy.IdleState = function()
  1008. {
  1009. while (!quit and !.dead)
  1010. {
  1011. sleep(nmeMoveTime);
  1012. .Move();
  1013. }
  1014. };
  1015. newEnemy.Start();
  1016. return newEnemy;
  1017. };
  1018. //--------------------------------------------------------------------------------------------------
  1019. // Refresh functions.
  1020. //--------------------------------------------------------------------------------------------------
  1021. global Refresh = function()
  1022. {
  1023. CATTRIB(bgColour | fgColour);
  1024. CLS();
  1025. // Draw blocks.
  1026. for (b = 0; b < blocks.count; b=b+1)
  1027. {
  1028. blocks.blocks[b].Draw();
  1029. }
  1030. // Draw powerups.
  1031. for (p = 0; p < powerups.count; p=p+1)
  1032. {
  1033. powerups.powerups[p].Draw();
  1034. }
  1035. // Draw enemies.
  1036. for (e = 0; e < enemies.count; e=e+1)
  1037. {
  1038. enemies.enemies[e].Draw();
  1039. }
  1040. // Draw bombs.
  1041. for (b = 0; b < player.nextBomb; b=b+1)
  1042. {
  1043. player.bombs[b].Draw();
  1044. }
  1045. player.Draw();
  1046. player.DrawStatus();
  1047. DrawGrid();
  1048. };
  1049. global RefreshXY = function(a_x, a_y)
  1050. {
  1051. RefreshRect(a_x, a_y, 1, 1);
  1052. };
  1053. global RefreshRect = function(a_x, a_y, a_w, a_h)
  1054. {
  1055. // Clear the area.
  1056. xLimit = a_x + a_w;
  1057. yLimit = a_y + a_h;
  1058. CATTRIB(bgColour | fgColour);
  1059. for (x = a_x; x < xLimit; x=x+1)
  1060. {
  1061. for (y = a_y; y < yLimit; y=y+1)
  1062. {
  1063. XYTEXT(x, y, spacePix);
  1064. }
  1065. }
  1066. // Draw blocks.
  1067. for (b = 0; b < blocks.count; b=b+1)
  1068. {
  1069. blk = blocks.blocks[b];
  1070. if (blk.Overlap(a_x, a_y, xLimit, yLimit))
  1071. {
  1072. blk.Draw();
  1073. }
  1074. }
  1075. // Draw powerups.
  1076. for (p = 0; p < powerups.count; p=p+1)
  1077. {
  1078. pu = powerups.powerups[p];
  1079. if (pu.Overlap(a_x, a_y, xLimit, yLimit))
  1080. {
  1081. pu.Draw();
  1082. }
  1083. }
  1084. // Draw enemies.
  1085. for (e = 0; e < enemies.count; e=e+1)
  1086. {
  1087. nme = enemies.enemies[e];
  1088. if (nme.Overlap(a_x, a_y, xLimit, yLimit))
  1089. {
  1090. nme.Draw();
  1091. }
  1092. }
  1093. // Draw bombs.
  1094. for (b = 0; b < player.nextBomb; b=b+1)
  1095. {
  1096. bomb = player.bombs[b];
  1097. if (bomb.Overlap(a_x, a_y, xLimit, yLimit))
  1098. {
  1099. bomb.Draw();
  1100. }
  1101. }
  1102. if (player.Overlap(a_x, a_y, xLimit, yLimit))
  1103. {
  1104. player.Draw();
  1105. }
  1106. DrawGridRect(a_x, a_y, a_w, a_h);
  1107. };
  1108. //--------------------------------------------------------------------------------------------------
  1109. // Grid control.
  1110. //--------------------------------------------------------------------------------------------------
  1111. global Grid = function(a_startX, a_startY, a_spaceX, a_spaceY)
  1112. {
  1113. grid.startX = a_startX;
  1114. grid.startY = a_startY;
  1115. grid.spaceX = a_spaceX;
  1116. grid.spaceY = a_spaceY;
  1117. grid.rows = (screen.w-grid.startX) / (grid.spaceX + 1);
  1118. grid.cols = (screen.h-grid.startY) / (grid.spaceY + 1);
  1119. if ((screen.w-grid.startX) % (grid.spaceX + 1) != 0)
  1120. {
  1121. grid.rows = grid.rows + 1;
  1122. }
  1123. if ((screen.h-grid.startY) % (grid.spaceY + 1) != 0)
  1124. {
  1125. grid.cols = grid.cols + 1;
  1126. }
  1127. };
  1128. global DrawGrid = function()
  1129. {
  1130. DrawGridRect(0, 0, screen.w, screen.h);
  1131. };
  1132. global DrawGridRect = function(a_startX, a_startY, a_w, a_h)
  1133. {
  1134. xLimit = a_startX + a_w;
  1135. yLimit = a_startY + a_h;
  1136. CATTRIB(bgColour | gridColour);
  1137. for (x = a_startX; x < xLimit; x=x+1)
  1138. {
  1139. for (y = a_startY; y < yLimit; y=y+1)
  1140. {
  1141. if (!IsSpaceOnGrid(x, y))
  1142. {
  1143. XYTEXT(x, y, gridPix);
  1144. }
  1145. }
  1146. }
  1147. };
  1148. global IsSpaceOnGrid = function(a_x, a_y)
  1149. {
  1150. return (a_x - grid.startX) % (grid.spaceX+1) == 0 or (a_y - grid.startY) % (grid.spaceY+1) == 0;
  1151. };
  1152. global IsFreePos = function(a_x, a_y, a_allowBlocks)
  1153. {
  1154. thing = GetThingAt(a_x, a_y, true);
  1155. return thing.type == T_Space or (a_allowBlocks and thing.type == T_Block);
  1156. };
  1157. global GetThingAt = function(a_x, a_y, a_ignoreExplosion)
  1158. {
  1159. if (!IsSpaceOnGrid(a_x, a_y))
  1160. {
  1161. return table(thing = grid, type = T_Grid);
  1162. }
  1163. // Test blocks
  1164. for (b = 0; b < blocks.count; b=b+1)
  1165. {
  1166. blk = blocks.blocks[b];
  1167. if (blk.visible and blk.x == a_x and blk.y == a_y)
  1168. {
  1169. return table(thing = blk, type = T_Block);
  1170. }
  1171. }
  1172. // Test enemies.
  1173. for (e = 0; e < enemies.count; e=e+1)
  1174. {
  1175. nme = enemies.enemies[e];
  1176. if (!nme.dead and nme.x == a_x and nme.y == a_y)
  1177. {
  1178. return table(thing = nme, type = T_Enemy);
  1179. }
  1180. }
  1181. // Test player pos.
  1182. if (!player.dead and a_x == player.x and a_y == player.y)
  1183. {
  1184. return table(thing = player, type = T_Player);
  1185. }
  1186. // Test bombs.
  1187. for (b = 0; b < player.nextBomb; b=b+1)
  1188. {
  1189. bomb = player.bombs[b];
  1190. if (!bomb.explode)
  1191. {
  1192. if (bomb.x == a_x and bomb.y == a_y)
  1193. {
  1194. return table(thing = bomb, type = T_Bomb);
  1195. }
  1196. }
  1197. else if (!a_ignoreExplosion and bomb.Overlap(a_x, a_y, a_x+1, a_y+1))
  1198. {
  1199. return table(thing = bomb, type = T_Explosion);
  1200. }
  1201. }
  1202. // Test powerups.
  1203. for (p = 0; p < powerups.count; p=p+1)
  1204. {
  1205. pu = powerups.powerups[p];
  1206. if (pu.x == a_x and pu.y == a_y)
  1207. {
  1208. return table(thing = pu, type = T_Powerup);
  1209. }
  1210. }
  1211. return table(thing = null, type = T_Space);
  1212. };
  1213. global InDeadZone = function(a_dtType, a_x, a_y)
  1214. {
  1215. if (a_dtType == DT_Block)
  1216. {
  1217. return IsPointWithin(a_x, a_y, blockDeadZone.x1, blockDeadZone.y1, blockDeadZone.x2, blockDeadZone.y2);
  1218. }
  1219. if (a_dtType == DT_Enemy)
  1220. {
  1221. return IsPointWithin(a_x, a_y, enemyDeadZone.x1, enemyDeadZone.y1, enemyDeadZone.x2, enemyDeadZone.y2);
  1222. }
  1223. return false;
  1224. };
  1225. global GetRandomFreePos1 = function(a_deadZoneType, a_allowBlocks, a_tries)
  1226. {
  1227. row = randint(0, grid.rows);
  1228. col = randint(0, grid.cols);
  1229. px = row*grid.spaceX + grid.startX;
  1230. py = col*grid.spaceY + grid.startY;
  1231. if (a_deadZoneType != DT_None and InDeadZone(a_deadZoneType, px, py))
  1232. {
  1233. return GetRandomFreePos1(a_deadZoneType, a_tries);
  1234. }
  1235. if (IsFreePos(px, py))
  1236. {
  1237. return table(x = px, y = py);
  1238. }
  1239. while (py < screen.h)
  1240. {
  1241. py=py+1;
  1242. if ((a_deadZoneType == DT_None or !InDeadZone(a_deadZoneType, px, py)) and IsFreePos(px, py))
  1243. {
  1244. return table(x = px, y = py);
  1245. }
  1246. }
  1247. if (tries < 5)
  1248. {
  1249. return GetRandomFreePos1(a_tries+1);
  1250. }
  1251. return table(x = -1, y = -1);
  1252. };
  1253. global GetRandomFreePos = function(a_deadZoneType, a_allowBlocks)
  1254. {
  1255. return GetRandomFreePos1(a_deadZoneType, a_allowBlocks, 0);
  1256. };
  1257. //--------------------------------------------------------------------------------------------------
  1258. // Initialisation.
  1259. //--------------------------------------------------------------------------------------------------
  1260. RenderRect = function(a_rect)
  1261. {
  1262. CATTRIB(bgColour | gridColour);
  1263. for (i = a_rect.x1; i <= a_rect.x2; i=i+1)
  1264. {
  1265. for (j = a_rect.y1; j <= a_rect.y2; j=j+1)
  1266. {
  1267. XYTEXT(i, j, "o");
  1268. }
  1269. }
  1270. };
  1271. MemThread = function()
  1272. {
  1273. while (!quit)
  1274. {
  1275. CATTRIB(bgColour | statusColour);
  1276. XYTEXT(65, statusY, format("Mem: %d ", sysGetMemoryUsage()));
  1277. sleep(1.0);
  1278. }
  1279. };
  1280. //--------------------------------------------------------------------------------------------------
  1281. // Level thread.
  1282. //--------------------------------------------------------------------------------------------------
  1283. global GameOver = function()
  1284. {
  1285. CATTRIB(bgColour | statusColour);
  1286. CLS();
  1287. local score = player.score;
  1288. KillAll();
  1289. sleep(0.3);
  1290. global quit;
  1291. while (!quit)
  1292. {
  1293. CATTRIB(bgColour | expColours[randint(0, expColourCount)]);
  1294. x = 8;
  1295. y = 8;
  1296. XYTEXT(x, y, "__________________________________________________________"); y=y+1;
  1297. XYTEXT(x, y, " __ __ "); y=y+1;
  1298. XYTEXT(x, y, " / ) / ) "); y=y+1;
  1299. XYTEXT(x, y, " / __ _ _ __ / / __ )__ "); y=y+1;
  1300. XYTEXT(x, y, " / --, / ) / / ) /___) / / | / /___) / )"); y=y+1;
  1301. XYTEXT(x, y, "_(____/___(___(_/_/__/_(___ ____(____/____|/__(___ _/_____"); y=y+1;
  1302. CATTRIB(bgColour | statusColour);
  1303. XYTEXT(0, statusY, format("Score : %d", score));
  1304. if (threadTime() < 1000 and ISPRESSED(' '))
  1305. {
  1306. stateSet(TitleScreenState);
  1307. }
  1308. else if (ISPRESSED(27))
  1309. {
  1310. quit = true;
  1311. }
  1312. sleep(randfloat(0.03, 0.3));
  1313. }
  1314. global player = null;
  1315. global blocks = null;
  1316. global enemies = null;
  1317. stateSet(TitleScreenState);
  1318. };
  1319. global GameState = function()
  1320. {
  1321. global maxLevel;
  1322. global player;
  1323. global blocks;
  1324. global enemies;
  1325. global gameLevel;
  1326. Grid(3, 2, 5, 5);
  1327. if (player == null or player.lives <= 0)
  1328. {
  1329. player = Player();
  1330. }
  1331. pos = player.GetStartPos();
  1332. player.x = pos.x;
  1333. player.y = pos.y;
  1334. global nmeMoveTime = 1.0 - gameLevel*0.1;
  1335. InitPowerups();
  1336. CreateBlocks(min(10 + 10*gameLevel, 99));
  1337. CreateEnemies(5*gameLevel);
  1338. yield();
  1339. Refresh();
  1340. yield();
  1341. player.Start();
  1342. local done = false;
  1343. while (!quit and !done)
  1344. {
  1345. local count;
  1346. done = true;
  1347. if (ISPRESSED(27))
  1348. {
  1349. global quit = true;
  1350. break;
  1351. }
  1352. /*
  1353. // Check blocks.
  1354. count = blocks.count;
  1355. for (i = 0; done and i < count; i=i+1)
  1356. {
  1357. blk = blocks.blocks[i];
  1358. if (blk.visible)
  1359. {
  1360. done = false;
  1361. }
  1362. }
  1363. */
  1364. // Check enemies.
  1365. count = enemies.count;
  1366. for (i = 0; done and i < count; i=i+1)
  1367. {
  1368. nme = enemies.enemies[i];
  1369. if (!nme.dead)
  1370. {
  1371. done = false;
  1372. }
  1373. }
  1374. // Check bombs.
  1375. done = done and player.nextBomb == 0;
  1376. // Check for lives.
  1377. done = done or player.lives <= 0;
  1378. sleep(0.3);
  1379. }
  1380. player.Stop();
  1381. if (!quit)
  1382. {
  1383. if (player.lives <= 0)
  1384. {
  1385. stateSet(GameOver);
  1386. }
  1387. global gameLevel;
  1388. gameLevel=gameLevel+1;
  1389. stateSet(LevelState);
  1390. }
  1391. KillAll();
  1392. };
  1393. global LevelState = function()
  1394. {
  1395. global maxLevel;
  1396. global gameLevel;
  1397. if (gameLevel > maxLevel)
  1398. {
  1399. gameLevel = maxLevel;
  1400. }
  1401. CATTRIB(bgColour | statusColour);
  1402. CLS();
  1403. sleep(0.3);
  1404. global quit;
  1405. while (!quit)
  1406. {
  1407. CATTRIB(bgColour | expColours[randint(0, expColourCount)]);
  1408. x = 17;
  1409. y = 8;
  1410. XYTEXT(x, y, "___________________________________________"); y=y+1;
  1411. XYTEXT(x, y, " ____ ___ "); y=y+1;
  1412. XYTEXT(x, y, " / ) / ( ) "); y=y+1;
  1413. XYTEXT(x, y, " /___ / __ __ __ / / "); y=y+1;
  1414. XYTEXT(x, y, " / | /___) / ) / / / / / "); y=y+1;
  1415. XYTEXT(x, y, "_/_____|__(___ _(___(_(___/___(___/__o_____"); y=y+1;
  1416. XYTEXT(x, y, " / "); y=y+1;
  1417. XYTEXT(x, y, " (_ / "); y=y+1;
  1418. if (threadTime() > 1000 and ISPRESSED(' '))
  1419. {
  1420. CLS();
  1421. sleep(0.5);
  1422. stateSet(GameState);
  1423. }
  1424. else if (ISPRESSED(27))
  1425. {
  1426. quit = true;
  1427. }
  1428. sleep(randfloat(0.03, 0.3));
  1429. }
  1430. KillAll();
  1431. };
  1432. global KillAll = function()
  1433. {
  1434. // Kill all threads.
  1435. global player;
  1436. global enemies;
  1437. global blocks;
  1438. if (player)
  1439. {
  1440. local count = player.nextBomb;
  1441. for (i = 0; i < count; i=i+1)
  1442. {
  1443. threadKill(player.bombs[i].threadId);
  1444. }
  1445. threadKill(player.threadId);
  1446. }
  1447. if (enemies)
  1448. {
  1449. count = enemies.count;
  1450. for (i = 0; i < count; i=i+1)
  1451. {
  1452. threadKill(enemies.enemies[i].threadId);
  1453. }
  1454. }
  1455. };
  1456. global TitleScreenState = function()
  1457. {
  1458. CATTRIB(bgColour | statusColour);
  1459. CLS();
  1460. sleep(0.3);
  1461. while (!quit)
  1462. {
  1463. CATTRIB(bgColour | expColours[randint(0, expColourCount)]);
  1464. x = 17;
  1465. y = 8;
  1466. XYTEXT(x, y, "_________________________________________"); y=y+1;
  1467. XYTEXT(x, y, " ____ "); y=y+1;
  1468. XYTEXT(x, y, " / ) / "); y=y+1;
  1469. XYTEXT(x, y, " /__ / __ _ _ /__ __ )__ "); y=y+1;
  1470. XYTEXT(x, y, " / ) / ) / / ) / ) /___) / )"); y=y+1;
  1471. XYTEXT(x, y, "_/____/___(___/_/_/__/_(___/_(___ _/_____"); y=y+1;
  1472. XYTEXT(x, y, "_________________________________________"); y=y+1;
  1473. if (ISPRESSED(27))
  1474. {
  1475. global quit = true;
  1476. break;
  1477. }
  1478. else if (ISPRESSED(' '))
  1479. {
  1480. global gameLevel = 1;
  1481. stateSet(LevelState);
  1482. }
  1483. sleep(randfloat(0.03, 0.3));
  1484. }
  1485. KillAll();
  1486. exit();
  1487. };
  1488. CURSOR(0, 0); // bool visible, percentage visible
  1489. CATTRIB(fgColour | bgColour);
  1490. thread(MemThread);
  1491. quit = false;
  1492. CLS();
  1493. stateSet(TitleScreenState);