rockout.bmx 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161
  1. ' -----------------------------------------------------------------------------
  2. ' RockOut -- Rocket BlockOut
  3. ' -----------------------------------------------------------------------------
  4. ' Public domain source code by James L Boyd (support @ blitzbasic . com)
  5. ' -----------------------------------------------------------------------------
  6. ' Rocket image © 2004 James L Boyd, with permission granted for freeware/PD use,
  7. ' not that anyone'd really want it anyway...!
  8. ' -----------------------------------------------------------------------------
  9. ' -----------------------------------------------------------------------------
  10. ' Constants...
  11. ' -----------------------------------------------------------------------------
  12. ' Sizes used for blocks...
  13. Const BLOCKWIDTH = 32
  14. Const BLOCKHEIGHT = 16
  15. Const GRAPHICS_WIDTH = 640
  16. Const GRAPHICS_HEIGHT = 480
  17. Const GW2 = GRAPHICS_WIDTH / 2
  18. Const GH2 = GRAPHICS_HEIGHT / 2
  19. Graphics 800,600,32,60
  20. SetVirtualResolution GRAPHICS_WIDTH,GRAPHICS_HEIGHT
  21. ' Pre-calc half of graphics width...
  22. ' -----------------------------------------------------------------------------
  23. ' Include media...
  24. ' -----------------------------------------------------------------------------
  25. ' Sounds (all from Yamaha RM1X!)...
  26. Incbin "sounds/shot.ogg" ' Player shot
  27. Incbin "sounds/fall.ogg" ' Block fall
  28. Incbin "sounds/hit.ogg" ' Block/player hit
  29. Incbin "sounds/beep.ogg" ' 'Press space' sound
  30. Incbin "sounds/gameover.ogg" ' Guess...
  31. ' Graphics...
  32. Incbin "gfx/boing.png" ' Rocket
  33. Incbin "gfx/land.png" ' Background (used to be land, now a grid)
  34. Incbin "gfx/shot.png" ' Player's shot
  35. Incbin "gfx/block.png" ' Guess...
  36. ' -----------------------------------------------------------------------------
  37. ' Types (object definitions)...
  38. ' -----------------------------------------------------------------------------
  39. ' GravityItem: all objects affected by gravity are based upon this...
  40. Type GravityItem
  41. ' ------------------------------------------------------------------------
  42. ' Type-specific globals...
  43. ' ------------------------------------------------------------------------
  44. ' Why not make these truly global? It's cleaner -- you can just copy and
  45. ' paste the type definition into a completely different program without
  46. ' having to remember which globals are related...
  47. Global GCount ' Count of all GravityItems (for debugging)
  48. Global GravityItemList:TList ' List used for all GravityItem objects
  49. Global Gravity# = 0.05 ' Gravity applied to all GravityItems
  50. ' ------------------------------------------------------------------------
  51. ' Type fields...
  52. ' ------------------------------------------------------------------------
  53. Field x# ' x position of object
  54. Field y# ' y position of object
  55. Field xs# ' x speed of object
  56. Field ys# ' y speed of object
  57. Field width ' Width of object
  58. Field height ' Height of object
  59. Field damage ' Damage caused by this item if it hits player
  60. Field fixed = False ' Is object fixed in place? Blocks are, at first...
  61. Field r, g, b
  62. ' ------------------------------------------------------------------------
  63. ' Type functions...
  64. ' ------------------------------------------------------------------------
  65. Function UpdateAll ()
  66. If GravityItemList = Null Then Return
  67. If Shadows_On Then Block.DrawShadows ' Shadows_On is a global...
  68. For g:GravityItem = EachIn GravityItemList
  69. g.Update
  70. g.Draw
  71. Next
  72. End Function
  73. ' ------------------------------------------------------------------------
  74. ' Type methods...
  75. ' ------------------------------------------------------------------------
  76. ' The New method is special -- Blitz calls it whenever a new object is
  77. ' created...
  78. ' Every time a new GravityItem is created -- including objects that extend
  79. ' GravityItem -- this is called. In this case, it creates the type-global
  80. ' list if it doesn't yet exist (only happens once), and adds the item to it...
  81. Method New ()
  82. If GravityItemList = Null Then GravityItemList = New TList
  83. GravityItemList.AddLast Self
  84. GCount = GCount + 1
  85. End Method
  86. ' Destroy current object and remove from list
  87. Method Destroy ()
  88. GravityItemList.Remove Self
  89. GCount = GCount - 1
  90. End Method
  91. ' Rectangle-based collision test of current object and player.
  92. ' 'The multiplier' parameter controls how much of an object's
  93. ' 'damage' field applies to the player -- in the case of Block
  94. ' objects, the more they're faded out, the less damage they do...
  95. ' The 'posyonly' parameter is a hack to stop Shot objects damaging
  96. ' the player while going up...
  97. Method PlayerCollide (multiplier# = 1, posyonly = 0)
  98. ' Offset x/y position of shots (all images' handles are centered)...
  99. ox = x - width / 2
  100. oy = y - height / 2
  101. ' Offset x/y position of player...
  102. opx = PlayerOne.x - PlayerOne.width / 2
  103. opy = PlayerOne.y - PlayerOne.height / 2
  104. ' Hack to stop Shot objects damaging player while going up...
  105. check = 1
  106. If posyonly
  107. If ys < 0
  108. check = 0
  109. EndIf
  110. EndIf
  111. ' Test for collision, apply damage and make explosion...
  112. If check
  113. If OverLap (ox, oy, ox + width, oy + height, opx, opy, opx + PlayerOne.width, opy + PlayerOne.height)
  114. PlayerOne.shields = PlayerOne.shields - damage * multiplier
  115. ExplosionParticle.Explode x, y, damage * 5 * multiplier
  116. PlayerOne.damaged = MilliSecs ()
  117. Return True
  118. EndIf
  119. EndIf
  120. End Method
  121. ' There is no default Draw method here, as it's different for each extended type
  122. ' of GravityItem, so I've defined it as Abstract...
  123. ' Abstract forces every type that extends GravityItem to have a Draw () method defined
  124. ' or the code simply won't compile...
  125. ' One practical use for this is that you can call Draw from any random GravityItem,
  126. ' regardless of which extended type it is, and this will call the correct Draw ()
  127. ' for the type of object in question...
  128. Method Draw () Abstract
  129. ' Abstract Update method for GravityItems. See Draw () explanation...
  130. Method Update () Abstract
  131. End Type
  132. ' Particles created in an explosion. This type extends GravityItem, meaning all
  133. ' properties of GravityItem apply, except where methods are over-ridden
  134. ' (ie. re-defined) here...
  135. Type ExplosionParticle Extends GravityItem
  136. ' ------------------------------------------------------------------------
  137. ' Type fields...
  138. ' ------------------------------------------------------------------------
  139. ' No need to define, x, y, xs, ys, etc as they're part of the GravityItem definition...
  140. Field alph# = 1.0 ' Alpha level of particle (translucency)
  141. ' ------------------------------------------------------------------------
  142. ' Type functions...
  143. ' ------------------------------------------------------------------------
  144. ' Create explosion of particles, and play sound...
  145. Function Explode (x#, y#, particles)
  146. ' NB. GW2 is a global set to half of GRAPHICS_WIDTH...
  147. If Sounds_On
  148. pan# = x / GW2 - 1.0
  149. play = CueSound (hit)
  150. SetChannelPan play, pan
  151. ResumeChannel play
  152. EndIf
  153. For loop = 1 To particles
  154. ExplosionParticle.Create (x, y)
  155. Next
  156. End Function
  157. ' Create single explosion particle. Note that any items extending GravityItem
  158. ' will call the New () method from GravityItem upon creation, so these will
  159. ' be added to the GravityItem list automatically...
  160. Function Create:ExplosionParticle (x, y)
  161. e:ExplosionParticle = New ExplosionParticle
  162. e.x = x
  163. e.y = y
  164. e.xs = Rnd (-8, 8)
  165. e.ys = Rnd (-8, 8)
  166. ' Random colour...
  167. Select Rand (0, 3)
  168. Case 0
  169. e.r = 255
  170. e.g = 255
  171. e.b = 255
  172. Case 1
  173. e.r = 255
  174. e.g = 127
  175. e.b = 0
  176. Case 2
  177. e.r = 255
  178. e.g = 255
  179. e.b = 0
  180. Case 3
  181. e.r = 255
  182. e.g = 0
  183. e.b = 0
  184. End Select
  185. ' Random size...
  186. size = Rand (1, 8)
  187. e.width = size
  188. e.height = size
  189. End Function
  190. ' ------------------------------------------------------------------------
  191. ' Type methods...
  192. ' ------------------------------------------------------------------------
  193. ' Update () over-rides the GravityItem Update () method...
  194. Method Update ()
  195. ' Reduce alpha level of particle...
  196. alph = alph - 0.01
  197. ' Apply Gravity global (see GravityItem) to y speed...
  198. ys = ys + Gravity
  199. ' Move particle by current speed...
  200. x = x + xs
  201. y = y + ys
  202. ' If off-screen or reduced to invisible, remove from list by
  203. ' calling the Destroy method (inherited from GravityItem)...
  204. If y > GRAPHICS_HEIGHT Or alph = 0 Then Destroy
  205. End Method
  206. ' Draw particle...
  207. Method Draw ()
  208. SetScale 1, 1
  209. SetBlend ALPHABLEND
  210. SetAlpha alph
  211. SetColor r, g, b
  212. DrawRect x, y, width, height
  213. End Method
  214. End Type
  215. ' Block definition. Again, Block is a kind of GravityItem...
  216. Type Block Extends GravityItem
  217. ' ------------------------------------------------------------------------
  218. ' Type-specific globals...
  219. ' ------------------------------------------------------------------------
  220. Global BCount ' Number of blocks
  221. ' ------------------------------------------------------------------------
  222. ' Type-specific fields...
  223. ' ------------------------------------------------------------------------
  224. Field alph# = 1.0 ' Alpha level of block
  225. Field ang# ' Rotation of block
  226. Field angspeed# ' Rotation speed of block
  227. Field desty#
  228. ' ------------------------------------------------------------------------
  229. ' Type-specific function...
  230. ' ------------------------------------------------------------------------
  231. ' Create a Block object (added to GravityItem list automatically)...
  232. Function Create:Block (x, y)
  233. blk:Block = New Block
  234. blk.x = x
  235. blk.y = y
  236. blk.desty = y
  237. blk.width = BLOCKWIDTH
  238. blk.height = BLOCKHEIGHT
  239. blk.fixed = True
  240. blk.damage = 20
  241. BCount = BCount + 1
  242. Return blk
  243. End Function
  244. ' ------------------------------------------------------------------------
  245. ' Type-specific methods...
  246. ' ------------------------------------------------------------------------
  247. ' Update () method for Block objects...
  248. Method Update ()
  249. ' Check for collision (passing alpha level of block to apply
  250. ' appropriate damage), and remove from GravityItem list if hit...
  251. If PlayerCollide (alph) Then BCount = BCount - 1; Destroy; Return
  252. ' If the block has been freed (by being hit), make it fall...
  253. If Not fixed
  254. alph = alph - 0.0075; If alph < 0 Then alph = 0
  255. ang = ang + angspeed; If ang > 359 Then ang = 0
  256. ys = ys + Gravity
  257. x = x + xs
  258. y = y + ys
  259. If y > GRAPHICS_HEIGHT Or alph = 0 Destroy; BCount = BCount - 1
  260. Else
  261. ' When blocks are lowered in main loop, they are just set to 'desty',
  262. ' their new y-position destination. This moves them towards that...
  263. ydist# = desty - y
  264. ys = ydist / 12.0
  265. y = y + ys
  266. EndIf
  267. End Method
  268. ' Block-specific Draw () method...
  269. Method Draw ()
  270. SetBlend ALPHABLEND
  271. SetRotation ang
  272. SetColor r, g, b
  273. SetAlpha alph
  274. DrawImage BlockImage, x, y
  275. SetRotation 0
  276. End Method
  277. Function DrawShadows ()
  278. SetBlend ALPHABLEND
  279. For blk:Block = EachIn GravityItemList
  280. SetRotation blk.ang
  281. SetColor 0, 0, 0
  282. SetAlpha blk.alph * 0.25
  283. DrawImage BlockImage, blk.x + 8, blk.y + 8
  284. Next
  285. End Function
  286. End Type
  287. ' Player object. Only one player possible right now, but this keeps everything
  288. ' together for easy reference...
  289. Type Player
  290. Field damaged ' Set to MilliSecs () when hit (used for flashing effect)
  291. ' ------------------------------------------------------------------------
  292. ' Type-specific fields...
  293. ' ------------------------------------------------------------------------
  294. ' The shields field is a float so I can reduce by small amounts, but I use
  295. ' Int (PlayerOne.shields) to display/evaluate it...
  296. Field shields# = 100
  297. Field x#
  298. Field y#
  299. Field xs#
  300. Field ys#
  301. Field image ' Player image...
  302. Field width
  303. Field height
  304. ' ------------------------------------------------------------------------
  305. ' Type-specific functions...
  306. ' ------------------------------------------------------------------------
  307. ' Create () is a function that creates & returns a :Player type object...
  308. Function Create:Player (x, y, image)
  309. PlayerOne:Player = New Player
  310. PlayerOne.image = image
  311. PlayerOne.x = x
  312. PlayerOne.y = y
  313. PlayerOne.width = ImageWidth (PlayerOne.image) * 0.2 ' Image is scaled in Draw ()
  314. PlayerOne.height = ImageHeight (PlayerOne.image) * 0.2
  315. Return PlayerOne
  316. End Function
  317. ' ------------------------------------------------------------------------
  318. ' Type-specific methods...
  319. ' ------------------------------------------------------------------------
  320. ' This is passed the MouseX () and MouseY () positions in the main game
  321. ' loop, and hence moves the player toward the mouse cursor...
  322. Method Move (destx#, desty#, div#)
  323. xdist# = destx - x
  324. ydist# = desty - y
  325. xs = xdist / div
  326. ys = ydist / div
  327. x = x + xs
  328. y = y + ys
  329. End Method
  330. Method Draw (alpha# = 1, r = 255, g = 255, b = 255)
  331. SetBlend ALPHABLEND
  332. SetScale 0.2, 0.2
  333. If Shadows_On
  334. SetColor 0, 0, 0
  335. SetAlpha alpha * 0.4
  336. DrawImage image, x + 8, y + 8
  337. EndIf
  338. SetAlpha alpha
  339. ' If player is damaged, rgb will be RED...
  340. SetColor r, g, b
  341. DrawImage image, x, y
  342. SetScale 1, 1
  343. End Method
  344. End Type
  345. Type Shot Extends GravityItem
  346. ' ------------------------------------------------------------------------
  347. ' Type-specific functions...
  348. ' ------------------------------------------------------------------------
  349. Function Create:Shot (x#, y#, ys#, xs#, soundpan#)
  350. If Sounds_On
  351. play = CueSound (shoot)
  352. SetChannelPan play, soundpan
  353. ResumeChannel play
  354. EndIf
  355. s:Shot = New Shot
  356. s.x = x
  357. s.y = y
  358. s.xs = xs
  359. s.ys = ys
  360. s.width = 6
  361. s.height = 6
  362. s.damage = 2
  363. Return s
  364. End Function
  365. ' ------------------------------------------------------------------------
  366. ' Type-specific methods...
  367. ' ------------------------------------------------------------------------
  368. ' Over-ride standard GravityItem Update () method...
  369. Method Update ()
  370. ' Hit the player (note 'posyonly', 2nd parameter, of PlayerCollide)...
  371. If PlayerCollide (1, 1) Then Destroy; Return
  372. ys = ys + Gravity
  373. x = x + xs
  374. y = y + ys
  375. ' Remove if below bottom of screen...
  376. If y > GRAPHICS_HEIGHT
  377. Destroy
  378. Else
  379. ' Check current Shot against all Blocks...
  380. ' (Notice that this only checks Block objects in the list!)
  381. For blk:Block = EachIn GravityItemList
  382. ' Get x offset (rectangles are mid-handled)...
  383. ox = x - width / 2
  384. oy = y - height / 2
  385. ogx = blk.x - blk.width / 2
  386. ogy = blk.y - blk.width / 2
  387. ' Check collision...
  388. If OverLap (ox, oy, ox + width, oy + height, ogx, ogy, ogx + blk.width, ogy + blk.height)
  389. ' If Block is already dead (ie. falling), reflect Shot, otherwise
  390. ' un-fix block and create explosion...
  391. ' Note: ys is current Shot object's y speed...
  392. If blk.fixed = False
  393. ys = -ys
  394. Else
  395. blk.fixed = False
  396. blk.ys = ys / Rnd (1, 4)
  397. blk.angspeed = Rnd (-4, 4)
  398. ExplosionParticle.Explode ogx, ogy, 4
  399. EndIf
  400. EndIf
  401. Next
  402. EndIf
  403. End Method
  404. Method Draw ()
  405. SetBlend MASKBLEND
  406. SetAlpha 1
  407. SetColor 255, 255, 255
  408. DrawImage ShotImage, x, y
  409. End Method
  410. End Type
  411. ' The random debris that falls 'down' the screen...
  412. Type DebrisItem
  413. ' ------------------------------------------------------------------------
  414. ' Type-specific fields...
  415. ' ------------------------------------------------------------------------
  416. Field x# = Rand (0, GRAPHICS_WIDTH - 1)
  417. Field y# = Rand (0, GRAPHICS_HEIGHT - 1)
  418. Field ys# = Rnd (0.01, 8)
  419. Field size = Rand (1, 2)
  420. ' ------------------------------------------------------------------------
  421. ' Type-specific methods...
  422. ' ------------------------------------------------------------------------
  423. Method Update ()
  424. If y > GRAPHICS_HEIGHT y = 0
  425. y = y + ys
  426. SetColor Rnd (127, 255), Rnd (127, 255), 255
  427. SetBlend SOLIDBLEND
  428. DrawRect x, y, size, size
  429. End Method
  430. End Type
  431. ' -----------------------------------------------------------------------------
  432. ' Functions...
  433. ' -----------------------------------------------------------------------------
  434. ' Draw simple text with shadow...
  435. Function DrawShadowText (t$, x, y)
  436. SetHandle 0,0
  437. SetRotation 0
  438. SetColor 0, 0, 0
  439. DrawText t$, x + 1, y + 1
  440. SetColor 255, 255, 255
  441. DrawText t$, x, y
  442. SetHandle .5,.5
  443. End Function
  444. ' Draw stuff in wireframe mode...
  445. Function WireFrame (enable = True)
  446. If enable
  447. glPolygonMode (GL_FRONT_AND_BACK, GL_LINE)
  448. Else
  449. glPolygonMode (GL_FRONT_AND_BACK, GL_FILL)
  450. EndIf
  451. End Function
  452. ' Draw stuff in point mode...
  453. Function Point (enable = True)
  454. If enable
  455. glPolygonMode (GL_FRONT_AND_BACK, GL_POINT)
  456. Else
  457. glPolygonMode (GL_FRONT_AND_BACK, GL_FILL)
  458. EndIf
  459. End Function
  460. ' Returns "Off" if 'status' is 0, otherwise "On"...
  461. Function OnOff$ (status)
  462. If status Then Return "On" Else Return "Off"
  463. End Function
  464. ' Phew! Thanks, Birdie! Rectangular overlap function. Should have been so easy...
  465. Function OverLap (x0, y0, x1, y1, x2, y2, x3, y3)
  466. If x0 > x3 Or x1 < x2 Then Return False
  467. If y0 > y3 Or y1 < y2 Then Return False
  468. Return True
  469. End Function
  470. ' Distance between two points...
  471. Function Dist# (x0#, y0#, x1#, y1#)
  472. Return Sqr (((x1 - x0) * (x1 - x0)) + ((y1 - y0) * (y1 - y0)))
  473. End Function
  474. ' -----------------------------------------------------------------------------
  475. ' Main game. This is where it all goes pear-shaped!
  476. ' -----------------------------------------------------------------------------
  477. ' Open display...
  478. ' Set Cls colour (used when background turned off)...
  479. SetClsColor 64, 96, 128
  480. ' All images' and rectangles' handles should be set to the centre...
  481. AutoMidHandle True
  482. SetHandle 0.5, 0.5
  483. ' All images mipped...
  484. AutoImageFlags MASKEDIMAGE|FILTEREDIMAGE|MIPMAPPEDIMAGE
  485. ' Mask colour for loaded images (will be transparent)...
  486. SetMaskColor 255, 0, 255
  487. ' Mouse position -- used in some type methods and functions, hence global...
  488. Global mx, my
  489. ' Player object...
  490. Global PlayerOne:Player
  491. ' Draw shadows?
  492. Global Shadows_On = True
  493. ' Turn off sound?
  494. Global Sounds_On = True
  495. ' Load media -- sounds, from included binaries (see start of code)...
  496. Global shoot = LoadSound ("incbin::sounds/shot.ogg")
  497. Global hit = LoadSound ("incbin::sounds/hit.ogg")
  498. Global beep = LoadSound ("incbin::sounds/beep.ogg")
  499. Global over = LoadSound ("incbin::sounds/gameover.ogg")
  500. ' Load media -- images, from included binaries...
  501. ' Shots...
  502. Global ShotImage = LoadImage ("incbin::gfx/shot.png")
  503. ' Blocks...
  504. ' Note there is only one image for all blocks -- they are altered by SetColorRGB before
  505. ' drawing (WHITE gives normal image)...
  506. Global BlockImage = LoadImage ("incbin::gfx/block.png")
  507. ' Player...
  508. pimage = LoadImage ("incbin::gfx/boing.png") ',MASKEDIMAGE|MIPMAPPEDIMAGE)
  509. ' Background...
  510. ' Note that bgscale stores the length of the screen diagonal, and this value is used
  511. ' for the image height, so it doesn't get chopped when it rotates...
  512. bg = LoadImage ("incbin::gfx/land.png")
  513. bgscale# = Dist (0, 0, GRAPHICS_WIDTH - 1, GRAPHICS_HEIGHT - 1) / ImageHeight (bg)
  514. ' Background angle/speed of rotation...
  515. bgang# = 0
  516. bgangspeed# = 0
  517. ' Create an array of 100 debris particles...
  518. Local debris:DebrisItem [100]
  519. For loop = 0 Until 100
  520. debris [loop] = New DebrisItem
  521. Next
  522. ' This should probably read 'rows' -- the number of rows of blocks at startup...
  523. layers = 5
  524. ' Toggle variables for drawing background, debris and wireframe mode...
  525. bgtoggle = 1
  526. debristoggle = 1
  527. wftoggle = 0
  528. ' Delay before adding another row of blocks (this is decreased as the game progresses)...
  529. rowdelay = 10000 ' 10 seconds (10000 milliseconds)...
  530. ' Background colour and first target colour...
  531. backr# = 64
  532. backg# = 96
  533. backb# = 180
  534. backtr# = 128
  535. backtg# = 32
  536. backtb# = 48
  537. ' Delay between colour increments...
  538. backstep# = 5000
  539. ' Colour increments...
  540. backstepr# = (backtr - backr) / backstep
  541. backstepg# = (backtg - backg) / backstep
  542. backstepb# = (backtb - backb) / backstep
  543. ' Direction of increment to target colour...
  544. backsgn = Sgn (backtr - backr)
  545. ' This is the point where the game is re-started from, whenever a level is completed or game ended...
  546. #ResetLevel ' $name signifies a label now...
  547. ' Increase level number (level is 0 on startup, so becomes 1 for first level)...
  548. level = level + 1
  549. ' Reset the 'new row' delay timer to the current time...
  550. rowtimer = MilliSecs ()
  551. ' Set fire rate limiter to current time...
  552. firetimer = MilliSecs ()
  553. ' Create rows of blocks...
  554. For y = 0 To layers - 1
  555. For x = 0 Until GRAPHICS_WIDTH Step BLOCKWIDTH
  556. b:Block = Block.Create (x + BLOCKWIDTH / 2, (y * BLOCKHEIGHT) + BLOCKHEIGHT / 2)
  557. b.r = Rnd (127, 255)
  558. b.g = Rnd (127, 255)
  559. b.b = Rnd (127, 255)
  560. Next
  561. Next
  562. ' Minimum number of blocks left before we *stop* dropping them down (equivalent of 2 rows)...
  563. lowblocks = 2 * (GRAPHICS_WIDTH / BLOCKWIDTH)
  564. ' When a level is completed, we delete the player object for simplicity of resetting
  565. ' all its values. This creates it (same for game startup)...
  566. If PlayerOne = Null Then PlayerOne = Player.Create (VirtualMouseX (), VirtualMouseY (), pimage)
  567. ' Don't show the mouse pointer; gonna draw our own...
  568. HideMouse
  569. ' Game text and precalculated x offsets...
  570. go$ = "G A M E O V E R -- H I T S P A C E O R R M B"
  571. wd$ = "W E L L D O N E -- H I T S P A C E O R R M B"
  572. gox = (GRAPHICS_WIDTH / 2) - (TextWidth (go$) / 2)
  573. wdx = (GRAPHICS_WIDTH / 2) - (TextWidth (wd$) / 2)
  574. Repeat
  575. ' Clear the screen...
  576. Cls
  577. ' Store mouse position in these global variables...
  578. mx = VirtualMouseX ()
  579. my = VirtualMouseY ()
  580. ' -----------------------------------------------------------------------
  581. ' Toggles...
  582. ' -----------------------------------------------------------------------
  583. If KeyHit (KEY_F1) Then bgtoggle = 1 - bgtoggle ' Background
  584. If KeyHit (KEY_F2) Then debristoggle = 1 - debristoggle ' Debris
  585. If KeyHit (KEY_F3) Then wftoggle = 1 - wftoggle; WireFrame wftoggle ' Wireframe *
  586. If KeyHit (KEY_F4) Then Sounds_On = 1 - Sounds_On ' Sound
  587. If KeyHit (KEY_F5) Then Shadows_On = 1 - Shadows_On ' Shadows
  588. ' * Wireframe worked when the game used rectangles instead of images for blocks!
  589. ' -----------------------------------------------------------------------
  590. ' Background...
  591. ' -----------------------------------------------------------------------
  592. ' Update background rotation...
  593. bgang = bgang + bgangspeed; If bgang > 359 - bgangspeed Then bgang = 0
  594. bgangspeed = bgangspeed + 0.0001
  595. ' The bgtoggle variable controls whether the background should be drawn or not...
  596. If bgtoggle
  597. ' Turn off wireframe mode (if it's on)...
  598. If wftoggle Then WireFrame False
  599. ' Change colour by pre-calculated increment...
  600. backr = backr + backstepr
  601. backg = backg + backstepg
  602. backb = backb + backstepb
  603. ' Reached target colour? Set a new target/increments/increment-direction...
  604. If backr => backtr * backsgn
  605. backtr = Rnd (255)
  606. backtg = Rnd (255)
  607. backtb = Rnd (255)
  608. backstepr# = (backtr - backr) / backstep
  609. backstepg# = (backtg - backg) / backstep
  610. backstepb# = (backtb - backb) / backstep
  611. backsgn = Sgn (backtr - backr)
  612. EndIf
  613. ' Set colour of background image (applied to the greyscale default)...
  614. SetColor backr, backg, backb
  615. ' Set the background's pre-calculated scale...
  616. SetScale bgscale, bgscale
  617. SetRotation bgang
  618. SetAlpha 1
  619. DrawImage bg, GW2, GH2
  620. ' Reset this stuff so next drawn items don't have to...
  621. SetRotation 0
  622. SetScale 1, 1
  623. ' Put back to wireframe/non-wireframe mode, depending on value of 'wftoggle'...
  624. WireFrame wftoggle
  625. EndIf
  626. ' -----------------------------------------------------------------------
  627. ' Debris...
  628. ' -----------------------------------------------------------------------
  629. ' Draw debris particles if 'debristoggle' is True...
  630. If debristoggle
  631. For loop = 0 Until 100
  632. debris [loop].Update
  633. Next
  634. EndIf
  635. ' -----------------------------------------------------------------------
  636. ' Cursor...
  637. ' -----------------------------------------------------------------------
  638. SetColor 255, 255, 255
  639. DrawLine mx - 8, my, mx + 8, my
  640. DrawLine mx, my - 8, mx, my + 8
  641. ' -----------------------------------------------------------------------
  642. ' Move and draw player...
  643. ' -----------------------------------------------------------------------
  644. ' Move the player object based on mouse position (the '20' controls the
  645. ' speed at which the player moves toward the mouse -- play with it;
  646. ' lower is faster)...
  647. PlayerOne.Move (mx, my, 12)
  648. ' Turn wireframe off if still on, before drawing player...
  649. If wftoggle Then WireFrame False
  650. ' When the player is hit, the 'damaged' field is set to the current time.
  651. ' This code checks if a second has passed since 'damaged'. If so, it draws
  652. ' the player normally; if not, the player is drawn in red, with varying
  653. ' transparency...
  654. If MilliSecs () > PlayerOne.damaged + 1000 ' Damage timeout has passed...
  655. ' Draw normally...
  656. PlayerOne.damaged = 0 ' Resetting damage time...
  657. alpha# = 1
  658. rcol = 255; gcol = 255; bcol = 255
  659. Else
  660. ' Flash player for 1 second if hit...
  661. alpha# = Sin (MilliSecs ())
  662. rcol = 255; gcol = 0; bcol = 0
  663. EndIf
  664. ' Draw the player using the above values...
  665. PlayerOne.Draw (alpha, rcol, gcol, bcol)
  666. ' Reset the wireframe mode according to 'w'...
  667. WireFrame wftoggle
  668. ' -----------------------------------------------------------------------
  669. ' If player is alive, do stuff...
  670. ' -----------------------------------------------------------------------
  671. If Int (PlayerOne.shields) > 0 ' Shields is a float, so gotta round it...
  672. ' Player is alive...
  673. ' If more than 'lowblocks' left on screen, add a row and lower all
  674. ' blocks. Reset drop-down timer and reduce delay for next drop-down...
  675. If Block.BCount > lowblocks And MilliSecs () > rowtimer + rowdelay
  676. ' Add a row of blocks, above top of screen...
  677. For x = 0 Until GRAPHICS_WIDTH Step BLOCKWIDTH
  678. b:Block = Block.Create (x + BLOCKWIDTH / 2, -BLOCKHEIGHT / 2)
  679. b.r = Rnd (127, 255)
  680. b.g = Rnd (127, 255)
  681. b.b = Rnd (127, 255)
  682. Next
  683. ' Set all blocks' target y position down by block height. When blocks
  684. ' are updated, they get moved towards this new position...
  685. For b:Block = EachIn GravityItem.GravityItemList
  686. b.desty = b.desty + BLOCKHEIGHT
  687. Next
  688. ' Reset timeout until a new row is added...
  689. rowtimer = MilliSecs ()
  690. ' Reduce row-down timeout a bit...
  691. If rowdelay => 1100 Then rowdelay = rowdelay - 100 ' Minimum 1 sec interval!
  692. EndIf
  693. ' --------------------------------------------------------------------
  694. ' Fire shot (maximum fire rate 75 milliseconds)...
  695. ' --------------------------------------------------------------------
  696. If MouseDown (1)
  697. If MilliSecs () > firetimer + 75
  698. pan# = PlayerOne.x / GW2 - 1.0
  699. s:Shot = Shot.Create (PlayerOne.x, PlayerOne.y - (PlayerOne.height / 2 + 5), -5, PlayerOne.xs / 5.0, pan)
  700. firetimer = MilliSecs ()
  701. EndIf
  702. EndIf
  703. ' --------------------------------------------------------------------
  704. ' No blocks left?
  705. ' --------------------------------------------------------------------
  706. ' Set 'welldone' flag (text shows "Well done" below if True);
  707. ' If there are no blocks and Space is hit, delete all GravityItems,
  708. ' reduce block count, increase number of block rows and reset level...
  709. If Block.BCount = 0
  710. ' Will display 'well done' message further down...
  711. welldone = True
  712. ' Remove all items (and reduce block count)...
  713. For g:GravityItem = EachIn GravityItem.GravityItemList
  714. If Block (g) Then Block.BCount = Block.BCount - 1
  715. g.Destroy
  716. Next
  717. ' If space is hit, add some layers and reset everything (new level)...
  718. If KeyHit (KEY_SPACE) Or MouseHit (2)
  719. If Sounds_On Then PlaySound beep
  720. layers = layers + 3
  721. Goto ResetLevel
  722. EndIf
  723. EndIf
  724. Else
  725. If gameoverplayed = 0
  726. If Sounds_On Then PlaySound over
  727. gameoverplayed = 1
  728. EndIf
  729. ' Player is dead...
  730. PlayerOne.shields = 0 ' Force to zero as can be reduced after game is over...
  731. gameover = True
  732. ' Remove all blocks...
  733. For b:Block = EachIn GravityItem.GravityItemList
  734. b.Destroy
  735. Block.BCount = Block.BCount - 1
  736. Next
  737. ' -------------------------------------------------------------------
  738. ' If player is dead and Space hit...
  739. ' -------------------------------------------------------------------
  740. ' Space hit... remove everything else and reset to inital settings...
  741. If KeyHit (KEY_SPACE) Or MouseHit (2)
  742. If Sounds_On Then PlaySound beep
  743. For g:GravityItem = EachIn GravityItem.GravityItemList
  744. g.Destroy
  745. Next
  746. ' Delete player (recreated when level is reset)...
  747. PlayerOne = Null
  748. layers = 5
  749. bgang = 0
  750. bgangspeed = 0
  751. level = 0
  752. rowdelay = 10000
  753. gameoverplayed = 0
  754. Goto ResetLevel
  755. Else
  756. ' Quit if ESC hit...
  757. If KeyHit (KEY_ESCAPE) Then End
  758. EndIf
  759. EndIf
  760. ' -----------------------------------------------------------------------
  761. ' Update everything...
  762. ' -----------------------------------------------------------------------
  763. GravityItem.UpdateAll
  764. ' -----------------------------------------------------------------------
  765. ' Draw text on top of everything...
  766. ' -----------------------------------------------------------------------
  767. SetAlpha 1
  768. DrawShadowText "Level: " + level + " | Shields: " + Int (PlayerOne.shields) + "%", 20, GRAPHICS_HEIGHT - 80
  769. DrawShadowText "GCMemAlloced:"+GCMemAlloced(),20,GRAPHICS_HEIGHT - 60
  770. DrawShadowText "F1: Toggle background | F3: Wireframe mode | F5: Toggle shadows", 20, GRAPHICS_HEIGHT - 40
  771. DrawShadowText "F2: Toggle debris | F4: Toggle audio (" + OnOff (Sounds_On) + ")", 20, GRAPHICS_HEIGHT - 20
  772. ' Draw extra text if appropriate...
  773. If gameover
  774. DrawShadowText go$, gox, GRAPHICS_HEIGHT / 2
  775. gameover = False
  776. Else
  777. If welldone
  778. DrawShadowText wd$, wdx, GRAPHICS_HEIGHT / 2
  779. welldone = False
  780. EndIf
  781. EndIf
  782. ' Display everything that's been drawn to the hidden back buffer...
  783. GCCollect
  784. Flip True
  785. Until KeyHit (KEY_ESCAPE)
  786. End