| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161 |
- ' -----------------------------------------------------------------------------
- ' RockOut -- Rocket BlockOut
- ' -----------------------------------------------------------------------------
- ' Public domain source code by James L Boyd (support @ blitzbasic . com)
- ' -----------------------------------------------------------------------------
- ' Rocket image © 2004 James L Boyd, with permission granted for freeware/PD use,
- ' not that anyone'd really want it anyway...!
- ' -----------------------------------------------------------------------------
- ' -----------------------------------------------------------------------------
- ' Constants...
- ' -----------------------------------------------------------------------------
- ' Sizes used for blocks...
- Const BLOCKWIDTH = 32
- Const BLOCKHEIGHT = 16
- Const GRAPHICS_WIDTH = 640
- Const GRAPHICS_HEIGHT = 480
- Const GW2 = GRAPHICS_WIDTH / 2
- Const GH2 = GRAPHICS_HEIGHT / 2
- Graphics 800,600,32,60
- SetVirtualResolution GRAPHICS_WIDTH,GRAPHICS_HEIGHT
- ' Pre-calc half of graphics width...
- ' -----------------------------------------------------------------------------
- ' Include media...
- ' -----------------------------------------------------------------------------
- ' Sounds (all from Yamaha RM1X!)...
- Incbin "sounds/shot.ogg" ' Player shot
- Incbin "sounds/fall.ogg" ' Block fall
- Incbin "sounds/hit.ogg" ' Block/player hit
- Incbin "sounds/beep.ogg" ' 'Press space' sound
- Incbin "sounds/gameover.ogg" ' Guess...
- ' Graphics...
- Incbin "gfx/boing.png" ' Rocket
- Incbin "gfx/land.png" ' Background (used to be land, now a grid)
- Incbin "gfx/shot.png" ' Player's shot
- Incbin "gfx/block.png" ' Guess...
- ' -----------------------------------------------------------------------------
- ' Types (object definitions)...
- ' -----------------------------------------------------------------------------
- ' GravityItem: all objects affected by gravity are based upon this...
- Type GravityItem
- ' ------------------------------------------------------------------------
- ' Type-specific globals...
- ' ------------------------------------------------------------------------
- ' Why not make these truly global? It's cleaner -- you can just copy and
- ' paste the type definition into a completely different program without
- ' having to remember which globals are related...
- Global GCount ' Count of all GravityItems (for debugging)
- Global GravityItemList:TList ' List used for all GravityItem objects
- Global Gravity# = 0.05 ' Gravity applied to all GravityItems
- ' ------------------------------------------------------------------------
- ' Type fields...
- ' ------------------------------------------------------------------------
- Field x# ' x position of object
- Field y# ' y position of object
- Field xs# ' x speed of object
- Field ys# ' y speed of object
- Field width ' Width of object
- Field height ' Height of object
- Field damage ' Damage caused by this item if it hits player
- Field fixed = False ' Is object fixed in place? Blocks are, at first...
- Field r, g, b
- ' ------------------------------------------------------------------------
- ' Type functions...
- ' ------------------------------------------------------------------------
- Function UpdateAll ()
- If GravityItemList = Null Then Return
- If Shadows_On Then Block.DrawShadows ' Shadows_On is a global...
- For g:GravityItem = EachIn GravityItemList
- g.Update
- g.Draw
- Next
- End Function
- ' ------------------------------------------------------------------------
- ' Type methods...
- ' ------------------------------------------------------------------------
- ' The New method is special -- Blitz calls it whenever a new object is
- ' created...
- ' Every time a new GravityItem is created -- including objects that extend
- ' GravityItem -- this is called. In this case, it creates the type-global
- ' list if it doesn't yet exist (only happens once), and adds the item to it...
- Method New ()
- If GravityItemList = Null Then GravityItemList = New TList
- GravityItemList.AddLast Self
- GCount = GCount + 1
- End Method
- ' Destroy current object and remove from list
- Method Destroy ()
- GravityItemList.Remove Self
- GCount = GCount - 1
- End Method
- ' Rectangle-based collision test of current object and player.
-
- ' 'The multiplier' parameter controls how much of an object's
- ' 'damage' field applies to the player -- in the case of Block
- ' objects, the more they're faded out, the less damage they do...
- ' The 'posyonly' parameter is a hack to stop Shot objects damaging
- ' the player while going up...
- Method PlayerCollide (multiplier# = 1, posyonly = 0)
- ' Offset x/y position of shots (all images' handles are centered)...
- ox = x - width / 2
- oy = y - height / 2
- ' Offset x/y position of player...
- opx = PlayerOne.x - PlayerOne.width / 2
- opy = PlayerOne.y - PlayerOne.height / 2
- ' Hack to stop Shot objects damaging player while going up...
- check = 1
- If posyonly
- If ys < 0
- check = 0
- EndIf
- EndIf
- ' Test for collision, apply damage and make explosion...
- If check
- If OverLap (ox, oy, ox + width, oy + height, opx, opy, opx + PlayerOne.width, opy + PlayerOne.height)
- PlayerOne.shields = PlayerOne.shields - damage * multiplier
- ExplosionParticle.Explode x, y, damage * 5 * multiplier
- PlayerOne.damaged = MilliSecs ()
- Return True
- EndIf
- EndIf
- End Method
- ' There is no default Draw method here, as it's different for each extended type
- ' of GravityItem, so I've defined it as Abstract...
- ' Abstract forces every type that extends GravityItem to have a Draw () method defined
- ' or the code simply won't compile...
- ' One practical use for this is that you can call Draw from any random GravityItem,
- ' regardless of which extended type it is, and this will call the correct Draw ()
- ' for the type of object in question...
- Method Draw () Abstract
- ' Abstract Update method for GravityItems. See Draw () explanation...
- Method Update () Abstract
- End Type
- ' Particles created in an explosion. This type extends GravityItem, meaning all
- ' properties of GravityItem apply, except where methods are over-ridden
- ' (ie. re-defined) here...
- Type ExplosionParticle Extends GravityItem
- ' ------------------------------------------------------------------------
- ' Type fields...
- ' ------------------------------------------------------------------------
- ' No need to define, x, y, xs, ys, etc as they're part of the GravityItem definition...
- Field alph# = 1.0 ' Alpha level of particle (translucency)
- ' ------------------------------------------------------------------------
- ' Type functions...
- ' ------------------------------------------------------------------------
- ' Create explosion of particles, and play sound...
- Function Explode (x#, y#, particles)
- ' NB. GW2 is a global set to half of GRAPHICS_WIDTH...
- If Sounds_On
- pan# = x / GW2 - 1.0
- play = CueSound (hit)
- SetChannelPan play, pan
- ResumeChannel play
- EndIf
- For loop = 1 To particles
- ExplosionParticle.Create (x, y)
- Next
- End Function
- ' Create single explosion particle. Note that any items extending GravityItem
- ' will call the New () method from GravityItem upon creation, so these will
- ' be added to the GravityItem list automatically...
- Function Create:ExplosionParticle (x, y)
- e:ExplosionParticle = New ExplosionParticle
- e.x = x
- e.y = y
- e.xs = Rnd (-8, 8)
- e.ys = Rnd (-8, 8)
- ' Random colour...
- Select Rand (0, 3)
- Case 0
- e.r = 255
- e.g = 255
- e.b = 255
- Case 1
- e.r = 255
- e.g = 127
- e.b = 0
- Case 2
- e.r = 255
- e.g = 255
- e.b = 0
- Case 3
- e.r = 255
- e.g = 0
- e.b = 0
- End Select
- ' Random size...
- size = Rand (1, 8)
- e.width = size
- e.height = size
- End Function
- ' ------------------------------------------------------------------------
- ' Type methods...
- ' ------------------------------------------------------------------------
- ' Update () over-rides the GravityItem Update () method...
- Method Update ()
- ' Reduce alpha level of particle...
- alph = alph - 0.01
- ' Apply Gravity global (see GravityItem) to y speed...
- ys = ys + Gravity
- ' Move particle by current speed...
- x = x + xs
- y = y + ys
-
- ' If off-screen or reduced to invisible, remove from list by
- ' calling the Destroy method (inherited from GravityItem)...
- If y > GRAPHICS_HEIGHT Or alph = 0 Then Destroy
- End Method
- ' Draw particle...
- Method Draw ()
- SetScale 1, 1
- SetBlend ALPHABLEND
- SetAlpha alph
- SetColor r, g, b
- DrawRect x, y, width, height
- End Method
- End Type
- ' Block definition. Again, Block is a kind of GravityItem...
- Type Block Extends GravityItem
- ' ------------------------------------------------------------------------
- ' Type-specific globals...
- ' ------------------------------------------------------------------------
- Global BCount ' Number of blocks
- ' ------------------------------------------------------------------------
- ' Type-specific fields...
- ' ------------------------------------------------------------------------
- Field alph# = 1.0 ' Alpha level of block
- Field ang# ' Rotation of block
- Field angspeed# ' Rotation speed of block
- Field desty#
- ' ------------------------------------------------------------------------
- ' Type-specific function...
- ' ------------------------------------------------------------------------
- ' Create a Block object (added to GravityItem list automatically)...
- Function Create:Block (x, y)
- blk:Block = New Block
- blk.x = x
- blk.y = y
- blk.desty = y
- blk.width = BLOCKWIDTH
- blk.height = BLOCKHEIGHT
- blk.fixed = True
- blk.damage = 20
- BCount = BCount + 1
- Return blk
- End Function
- ' ------------------------------------------------------------------------
- ' Type-specific methods...
- ' ------------------------------------------------------------------------
- ' Update () method for Block objects...
- Method Update ()
- ' Check for collision (passing alpha level of block to apply
- ' appropriate damage), and remove from GravityItem list if hit...
- If PlayerCollide (alph) Then BCount = BCount - 1; Destroy; Return
- ' If the block has been freed (by being hit), make it fall...
- If Not fixed
- alph = alph - 0.0075; If alph < 0 Then alph = 0
- ang = ang + angspeed; If ang > 359 Then ang = 0
- ys = ys + Gravity
- x = x + xs
- y = y + ys
- If y > GRAPHICS_HEIGHT Or alph = 0 Destroy; BCount = BCount - 1
- Else
- ' When blocks are lowered in main loop, they are just set to 'desty',
- ' their new y-position destination. This moves them towards that...
- ydist# = desty - y
- ys = ydist / 12.0
- y = y + ys
- EndIf
- End Method
- ' Block-specific Draw () method...
- Method Draw ()
- SetBlend ALPHABLEND
- SetRotation ang
- SetColor r, g, b
- SetAlpha alph
- DrawImage BlockImage, x, y
- SetRotation 0
- End Method
- Function DrawShadows ()
- SetBlend ALPHABLEND
- For blk:Block = EachIn GravityItemList
- SetRotation blk.ang
- SetColor 0, 0, 0
- SetAlpha blk.alph * 0.25
- DrawImage BlockImage, blk.x + 8, blk.y + 8
- Next
- End Function
- End Type
- ' Player object. Only one player possible right now, but this keeps everything
- ' together for easy reference...
- Type Player
- Field damaged ' Set to MilliSecs () when hit (used for flashing effect)
- ' ------------------------------------------------------------------------
- ' Type-specific fields...
- ' ------------------------------------------------------------------------
- ' The shields field is a float so I can reduce by small amounts, but I use
- ' Int (PlayerOne.shields) to display/evaluate it...
- Field shields# = 100
- Field x#
- Field y#
- Field xs#
- Field ys#
- Field image ' Player image...
- Field width
- Field height
- ' ------------------------------------------------------------------------
- ' Type-specific functions...
- ' ------------------------------------------------------------------------
- ' Create () is a function that creates & returns a :Player type object...
- Function Create:Player (x, y, image)
- PlayerOne:Player = New Player
- PlayerOne.image = image
- PlayerOne.x = x
- PlayerOne.y = y
- PlayerOne.width = ImageWidth (PlayerOne.image) * 0.2 ' Image is scaled in Draw ()
- PlayerOne.height = ImageHeight (PlayerOne.image) * 0.2
- Return PlayerOne
- End Function
- ' ------------------------------------------------------------------------
- ' Type-specific methods...
- ' ------------------------------------------------------------------------
- ' This is passed the MouseX () and MouseY () positions in the main game
- ' loop, and hence moves the player toward the mouse cursor...
- Method Move (destx#, desty#, div#)
- xdist# = destx - x
- ydist# = desty - y
- xs = xdist / div
- ys = ydist / div
- x = x + xs
- y = y + ys
- End Method
- Method Draw (alpha# = 1, r = 255, g = 255, b = 255)
- SetBlend ALPHABLEND
- SetScale 0.2, 0.2
- If Shadows_On
- SetColor 0, 0, 0
- SetAlpha alpha * 0.4
- DrawImage image, x + 8, y + 8
- EndIf
- SetAlpha alpha
- ' If player is damaged, rgb will be RED...
- SetColor r, g, b
- DrawImage image, x, y
- SetScale 1, 1
- End Method
- End Type
- Type Shot Extends GravityItem
- ' ------------------------------------------------------------------------
- ' Type-specific functions...
- ' ------------------------------------------------------------------------
- Function Create:Shot (x#, y#, ys#, xs#, soundpan#)
- If Sounds_On
- play = CueSound (shoot)
- SetChannelPan play, soundpan
- ResumeChannel play
- EndIf
- s:Shot = New Shot
- s.x = x
- s.y = y
- s.xs = xs
- s.ys = ys
- s.width = 6
- s.height = 6
- s.damage = 2
- Return s
- End Function
- ' ------------------------------------------------------------------------
- ' Type-specific methods...
- ' ------------------------------------------------------------------------
- ' Over-ride standard GravityItem Update () method...
- Method Update ()
- ' Hit the player (note 'posyonly', 2nd parameter, of PlayerCollide)...
- If PlayerCollide (1, 1) Then Destroy; Return
- ys = ys + Gravity
- x = x + xs
- y = y + ys
- ' Remove if below bottom of screen...
- If y > GRAPHICS_HEIGHT
- Destroy
- Else
- ' Check current Shot against all Blocks...
- ' (Notice that this only checks Block objects in the list!)
- For blk:Block = EachIn GravityItemList
- ' Get x offset (rectangles are mid-handled)...
- ox = x - width / 2
- oy = y - height / 2
- ogx = blk.x - blk.width / 2
- ogy = blk.y - blk.width / 2
- ' Check collision...
- If OverLap (ox, oy, ox + width, oy + height, ogx, ogy, ogx + blk.width, ogy + blk.height)
- ' If Block is already dead (ie. falling), reflect Shot, otherwise
- ' un-fix block and create explosion...
- ' Note: ys is current Shot object's y speed...
- If blk.fixed = False
- ys = -ys
- Else
- blk.fixed = False
- blk.ys = ys / Rnd (1, 4)
- blk.angspeed = Rnd (-4, 4)
- ExplosionParticle.Explode ogx, ogy, 4
- EndIf
- EndIf
- Next
- EndIf
- End Method
- Method Draw ()
- SetBlend MASKBLEND
- SetAlpha 1
- SetColor 255, 255, 255
- DrawImage ShotImage, x, y
- End Method
- End Type
- ' The random debris that falls 'down' the screen...
- Type DebrisItem
- ' ------------------------------------------------------------------------
- ' Type-specific fields...
- ' ------------------------------------------------------------------------
- Field x# = Rand (0, GRAPHICS_WIDTH - 1)
- Field y# = Rand (0, GRAPHICS_HEIGHT - 1)
- Field ys# = Rnd (0.01, 8)
- Field size = Rand (1, 2)
- ' ------------------------------------------------------------------------
- ' Type-specific methods...
- ' ------------------------------------------------------------------------
- Method Update ()
- If y > GRAPHICS_HEIGHT y = 0
- y = y + ys
- SetColor Rnd (127, 255), Rnd (127, 255), 255
- SetBlend SOLIDBLEND
- DrawRect x, y, size, size
- End Method
- End Type
- ' -----------------------------------------------------------------------------
- ' Functions...
- ' -----------------------------------------------------------------------------
- ' Draw simple text with shadow...
- Function DrawShadowText (t$, x, y)
- SetHandle 0,0
- SetRotation 0
- SetColor 0, 0, 0
- DrawText t$, x + 1, y + 1
- SetColor 255, 255, 255
- DrawText t$, x, y
- SetHandle .5,.5
- End Function
- ' Draw stuff in wireframe mode...
- Function WireFrame (enable = True)
- If enable
- glPolygonMode (GL_FRONT_AND_BACK, GL_LINE)
- Else
- glPolygonMode (GL_FRONT_AND_BACK, GL_FILL)
- EndIf
- End Function
- ' Draw stuff in point mode...
- Function Point (enable = True)
- If enable
- glPolygonMode (GL_FRONT_AND_BACK, GL_POINT)
- Else
- glPolygonMode (GL_FRONT_AND_BACK, GL_FILL)
- EndIf
- End Function
- ' Returns "Off" if 'status' is 0, otherwise "On"...
- Function OnOff$ (status)
- If status Then Return "On" Else Return "Off"
- End Function
- ' Phew! Thanks, Birdie! Rectangular overlap function. Should have been so easy...
- Function OverLap (x0, y0, x1, y1, x2, y2, x3, y3)
- If x0 > x3 Or x1 < x2 Then Return False
- If y0 > y3 Or y1 < y2 Then Return False
- Return True
- End Function
- ' Distance between two points...
- Function Dist# (x0#, y0#, x1#, y1#)
- Return Sqr (((x1 - x0) * (x1 - x0)) + ((y1 - y0) * (y1 - y0)))
- End Function
- ' -----------------------------------------------------------------------------
- ' Main game. This is where it all goes pear-shaped!
- ' -----------------------------------------------------------------------------
- ' Open display...
- ' Set Cls colour (used when background turned off)...
- SetClsColor 64, 96, 128
- ' All images' and rectangles' handles should be set to the centre...
- AutoMidHandle True
- SetHandle 0.5, 0.5
- ' All images mipped...
- AutoImageFlags MASKEDIMAGE|FILTEREDIMAGE|MIPMAPPEDIMAGE
- ' Mask colour for loaded images (will be transparent)...
- SetMaskColor 255, 0, 255
- ' Mouse position -- used in some type methods and functions, hence global...
- Global mx, my
- ' Player object...
- Global PlayerOne:Player
- ' Draw shadows?
- Global Shadows_On = True
- ' Turn off sound?
- Global Sounds_On = True
- ' Load media -- sounds, from included binaries (see start of code)...
- Global shoot = LoadSound ("incbin::sounds/shot.ogg")
- Global hit = LoadSound ("incbin::sounds/hit.ogg")
- Global beep = LoadSound ("incbin::sounds/beep.ogg")
- Global over = LoadSound ("incbin::sounds/gameover.ogg")
- ' Load media -- images, from included binaries...
- ' Shots...
- Global ShotImage = LoadImage ("incbin::gfx/shot.png")
- ' Blocks...
- ' Note there is only one image for all blocks -- they are altered by SetColorRGB before
- ' drawing (WHITE gives normal image)...
- Global BlockImage = LoadImage ("incbin::gfx/block.png")
- ' Player...
- pimage = LoadImage ("incbin::gfx/boing.png") ',MASKEDIMAGE|MIPMAPPEDIMAGE)
- ' Background...
- ' Note that bgscale stores the length of the screen diagonal, and this value is used
- ' for the image height, so it doesn't get chopped when it rotates...
- bg = LoadImage ("incbin::gfx/land.png")
- bgscale# = Dist (0, 0, GRAPHICS_WIDTH - 1, GRAPHICS_HEIGHT - 1) / ImageHeight (bg)
- ' Background angle/speed of rotation...
- bgang# = 0
- bgangspeed# = 0
- ' Create an array of 100 debris particles...
- Local debris:DebrisItem [100]
- For loop = 0 Until 100
- debris [loop] = New DebrisItem
- Next
- ' This should probably read 'rows' -- the number of rows of blocks at startup...
- layers = 5
- ' Toggle variables for drawing background, debris and wireframe mode...
- bgtoggle = 1
- debristoggle = 1
- wftoggle = 0
- ' Delay before adding another row of blocks (this is decreased as the game progresses)...
- rowdelay = 10000 ' 10 seconds (10000 milliseconds)...
- ' Background colour and first target colour...
- backr# = 64
- backg# = 96
- backb# = 180
- backtr# = 128
- backtg# = 32
- backtb# = 48
- ' Delay between colour increments...
- backstep# = 5000
- ' Colour increments...
- backstepr# = (backtr - backr) / backstep
- backstepg# = (backtg - backg) / backstep
- backstepb# = (backtb - backb) / backstep
- ' Direction of increment to target colour...
- backsgn = Sgn (backtr - backr)
- ' This is the point where the game is re-started from, whenever a level is completed or game ended...
- #ResetLevel ' $name signifies a label now...
- ' Increase level number (level is 0 on startup, so becomes 1 for first level)...
- level = level + 1
- ' Reset the 'new row' delay timer to the current time...
- rowtimer = MilliSecs ()
- ' Set fire rate limiter to current time...
- firetimer = MilliSecs ()
- ' Create rows of blocks...
- For y = 0 To layers - 1
- For x = 0 Until GRAPHICS_WIDTH Step BLOCKWIDTH
- b:Block = Block.Create (x + BLOCKWIDTH / 2, (y * BLOCKHEIGHT) + BLOCKHEIGHT / 2)
- b.r = Rnd (127, 255)
- b.g = Rnd (127, 255)
- b.b = Rnd (127, 255)
- Next
- Next
- ' Minimum number of blocks left before we *stop* dropping them down (equivalent of 2 rows)...
- lowblocks = 2 * (GRAPHICS_WIDTH / BLOCKWIDTH)
- ' When a level is completed, we delete the player object for simplicity of resetting
- ' all its values. This creates it (same for game startup)...
- If PlayerOne = Null Then PlayerOne = Player.Create (VirtualMouseX (), VirtualMouseY (), pimage)
- ' Don't show the mouse pointer; gonna draw our own...
- HideMouse
- ' Game text and precalculated x offsets...
- go$ = "G A M E O V E R -- H I T S P A C E O R R M B"
- wd$ = "W E L L D O N E -- H I T S P A C E O R R M B"
- gox = (GRAPHICS_WIDTH / 2) - (TextWidth (go$) / 2)
- wdx = (GRAPHICS_WIDTH / 2) - (TextWidth (wd$) / 2)
- Repeat
- ' Clear the screen...
- Cls
- ' Store mouse position in these global variables...
- mx = VirtualMouseX ()
- my = VirtualMouseY ()
- ' -----------------------------------------------------------------------
- ' Toggles...
- ' -----------------------------------------------------------------------
- If KeyHit (KEY_F1) Then bgtoggle = 1 - bgtoggle ' Background
- If KeyHit (KEY_F2) Then debristoggle = 1 - debristoggle ' Debris
- If KeyHit (KEY_F3) Then wftoggle = 1 - wftoggle; WireFrame wftoggle ' Wireframe *
- If KeyHit (KEY_F4) Then Sounds_On = 1 - Sounds_On ' Sound
- If KeyHit (KEY_F5) Then Shadows_On = 1 - Shadows_On ' Shadows
- ' * Wireframe worked when the game used rectangles instead of images for blocks!
-
- ' -----------------------------------------------------------------------
- ' Background...
- ' -----------------------------------------------------------------------
- ' Update background rotation...
- bgang = bgang + bgangspeed; If bgang > 359 - bgangspeed Then bgang = 0
- bgangspeed = bgangspeed + 0.0001
- ' The bgtoggle variable controls whether the background should be drawn or not...
- If bgtoggle
- ' Turn off wireframe mode (if it's on)...
- If wftoggle Then WireFrame False
- ' Change colour by pre-calculated increment...
- backr = backr + backstepr
- backg = backg + backstepg
- backb = backb + backstepb
- ' Reached target colour? Set a new target/increments/increment-direction...
- If backr => backtr * backsgn
- backtr = Rnd (255)
- backtg = Rnd (255)
- backtb = Rnd (255)
- backstepr# = (backtr - backr) / backstep
- backstepg# = (backtg - backg) / backstep
- backstepb# = (backtb - backb) / backstep
- backsgn = Sgn (backtr - backr)
- EndIf
- ' Set colour of background image (applied to the greyscale default)...
- SetColor backr, backg, backb
- ' Set the background's pre-calculated scale...
- SetScale bgscale, bgscale
- SetRotation bgang
- SetAlpha 1
- DrawImage bg, GW2, GH2
- ' Reset this stuff so next drawn items don't have to...
- SetRotation 0
- SetScale 1, 1
- ' Put back to wireframe/non-wireframe mode, depending on value of 'wftoggle'...
- WireFrame wftoggle
- EndIf
- ' -----------------------------------------------------------------------
- ' Debris...
- ' -----------------------------------------------------------------------
- ' Draw debris particles if 'debristoggle' is True...
- If debristoggle
- For loop = 0 Until 100
- debris [loop].Update
- Next
- EndIf
- ' -----------------------------------------------------------------------
- ' Cursor...
- ' -----------------------------------------------------------------------
- SetColor 255, 255, 255
- DrawLine mx - 8, my, mx + 8, my
- DrawLine mx, my - 8, mx, my + 8
- ' -----------------------------------------------------------------------
- ' Move and draw player...
- ' -----------------------------------------------------------------------
- ' Move the player object based on mouse position (the '20' controls the
- ' speed at which the player moves toward the mouse -- play with it;
- ' lower is faster)...
- PlayerOne.Move (mx, my, 12)
- ' Turn wireframe off if still on, before drawing player...
- If wftoggle Then WireFrame False
- ' When the player is hit, the 'damaged' field is set to the current time.
- ' This code checks if a second has passed since 'damaged'. If so, it draws
- ' the player normally; if not, the player is drawn in red, with varying
- ' transparency...
- If MilliSecs () > PlayerOne.damaged + 1000 ' Damage timeout has passed...
- ' Draw normally...
- PlayerOne.damaged = 0 ' Resetting damage time...
- alpha# = 1
- rcol = 255; gcol = 255; bcol = 255
- Else
- ' Flash player for 1 second if hit...
- alpha# = Sin (MilliSecs ())
- rcol = 255; gcol = 0; bcol = 0
- EndIf
- ' Draw the player using the above values...
- PlayerOne.Draw (alpha, rcol, gcol, bcol)
- ' Reset the wireframe mode according to 'w'...
- WireFrame wftoggle
- ' -----------------------------------------------------------------------
- ' If player is alive, do stuff...
- ' -----------------------------------------------------------------------
- If Int (PlayerOne.shields) > 0 ' Shields is a float, so gotta round it...
- ' Player is alive...
- ' If more than 'lowblocks' left on screen, add a row and lower all
- ' blocks. Reset drop-down timer and reduce delay for next drop-down...
- If Block.BCount > lowblocks And MilliSecs () > rowtimer + rowdelay
- ' Add a row of blocks, above top of screen...
- For x = 0 Until GRAPHICS_WIDTH Step BLOCKWIDTH
- b:Block = Block.Create (x + BLOCKWIDTH / 2, -BLOCKHEIGHT / 2)
- b.r = Rnd (127, 255)
- b.g = Rnd (127, 255)
- b.b = Rnd (127, 255)
- Next
- ' Set all blocks' target y position down by block height. When blocks
- ' are updated, they get moved towards this new position...
- For b:Block = EachIn GravityItem.GravityItemList
- b.desty = b.desty + BLOCKHEIGHT
- Next
- ' Reset timeout until a new row is added...
- rowtimer = MilliSecs ()
- ' Reduce row-down timeout a bit...
- If rowdelay => 1100 Then rowdelay = rowdelay - 100 ' Minimum 1 sec interval!
- EndIf
- ' --------------------------------------------------------------------
- ' Fire shot (maximum fire rate 75 milliseconds)...
- ' --------------------------------------------------------------------
- If MouseDown (1)
- If MilliSecs () > firetimer + 75
- pan# = PlayerOne.x / GW2 - 1.0
- s:Shot = Shot.Create (PlayerOne.x, PlayerOne.y - (PlayerOne.height / 2 + 5), -5, PlayerOne.xs / 5.0, pan)
- firetimer = MilliSecs ()
- EndIf
- EndIf
- ' --------------------------------------------------------------------
- ' No blocks left?
- ' --------------------------------------------------------------------
- ' Set 'welldone' flag (text shows "Well done" below if True);
- ' If there are no blocks and Space is hit, delete all GravityItems,
- ' reduce block count, increase number of block rows and reset level...
- If Block.BCount = 0
- ' Will display 'well done' message further down...
- welldone = True
- ' Remove all items (and reduce block count)...
- For g:GravityItem = EachIn GravityItem.GravityItemList
- If Block (g) Then Block.BCount = Block.BCount - 1
- g.Destroy
- Next
- ' If space is hit, add some layers and reset everything (new level)...
- If KeyHit (KEY_SPACE) Or MouseHit (2)
- If Sounds_On Then PlaySound beep
- layers = layers + 3
- Goto ResetLevel
- EndIf
- EndIf
- Else
- If gameoverplayed = 0
- If Sounds_On Then PlaySound over
- gameoverplayed = 1
- EndIf
- ' Player is dead...
- PlayerOne.shields = 0 ' Force to zero as can be reduced after game is over...
- gameover = True
- ' Remove all blocks...
- For b:Block = EachIn GravityItem.GravityItemList
- b.Destroy
- Block.BCount = Block.BCount - 1
- Next
- ' -------------------------------------------------------------------
- ' If player is dead and Space hit...
- ' -------------------------------------------------------------------
- ' Space hit... remove everything else and reset to inital settings...
- If KeyHit (KEY_SPACE) Or MouseHit (2)
- If Sounds_On Then PlaySound beep
- For g:GravityItem = EachIn GravityItem.GravityItemList
- g.Destroy
- Next
- ' Delete player (recreated when level is reset)...
- PlayerOne = Null
- layers = 5
- bgang = 0
- bgangspeed = 0
- level = 0
- rowdelay = 10000
- gameoverplayed = 0
- Goto ResetLevel
- Else
- ' Quit if ESC hit...
- If KeyHit (KEY_ESCAPE) Then End
- EndIf
- EndIf
- ' -----------------------------------------------------------------------
- ' Update everything...
- ' -----------------------------------------------------------------------
- GravityItem.UpdateAll
- ' -----------------------------------------------------------------------
- ' Draw text on top of everything...
- ' -----------------------------------------------------------------------
- SetAlpha 1
- DrawShadowText "Level: " + level + " | Shields: " + Int (PlayerOne.shields) + "%", 20, GRAPHICS_HEIGHT - 80
- DrawShadowText "GCMemAlloced:"+GCMemAlloced(),20,GRAPHICS_HEIGHT - 60
- DrawShadowText "F1: Toggle background | F3: Wireframe mode | F5: Toggle shadows", 20, GRAPHICS_HEIGHT - 40
- DrawShadowText "F2: Toggle debris | F4: Toggle audio (" + OnOff (Sounds_On) + ")", 20, GRAPHICS_HEIGHT - 20
- ' Draw extra text if appropriate...
- If gameover
- DrawShadowText go$, gox, GRAPHICS_HEIGHT / 2
- gameover = False
- Else
- If welldone
- DrawShadowText wd$, wdx, GRAPHICS_HEIGHT / 2
- welldone = False
- EndIf
- EndIf
- ' Display everything that's been drawn to the hidden back buffer...
- GCCollect
- Flip True
- Until KeyHit (KEY_ESCAPE)
- End
|