summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GFX/small.bmfbin9888 -> 24544 bytes
-rw-r--r--HELP/help.txt162
-rw-r--r--game.bmx676
-rw-r--r--gametypes.bmx1937
-rw-r--r--hardwire.bmx770
-rw-r--r--help.bmx598
-rw-r--r--particle.bmx652
-rw-r--r--sounds.bmx124
-rw-r--r--types.bmx886
9 files changed, 2973 insertions, 2832 deletions
diff --git a/GFX/small.bmf b/GFX/small.bmf
index 16d8db4..b2f51f5 100644
--- a/GFX/small.bmf
+++ b/GFX/small.bmf
Binary files differ
diff --git a/HELP/help.txt b/HELP/help.txt
index 0d98d52..190aa53 100644
--- a/HELP/help.txt
+++ b/HELP/help.txt
@@ -1,81 +1,81 @@
-
-@THE RULES
-
-You start with an empty pit that has electrodes
-down the sides and at the bottom.
-
-#incbin::HELP/pit.png
-
-You must connect these using geometric
-shapes that fall from the sky which have
-wires embedded in the blocks...
-
-#incbin::HELP/piece.png
-
-I'm sure you'll (cough) recognise the shapes.
-
-Once a piece has landed in the pit if a
-connection can be made between electrodes,
-or a loop of wires can be made, then these
-are removed and you score lovely points...
-
-#incbin::HELP/wire1.png
-
-#incbin::HELP/loop1.png
-
-If a connection cannot be made, as in this one:
-
-#incbin::HELP/wire2.png
-
-Then the peices are unglued and any hanging bits
-drop down into the pit to make other possible
-loops...
-
-#incbin::HELP/wire3.png
-
-If a piece lands with anything sticking out of the
-top of the pit, it's GAME OVER.
-
-
-@SPECIAL PIECES
-
-Once in a while a special piece may drop down...
-
-
-!SMART BOMB
-
-$incbin::HELP/bomb.png
-
-This special will destroy all blocks that are the
-same as the one it lands on. Landing on nothing
-is perhaps not a good idea...
-
-
-!TWISTER
-
-$incbin::HELP/twister.png
-
-The twister will rotate all the pieces in the pit
-four times, scoring any loops and wires that
-are made from doing this.
-
-
-!SMART NUKE
-
-$incbin::HELP/nuke.png
-
-The smart nuke destroy all blocks that match
-the blocks surrounding the point were it lands.
-
-
-!SUPER CROSS
-
-~incbin::HELP/cross.png
-
-This will change all blocks above, below and to
-the left and right radiating out from the
-special to cross pieces.
-
-
-* * * * * * * * * * * * *
-
+
+@THE RULES
+
+You start with an empty pit that has electrodes
+down the sides and at the bottom.
+
+#incbin::HELP/pit.png
+
+You must connect these using geometric
+shapes that fall from the sky which have
+wires embedded in the blocks...
+
+#incbin::HELP/piece.png
+
+I'm sure you'll (cough) recognise the shapes.
+
+Once a piece has landed in the pit if a
+connection can be made between electrodes,
+or a loop of wires can be made, then these
+are removed and you score lovely points...
+
+#incbin::HELP/wire1.png
+
+#incbin::HELP/loop1.png
+
+If a connection cannot be made, as in this one:
+
+#incbin::HELP/wire2.png
+
+Then the peices are unglued and any hanging bits
+drop down into the pit to make other possible
+connections and loops...
+
+#incbin::HELP/wire3.png
+
+If a piece lands with anything sticking out of the
+top of the pit, it's GAME OVER.
+
+
+@SPECIAL PIECES
+
+Once in a while a special piece may drop down...
+
+
+!SMART BOMB
+
+$incbin::HELP/bomb.png
+
+This special will destroy all blocks that are the
+same as the one it lands on. Landing on nothing
+is perhaps not a good idea...
+
+
+!TWISTER
+
+$incbin::HELP/twister.png
+
+The twister will rotate all the pieces in the pit
+four times, scoring any loops and wires that
+are made from doing this.
+
+
+!SMART NUKE
+
+$incbin::HELP/nuke.png
+
+The smart nuke destroy all blocks that match
+the blocks surrounding the point were it lands.
+
+
+!SUPER CROSS
+
+~incbin::HELP/cross.png
+
+This will change all blocks above, below and to
+the left and right radiating out from the
+special to cross pieces.
+
+
+* * * * * * * * * * * * *
+
diff --git a/game.bmx b/game.bmx
index d07d1a3..3857f30 100644
--- a/game.bmx
+++ b/game.bmx
@@ -1,330 +1,346 @@
-' Hardwire
-'
-' Copyright 2005 Ian Cowburn
-'
-' $Id$
-'
-Strict
-Import "types.bmx"
-Import "particle.bmx"
-Import "sounds.bmx"
-Import "gametypes.bmx"
-
-Type TBufferedKey
- Global list:TList
- Field key:Int
- Field del:Int
- Field cnt:Int
-
- Function Clear()
- list=CreateList()
- End Function
-
- Function Create:TBufferedKey(key:Int, del:Int=30)
- Local o:TBufferedKey=New TBufferedKey
- o.key=key
- o.del=del
- o.cnt=0
- list.AddLast(o)
- Return o
- End Function
-
- Function Flush()
- For Local k:TBufferedKey=EachIn list
- k.cnt=0
- Next
- End Function
-
- Function Idle()
- For Local k:TBufferedKey=EachIn list
- If k.cnt
- k.cnt:-1
- EndIf
- Next
- End Function
-
- Method ForceRelease()
- cnt=999999
- End Method
-
- Method Poll:Int()
- If KeyDown(key)
- If cnt
- cnt:-1
- Return False
- Else
- cnt=del
- Return True
- EndIf
- Else
- cnt=0
- Return False
- EndIf
- End Method
-End Type
-
-Type TGame
- Field level:Int
- Field score:Int
- Field gm:TGameMap
- Field timer:Int
- Field alpha:Double
- Field alphainc:Double
- Field count:Int
- Field total:Int
- Field block:TPiece
- Field nextblock:TPiece
- Field drop:Int
- Field fade:TFadeScreen
- Field bdrop:TGameBackdrop
- Field kleft:TBufferedKey
- Field kright:TBufferedKey
- Field krotleft:TBufferedKey
- Field krotright:TBufferedKey
- Field kdrop:TBufferedKey
-
- Method New()
- score=0
- gm=New TGameMap
- level=1
- Particles.Clear()
- TextParticles.Clear()
- ExplosionParticles.Clear()
- alpha=0.0
- alphainc=0.01
- count=0
- total=0
- nextblock=TPiece.Create(False)
- drop=False
- CreateNext(False)
- fade=TFadeScreen.FadeIn()
- bdrop=New TGameBackdrop
-
- TBufferedKey.Clear()
- kleft=TBufferedKey.Create(GameConfig.kleft)
- kright=TBufferedKey.Create(GameConfig.kright)
- krotleft=TBufferedKey.Create(GameConfig.krotleft)
- krotright=TBufferedKey.Create(GameConfig.krotright)
- kdrop=TBufferedKey.Create(GameConfig.kdrop,1)
- End Method
-
- Method SetInitLevel(l:Int)
- level=l
- SetTimer()
- End Method
-
- Method SetTimer()
- If drop
- timer=5
- Else
- timer=Max(HERTZ/5,(16-level)*HERTZ/5)
- EndIf
- End Method
-
- Method LevelUp()
- level:+1
- count=0
- End Method
-
- Method CreateNext(special:Int)
- block=nextblock
- block.y=-3
- block.x=Pit.WIDTH/2
- nextblock=TPiece.Create(special)
- nextblock.x=Pit.WIDTH+3
- nextblock.y=1
- drop=False
- End Method
-
- Method Pause()
- Local i:Timage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,MASKEDIMAGE|DYNAMICIMAGE|FILTEREDIMAGE)
-
- GrabImage(i,0,0)
- MidHandleImage(i)
- SetColor(255,255,255)
-
- FlushKeys()
-
- Local a:Int[]=[0,0,0,0,0,0,0,0]
- Local ac:Int[]=[7,6,5,4,3,2,1,0]
-
- While Not KeyHit(GameConfig.kpause)
- Cls
-
- Local al:Double=0.3
-
- For Local f:Int=0 Until a.length
- SetAlpha(al)
- SetRotation(a[f])
- SetScale(al*2,al*2)
- DrawImage(i,GraphicsWidth()/2,GraphicsHeight()/2)
- If ac[f]>0
- ac[f]:-1
- Else
- If f Mod 2
- a[f]:+1
- Else
- a[f]:-1
- EndIf
- EndIf
- al:+0.1
- Next
-
- SetRotation(0)
- SetScale(1,1)
- GameGFX.large.Centre("PAUSED",GraphicsHeight()/2-16)
-
- Flip
- Wend
-
- SetAlpha(1)
- SetRotation(0)
- SetScale(1,1)
-
- FlushKeys
- TBufferedKey.Flush()
- End Method
-
- Method Play:Int()
- Local playing:Int=True
-
- Cls
-
- bdrop.Draw()
-
- GameGFX.large.Draw("SCORE",0,0,255,255,0)
- GameGFX.large.Draw(score,0,20)
-
- GameGFX.large.Draw("LEVEL",0,100,255,255,0)
- GameGFX.large.Draw(level,0,120)
-
- GameGFX.large.Draw("HISCORE",0,200,255,255,0)
- If score>GameConfig.hiscore
- GameConfig.hiscore=score
- EndIf
- GameGFX.large.Draw(GameConfig.hiscore,0,220)
-
- nextblock.Draw()
-
- block.Draw()
-
- If Not gm.overflow
- If KeyHit(KEY_ESCAPE)
- playing=False
- EndIf
-
- If Not gm.BlockInteract()
- timer:-1
-
- If timer<=0
- SetTimer()
- block.y:+1
-
- If block.Collides(gm)
- block.y:-1
- block.AddToMap(gm)
- count:+1
- total:+1
- If count>10
- LevelUp()
- EndIf
-
- kdrop.ForceRelease()
-
- If Not gm.overflow
- score:+level*2
- CreateNext((total Mod 17)=0) ' 17
- Else
- FlushKeys()
- TBufferedKey.Flush()
- EndIf
- EndIf
- EndIf
-
- If kleft.Poll()
- block.x:-1
- If block.Collides(gm)
- block.x:+1
- EndIf
- EndIf
-
- If kright.Poll()
- block.x:+1
- If block.Collides(gm)
- block.x:-1
- EndIf
- EndIf
-
- If krotright.Poll()
- block.RotateRight()
- If block.Collides(gm)
- block.x:-1
- If block.Collides(gm)
- block.x:+1
- block.RotateLeft()
- EndIf
- EndIf
- EndIf
-
- If krotleft.Poll()
- block.RotateLeft()
- If block.Collides(gm)
- block.x:+1
- If block.Collides(gm)
- block.x:-1
- block.RotateRight()
- EndIf
- EndIf
- EndIf
-
- If kdrop.Poll()
- timer=0
- 'drop=True
- EndIf
- Else
- TBufferedKey.Idle()
- EndIf
-
- score:+gm.Draw()*level*20
- Else
- gm.Draw()
-
- SetAlpha(alpha)
- SetColor(255,255,255)
- DrawImage(GameGFX.gameover,GraphicsWidth()/2,GraphicsHeight()/2)
- SetAlpha(1)
- alpha:+alphainc
- If (alpha<=0.7 And alphainc<0) Or (alpha>=1.0 And alphainc>0)
- alpha=Max(0,Min(1,alpha))
- alphainc=-alphainc
- EndIf
-
- If KeyHit(KEY_ENTER) Or KeyHit(KEY_ESCAPE)
- playing=False
- EndIf
- EndIf
-
- Particles.Draw()
- ExplosionParticles.Draw()
- TextParticles.Draw()
-
- If KeyHit(GameConfig.kpause) And Not gm.overflow
- Pause()
- EndIf
-
- Sound.Process()
-
- If fade
- If fade.Fade()
- fade.Draw()
- Else
- fade=Null
- EndIf
- EndIf
-
- Flip
-
- Return playing
- End Method
-End Type
-
+' Hardwire
+'
+' Copyright (C) 2005 Ian Cowburn (ianc@noddybox.co.uk)
+'
+' This program is free software; you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation; either version 2 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY; without even the implied warranty of
+' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+' GNU General Public License for more details.
+'
+' You should have received a copy of the GNU General Public License
+' along with this program; if not, write to the Free Software
+' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+'
+' -------------------------------------------------------------------------
+'
+' $Id$
+'
+Strict
+Import "types.bmx"
+Import "particle.bmx"
+Import "sounds.bmx"
+Import "gametypes.bmx"
+
+Type TBufferedKey
+ Global list:TList
+ Field key:Int
+ Field del:Int
+ Field cnt:Int
+
+ Function Clear()
+ list=CreateList()
+ End Function
+
+ Function Create:TBufferedKey(key:Int, del:Int=30)
+ Local o:TBufferedKey=New TBufferedKey
+ o.key=key
+ o.del=del
+ o.cnt=0
+ list.AddLast(o)
+ Return o
+ End Function
+
+ Function Flush()
+ For Local k:TBufferedKey=EachIn list
+ k.cnt=0
+ Next
+ End Function
+
+ Function Idle()
+ For Local k:TBufferedKey=EachIn list
+ If k.cnt
+ k.cnt:-1
+ EndIf
+ Next
+ End Function
+
+ Method ForceRelease()
+ cnt=999999
+ End Method
+
+ Method Poll:Int()
+ If KeyDown(key)
+ If cnt
+ cnt:-1
+ Return False
+ Else
+ cnt=del
+ Return True
+ EndIf
+ Else
+ cnt=0
+ Return False
+ EndIf
+ End Method
+End Type
+
+Type TGame
+ Field level:Int
+ Field score:Int
+ Field gm:TGameMap
+ Field timer:Int
+ Field alpha:Double
+ Field alphainc:Double
+ Field count:Int
+ Field total:Int
+ Field block:TPiece
+ Field nextblock:TPiece
+ Field drop:Int
+ Field fade:TFadeScreen
+ Field bdrop:TGameBackdrop
+ Field kleft:TBufferedKey
+ Field kright:TBufferedKey
+ Field krotleft:TBufferedKey
+ Field krotright:TBufferedKey
+ Field kdrop:TBufferedKey
+
+ Method New()
+ score=0
+ gm=New TGameMap
+ level=1
+ Particles.Clear()
+ TextParticles.Clear()
+ ExplosionParticles.Clear()
+ alpha=0.0
+ alphainc=0.01
+ count=0
+ total=0
+ nextblock=TPiece.Create(False)
+ drop=False
+ CreateNext(False)
+ fade=TFadeScreen.FadeIn()
+ bdrop=New TGameBackdrop
+
+ TBufferedKey.Clear()
+ kleft=TBufferedKey.Create(GameConfig.kleft)
+ kright=TBufferedKey.Create(GameConfig.kright)
+ krotleft=TBufferedKey.Create(GameConfig.krotleft)
+ krotright=TBufferedKey.Create(GameConfig.krotright)
+ kdrop=TBufferedKey.Create(GameConfig.kdrop,1)
+ End Method
+
+ Method SetInitLevel(l:Int)
+ level=l
+ SetTimer()
+ End Method
+
+ Method SetTimer()
+ If drop
+ timer=5
+ Else
+ timer=Max(5,(20-level)*5)
+ EndIf
+ End Method
+
+ Method LevelUp()
+ level:+1
+ count=0
+ End Method
+
+ Method CreateNext(special:Int)
+ block=nextblock
+ block.y=-3
+ block.x=Pit.WIDTH/2
+ nextblock=TPiece.Create(special)
+ nextblock.x=Pit.WIDTH+3
+ nextblock.y=1
+ drop=False
+ End Method
+
+ Method Pause()
+ Local i:Timage=CreateImage(GraphicsWidth(),GraphicsHeight(),1,MASKEDIMAGE|DYNAMICIMAGE|FILTEREDIMAGE)
+
+ GrabImage(i,0,0)
+ MidHandleImage(i)
+ SetColor(255,255,255)
+
+ FlushKeys()
+
+ Local a:Int[]=[0,0,0,0,0,0,0,0]
+ Local ac:Int[]=[7,6,5,4,3,2,1,0]
+
+ While Not KeyHit(GameConfig.kpause)
+ Cls
+
+ Local al:Double=0.3
+
+ For Local f:Int=0 Until a.length
+ SetAlpha(al)
+ SetRotation(a[f])
+ SetScale(al*2,al*2)
+ DrawImage(i,GraphicsWidth()/2,GraphicsHeight()/2)
+ If ac[f]>0
+ ac[f]:-1
+ Else
+ If f Mod 2
+ a[f]:+1
+ Else
+ a[f]:-1
+ EndIf
+ EndIf
+ al:+0.1
+ Next
+
+ SetRotation(0)
+ SetScale(1,1)
+ GameGFX.large.Centre("PAUSED",GraphicsHeight()/2-16)
+
+ Flip
+ Wend
+
+ SetAlpha(1)
+ SetRotation(0)
+ SetScale(1,1)
+
+ FlushKeys
+ TBufferedKey.Flush()
+ End Method
+
+ Method Play:Int()
+ Local playing:Int=True
+
+ Cls
+
+ bdrop.Draw()
+
+ GameGFX.large.Draw("SCORE",0,0,255,255,0)
+ GameGFX.large.Draw(Number.Format(score),0,20)
+
+ GameGFX.large.Draw("LEVEL",0,100,255,255,0)
+ GameGFX.large.Draw(level,0,120)
+
+ GameGFX.large.Draw("HISCORE",0,200,255,255,0)
+ If score>GameConfig.hiscore
+ GameConfig.hiscore=score
+ EndIf
+ GameGFX.large.Draw(Number.Format(GameConfig.hiscore),0,220)
+
+ nextblock.Draw()
+
+ block.Draw()
+
+ If Not gm.overflow
+ If KeyHit(KEY_ESCAPE)
+ playing=False
+ EndIf
+
+ If Not gm.BlockInteract()
+ timer:-1
+
+ If timer<=0
+ SetTimer()
+ block.y:+1
+
+ If block.Collides(gm)
+ block.y:-1
+ block.AddToMap(gm)
+ count:+1
+ total:+1
+ If count>10
+ LevelUp()
+ EndIf
+
+ kdrop.ForceRelease()
+
+ If Not gm.overflow
+ score:+level*2
+ CreateNext((total Mod 17)=0) ' 17
+ Else
+ FlushKeys()
+ TBufferedKey.Flush()
+ EndIf
+ EndIf
+ EndIf
+
+ If kleft.Poll()
+ block.x:-1
+ If block.Collides(gm)
+ block.x:+1
+ EndIf
+ EndIf
+
+ If kright.Poll()
+ block.x:+1
+ If block.Collides(gm)
+ block.x:-1
+ EndIf
+ EndIf
+
+ If krotright.Poll()
+ block.RotateRight()
+ If block.Collides(gm)
+ block.x:-1
+ If block.Collides(gm)
+ block.x:+1
+ block.RotateLeft()
+ EndIf
+ EndIf
+ EndIf
+
+ If krotleft.Poll()
+ block.RotateLeft()
+ If block.Collides(gm)
+ block.x:+1
+ If block.Collides(gm)
+ block.x:-1
+ block.RotateRight()
+ EndIf
+ EndIf
+ EndIf
+
+ If kdrop.Poll()
+ timer=0
+ 'drop=True
+ EndIf
+ Else
+ TBufferedKey.Idle()
+ EndIf
+
+ score:+gm.Draw()*level*20
+ Else
+ gm.Draw()
+
+ SetAlpha(alpha)
+ SetColor(255,255,255)
+ DrawImage(GameGFX.gameover,GraphicsWidth()/2,GraphicsHeight()/2)
+ SetAlpha(1)
+ alpha:+alphainc
+ If (alpha<=0.7 And alphainc<0) Or (alpha>=1.0 And alphainc>0)
+ alpha=Max(0,Min(1,alpha))
+ alphainc=-alphainc
+ EndIf
+
+ If KeyHit(KEY_ENTER) Or KeyHit(KEY_ESCAPE)
+ playing=False
+ EndIf
+ EndIf
+
+ Particles.Draw()
+ ExplosionParticles.Draw()
+ TextParticles.Draw()
+
+ If KeyHit(GameConfig.kpause) And Not gm.overflow
+ Pause()
+ EndIf
+
+ Sound.Process()
+
+ If fade
+ If fade.Fade()
+ fade.Draw()
+ Else
+ fade=Null
+ EndIf
+ EndIf
+
+ Flip
+
+ Return playing
+ End Method
+End Type
+
diff --git a/gametypes.bmx b/gametypes.bmx
index 24d1617..5875363 100644
--- a/gametypes.bmx
+++ b/gametypes.bmx
@@ -1,960 +1,977 @@
-' Hardwire
-'
-' Copyright 2005 Ian Cowburn
-'
-' $Id$
-'
-Strict
-Import "types.bmx"
-Import "particle.bmx"
-Import "sounds.bmx"
-
-Type Pit
- Const WIDTH=10
- Const HEIGHT=13
-
- Function X:Int(p:Int)
- Return 230+p*32
- End Function
-
- Function Y:Int(p:Int)
- Return 120+p*32
- End Function
-End Type
-
-Type TWire
- Const CROSS:Int=0
- Const LEFT_RIGHT:Int=1
- Const TOP_BOTTOM:Int=2
- Const TOP_LEFT:Int=3
- Const TOP_RIGHT:Int=4
- Const BOTTOM_LEFT:Int=5
- Const BOTTOM_RIGHT:Int=6
- Const SPECIAL_BOMB:Int=7
- Const SPECIAL_TWISTER:Int=8
- Const SPECIAL_NUKE:Int=9
- Const SPECIAL_CROSS:Int=10
-
- Const DIR_NONE:Int=0
- Const DIR_UP:Int=1
- Const DIR_RIGHT:Int=2
- Const DIR_DOWN:Int=3
- Const DIR_LEFT:Int=4
-
- Global rotright:Int[]
- Global rotleft:Int[]
- Global img:TImage[]
- Global dir:Int[][]
- Global dx:Int[]
- Global dy:Int[]
-
- Global dirname:String[]
- Global typename:String[]
-
- Field t:Int
-
- Function Init()
- rotright=[0,2,1,4,6,3,5,7,8,9,10]
- rotleft=[0,2,1,5,3,6,4,7,8,9,10]
-
- img=[GameGFX.cross, ..
- GameGFX.left_right, ..
- GameGFX.top_bottom, ..
- GameGFX.top_left, ..
- GameGFX.top_right, ..
- GameGFX.bottom_left, ..
- GameGFX.bottom_right, ..
- GameGFX.special_bomb, ..
- GameGFX.special_twister, ..
- GameGFX.special_nuke, ..
- GameGFX.special_cross]
-
- dir=[[DIR_UP,DIR_RIGHT,DIR_DOWN,DIR_LEFT], .. ' CROSS
- [DIR_NONE,DIR_RIGHT,DIR_NONE,DIR_LEFT], .. ' LEFT_RIGHT
- [DIR_UP,DIR_NONE,DIR_DOWN,DIR_NONE], .. ' TOP_BOTTOM
- [DIR_NONE,DIR_UP,DIR_LEFT,DIR_NONE], .. ' TOP_LEFT
- [DIR_NONE,DIR_NONE,DIR_RIGHT,DIR_UP], .. ' TOP_RIGHT
- [DIR_LEFT,DIR_DOWN,DIR_NONE,DIR_NONE], .. ' BOTTOM_LEFT
- [DIR_RIGHT,DIR_NONE,DIR_NONE,DIR_DOWN], .. ' BOTTOM_RIGHT
- [DIR_NONE,DIR_NONE,DIR_NONE,DIR_NONE], .. ' SPECIAL_BOMB
- [DIR_NONE,DIR_NONE,DIR_NONE,DIR_NONE], .. ' SPECIAL_TWISTER
- [DIR_NONE,DIR_NONE,DIR_NONE,DIR_NONE], .. ' SPECIAL_NUKE
- [DIR_NONE,DIR_NONE,DIR_NONE,DIR_NONE]] ' SPECIAL_CROSS
-
- dx=[0,0,1,0,-1]
- dy=[0,-1,0,1,0]
-
- dirname=["NONE","UP","RIGHT","DOWN","LEFT"]
- typename=["CROSS","LEFT_RIGHT","TOP_BOTTOM","TOP_LEFT","TOP_RIGHT","BOTTOM_LEFT","BOTTOM_RIGHT","SPECIAL BOMB","SPECIAL TWISTER"]
- End Function
-
- Method New()
- t=Rand(0,6)
- End Method
-
- Function Create:TWire(t:Int[])
- Local o:TWire=New TWire
- o.t=t[Rand(0,t.length-1)]
- Return o
- End Function
-
- Method Image:TImage()
- Return img[t]
- End Method
-
- Method RotateLeft()
- t=rotleft[t]
- End Method
-
- Method RotateRight()
- t=rotright[t]
- End Method
-
- Method Traverse:Int(d:Int)
- If d=DIR_NONE
- Return DIR_NONE
- EndIf
-
- Return dir[t][d-1]
- End Method
-
- Function DirX:Int(d:Int)
- Return dx[d]
- End Function
-
- Function DirY:Int(d:Int)
- Return dy[d]
- End Function
-End Type
-
-Type TPiece Abstract
- Field x:Int
- Field y:Int
- Field ox:Int
- Field oy:Int
- Field map:TWire[4,4]
- Field rot:Int
- Field offx:Int[4]
- Field offy:Int[4]
- Field special:Int
- Field special_pulse:Int
- Field col:Int
- Field coli:Int
- Field frame:Int
- Field framed:Int
- Field framespd:Int
- Field framei:Int
- Field pong:Int
-
- Function Create:TPiece(special:Int)
- Local o:TPiece
-
- If special
- Select Rand(0,3)
- Case 0
- o=TPiece(New TPiece_SpecialBomb)
- Case 1
- o=TPiece(New TPiece_SpecialTwister)
- Case 2
- o=TPiece(New TPiece_SpecialNuke)
- Case 3
- o=TPiece(New TPiece_SpecialCross)
- End Select
- Else
- Select Rand(0,5)
- Case 0
- o=TPiece(New TPiece_S_Left)
- Case 1
- o=TPiece(New TPiece_S_Right)
- Case 2
- o=TPiece(New TPiece_L_Left)
- Case 3
- o=TPiece(New TPiece_L_Right)
- Case 4
- o=TPiece(New TPiece_Square)
- Case 5
- o=TPiece(New TPiece_Bar)
- End Select
- EndIf
-
- o.BaseInit(special)
-
- Return o
- End Function
-
- Function CreateSpecific:TPiece(t:Int)
- Local o:TPiece
- Local s:Int=False
-
- Select t
- Case 0
- o=TPiece(New TPiece_S_Left)
- Case 1
- o=TPiece(New TPiece_S_Right)
- Case 2
- o=TPiece(New TPiece_L_Left)
- Case 3
- o=TPiece(New TPiece_L_Right)
- Case 4
- o=TPiece(New TPiece_Square)
- Case 5
- o=TPiece(New TPiece_Bar)
- Case 6
- o=TPiece(New TPiece_SpecialBomb)
- s=True
- Case 7
- o=TPiece(New TPiece_SpecialTwister)
- s=True
- Case 8
- o=TPiece(New TPiece_SpecialNuke)
- s=True
- Case 9
- o=TPiece(New TPiece_SpecialCross)
- s=True
- Default
- Return Create(False)
- End Select
-
- o.BaseInit(s)
-
- Return o
- End Function
-
- Method Init() Abstract
-
- Method BaseInit(special:Int)
- special_pulse=False
- framespd=5
- pong=False
- Init()
- rot=0
- ox=offx[rot]
- oy=offy[rot]
- self.special=special
- col=255
- coli=-1
- frame=0
- framed=0
- framei=1
- End Method
-
- Method Draw()
- If special
- col:+coli
- If col=255 Or col=128
- coli=-coli
- EndIf
-
- framed:+1
- If framed=framespd
- framed=0
- If pong
- frame:+framei
- If frame=0 Or frame=3
- framei=-framei
- EndIf
- Else
- frame=(frame+1) Mod 4
- EndIf
- EndIf
-
- For Local px:Int=0 Until 4
- For Local py:Int=0 Until 4
- If map[px,py]
- Local gx:Int=Pit.X(x-ox+px)
- Local gy:Int=Pit.Y(y-oy+py)
- SetColor(255,255,255)
- DrawImage(GameGFX.tile,gx,gy)
- If special_pulse
- SetColor(col,col/2,255-col)
- EndIf
- DrawImage(map[px,py].Image(),gx,gy,frame)
- EndIf
- Next
- Next
- Else
- For Local px:Int=0 Until 4
- For Local py:Int=0 Until 4
- If map[px,py]
- Local gx:Int=Pit.X(x-ox+px)
- Local gy:Int=Pit.Y(y-oy+py)
- SetColor(255,255,255)
- DrawImage(GameGFX.tile,gx,gy)
- SetColor(128,128,128)
- DrawImage(map[px,py].Image(),gx,gy)
- EndIf
- Next
- Next
- EndIf
- End Method
-
- Method RotateLeft()
- If special Then Return
-
- If rot=0
- rot=3
- Else
- rot:-1
- EndIf
-
- ox=offx[rot]
- oy=offy[rot]
-
- Local m:TWire[4,4]
-
- For Local px:Int=0 Until 4
- For Local py:Int=0 Until 4
- If map[px,py]
- map[px,py].RotateLeft()
- EndIf
- m[py,3-px]=map[px,py]
- Next
- Next
-
- map=m
- End Method
-
- Method RotateRight()
- If special Then Return
-
- rot=(rot+1) Mod 4
-
- ox=offx[rot]
- oy=offy[rot]
-
- Local m:TWire[4,4]
-
- For Local px:Int=0 Until 4
- For Local py:Int=0 Until 4
- If map[px,py]
- map[px,py].RotateRight()
- EndIf
- m[3-py,px]=map[px,py]
- Next
- Next
-
- map=m
- End Method
-
- Method Collides:Int(gm:TGameMap)
- For Local px:Int=0 Until 4
- For Local py:Int=0 Until 4
- If map[px,py]
- Local gx:Int=x-ox+px
- Local gy:Int=y-oy+py
-
- If gx<0 Or gx>=Pit.WIDTH Or gy>=Pit.HEIGHT
- Return True
- EndIf
-
- If gy>=0 And gm.map[gx,gy]
- Return True
- EndIf
- EndIf
- Next
- Next
-
- Return False
- End Method
-
- Method AddToMap(gm:TGameMap)
- If special
- gm.SetSpecial(TSpecial(Self))
- Else
- For Local px:Int=0 Until 4
- For Local py:Int=0 Until 4
- If map[px,py]
- Local gx:Int=x-ox+px
- Local gy:Int=y-oy+py
-
- If gy<0
- gm.overflow=True
- Else
- gm.map[gx,gy]=map[px,py]
-
- If gy=Pit.HEIGHT-1 Or gm.map[gx,gy+1]
- Particles.AddDust(Pit.X(gx)+16,Pit.Y(gy)+32)
- EndIf
- EndIf
- EndIf
- Next
- Next
-
- Sound.Click()
-
- If Not gm.overflow
- If Not gm.CheckWires()
- gm.Flatten()
- gm.CheckWires()
- EndIf
- EndIf
- EndIf
- End Method
-End Type
-
-Type TSpecial Extends TPiece Abstract
- Method DoSpecial:Int(gm:TGameMap) Abstract
-End Type
-
-Type TPiece_S_Right Extends TPiece
- Method Init()
- map[1,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_RIGHT])
- map[2,0]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.BOTTOM_LEFT,TWire.LEFT_RIGHT])
- map[0,1]=TWire.Create([TWire.CROSS,TWire.TOP_RIGHT,TWire.BOTTOM_RIGHT,TWire.LEFT_RIGHT])
- map[1,1]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT])
- offx=[1,2,2,0]
- offy=[1,1,2,2]
- End Method
-End Type
-
-
-Type TPiece_S_Left Extends TPiece
- Method Init()
- map[0,0]=TWire.Create([TWire.CROSS,TWire.TOP_RIGHT,TWire.BOTTOM_RIGHT,TWire.LEFT_RIGHT])
- map[1,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_LEFT])
- map[1,1]=TWire.Create([TWire.CROSS,TWire.TOP_RIGHT])
- map[2,1]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.BOTTOM_LEFT,TWire.LEFT_RIGHT])
- offx=[1,2,2,0]
- offy=[1,1,2,2]
- End Method
-End Type
-
-
-Type TPiece_L_Right Extends TPiece
- Method Init()
- map[0,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_RIGHT])
- map[1,0]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.BOTTOM_LEFT,TWire.LEFT_RIGHT])
- map[0,1]=TWire.Create([TWire.CROSS,TWire.TOP_BOTTOM])
- map[0,2]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.TOP_RIGHT,TWire.TOP_BOTTOM])
- offx=[0,2,3,1]
- offy=[1,0,2,3]
- End Method
-End Type
-
-
-Type TPiece_L_Left Extends TPiece
- Method Init()
- map[0,0]=TWire.Create([TWire.CROSS,TWire.TOP_RIGHT,TWire.BOTTOM_RIGHT,TWire.LEFT_RIGHT])
- map[1,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_LEFT])
- map[1,1]=TWire.Create([TWire.CROSS,TWire.TOP_BOTTOM])
- map[1,2]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.TOP_RIGHT,TWire.TOP_BOTTOM])
- offx=[1,2,2,1]
- offy=[1,1,2,2]
- End Method
-End Type
-
-
-Type TPiece_Square Extends TPiece
- Method Init()
- map[0,0]=TWire.Create([TWire.CROSS])
- map[1,0]=TWire.Create([TWire.CROSS])
- map[0,1]=TWire.Create([TWire.CROSS])
- map[1,1]=TWire.Create([TWire.CROSS])
- offx=[0,2,2,0]
- offy=[1,1,3,3]
- End Method
-End Type
-
-
-Type TPiece_Bar Extends TPiece
- Method Init()
- map[1,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_LEFT,TWire.BOTTOM_RIGHT,TWire.TOP_BOTTOM])
- map[1,1]=TWire.Create([TWire.CROSS,TWire.TOP_BOTTOM])
- map[1,2]=TWire.Create([TWire.CROSS,TWire.TOP_BOTTOM])
- map[1,3]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.TOP_RIGHT,TWire.TOP_BOTTOM])
- offx=[1,1,2,1]
- offy=[1,1,1,2]
- End Method
-End Type
-
-Type TPiece_SpecialBomb Extends TSpecial
- Method Init()
- map[0,0]=TWire.Create([TWire.SPECIAL_BOMB])
- offx=[0,0,0,0]
- offy=[0,0,0,0]
- End Method
-
- Method DoSpecial:Int(gm:TGameMap)
- Draw()
-
- Local l:TWireList=New TWireList
-
- If y<Pit.HEIGHT-1
- Local t:Int=gm.map[x,y+1].t
-
- For Local px:Int=0 Until Pit.WIDTH
- For Local py:Int=0 Until Pit.HEIGHT
- If gm.map[px,py] And gm.map[px,py].t=t
- l.Add(px,py,gm.map[px,py])
- EndIf
- Next
- Next
- EndIf
-
- If l.Count()=0
- TextParticles.Big("WHAT A WASTE!",255,0,0)
- Else
- TextParticles.Big("SMART BOMB!",255,255,0)
- gm.path.AddLast(l)
- EndIf
-
- ExplosionParticles.BlowUp(Pit.X(x),Pit.Y(y))
-
- Return False
- End Method
-End Type
-
-Type TPiece_SpecialTwister Extends TSpecial
- Field rot:Int
- Field rotd:Int
-
- Method Init()
- rot=0
- rotd=0
- special_pulse=True
- map[0,0]=TWire.Create([TWire.SPECIAL_TWISTER])
- offx=[0,0,0,0]
- offy=[0,0,0,0]
- End Method
-
- Method DoSpecial:Int(gm:TGameMap)
- Draw()
-
- If gm.path.Count()
- Return True
- EndIf
-
- If rotd=0
- rotd=60
- rot:+1
- If rot=5
- ExplosionParticles.BlowUp(Pit.X(x),Pit.Y(y))
- Return False
- EndIf
- TextParticles.Big("TWIST!")
- Else
- rotd:-1
- Return True
- EndIf
-
- For Local px:Int=0 Until Pit.WIDTH
- For Local py:Int=0 Until Pit.HEIGHT
- If gm.map[px,py]
- gm.map[px,py].RotateRight()
- Particles.AddDust(Pit.X(px)+16,Pit.Y(py)+32)
- EndIf
- Next
- Next
-
- Sound.Click()
-
- If Not gm.CheckWires()
- gm.Flatten()
- gm.CheckWires()
- EndIf
-
- Return True
- End Method
-End Type
-
-Type TPiece_SpecialNuke Extends TSpecial
- Method Init()
- special_pulse=True
- map[0,0]=TWire.Create([TWire.SPECIAL_NUKE])
- offx=[0,0,0,0]
- offy=[0,0,0,0]
- End Method
-
- Method AddToList(gm:TGameMap, l:TWireList, t:Int)
- For Local px:Int=0 Until Pit.WIDTH
- For Local py:Int=0 Until Pit.HEIGHT
- If gm.map[px,py] And gm.map[px,py].t=t
- l.Add(px,py,gm.map[px,py])
- EndIf
- Next
- Next
- End Method
-
- Method DoSpecial:Int(gm:TGameMap)
- Draw()
-
- Local l:TWireList=New TWireList
-
- If y<Pit.HEIGHT-1 And gm.map[x,y+1]
- AddToList(gm,l,gm.map[x,y+1].t)
- EndIf
-
- If x>0 And gm.map[x-1,y]
- AddToList(gm,l,gm.map[x-1,y].t)
- EndIf
-
- If x<Pit.WIDTH-1 And gm.map[x+1,y]
- AddToList(gm,l,gm.map[x+1,y].t)
- EndIf
-
- If l.Count()=0
- TextParticles.Big("WHAT A WASTE!",255,0,0)
- Else
- TextParticles.Big("SMART NUKE!",255,255,0)
- gm.path.AddLast(l)
- EndIf
-
- ExplosionParticles.BlowUp(Pit.X(x),Pit.Y(y))
-
- Return False
- End Method
-End Type
-
-Type TPiece_SpecialCross Extends TSpecial
-
- Method Init()
- special_pulse=True
- pong=True
- map[0,0]=TWire.Create([TWire.SPECIAL_CROSS])
- offx=[0,0,0,0]
- offy=[0,0,0,0]
- End Method
-
- Method DoSpecial:Int(gm:TGameMap)
- Draw()
-
- TextParticles.Big("SUPER CROSS!",255,255,0)
-
- For Local px:Int=x+1 Until Pit.WIDTH
- If gm.map[px,y]
- gm.map[px,y].t=TWire.CROSS
- Particles.AddDust(Pit.X(px)+16,Pit.Y(y)+32)
- EndIf
- Next
-
- For Local px:Int=0 Until x
- If gm.map[px,y]
- gm.map[px,y].t=TWire.CROSS
- Particles.AddDust(Pit.X(px)+16,Pit.Y(y)+32)
- EndIf
- Next
-
- For Local py:Int=y+1 Until Pit.HEIGHT
- If gm.map[x,py]
- gm.map[x,py].t=TWire.CROSS
- Particles.AddDust(Pit.X(x)+16,Pit.Y(py)+32)
- EndIf
- Next
-
- If Not gm.CheckWires()
- gm.Flatten()
- gm.CheckWires()
- EndIf
-
- ExplosionParticles.BlowUp(Pit.X(x),Pit.Y(y))
-
- Return False
- End Method
-End Type
-
-
-Type TWireListEnt
- Field w:TWire
- Field x:Int
- Field y:Int
-
- Function Create:TWireListEnt(x:Int, y:Int, w:TWire)
- Local o:TWireListEnt=New TWireListEnt
- o.x=x
- o.y=y
- o.w=w
- Return o
- End Function
-End Type
-
-
-Type TWireList
- Field list:TList
- Field col:Int
-
- Method New()
- list=CreateList()
- col=128
- End Method
-
- Method Add(x:Int, y:Int, w:TWire)
- list.AddLast(TWireListEnt.Create(x,y,w))
- End Method
-
- Method Draw:Int()
- col=Min(255,col+5)
- SetColor(col,col,col)
- For Local e:TWireListEnt=EachIn list
- DrawImage(e.w.Image(),Pit.X(e.x),Pit.Y(e.y))
- Next
-
- If col<255
- Return True
- Else
- For Local e:TWireListEnt=EachIn list
- Particles.AddImage(e.w.Image(),Pit.X(e.x),Pit.Y(e.y))
- Next
- Return False
- EndIf
- End Method
-
- Method Count:Int()
- Return list.Count()
- End Method
-End Type
-
-
-Type TGameMap
- Field map:TWire[Pit.WIDTH,Pit.HEIGHT]
- Field trode_col:Int
- Field trode_coli:Int
- Field overflow:Int
- Field cx:Int
- Field cy:Int
- Field path:TList
- Field special:TSpecial
-
- Method New()
- trode_col=0
- trode_coli=1
- overflow=False
- path=CreateList()
- special=Null
- End Method
-
- Method BlockInteract:Int()
- Return overflow Or path.Count() Or special
- End Method
-
- Method FindPath:Int(l:TWireList, x:Int, y:Int, dir:Int)
- If y<0
- Return False
- EndIf
-
- If x<0 Or x=Pit.WIDTH Or y=Pit.HEIGHT
- Return True
- EndIf
-
- Local w:TWire=map[x,y]
-
- If Not w
- Return False
- EndIf
-
- dir=w.Traverse(dir)
-
- If dir=TWire.DIR_NONE
- Return False
- EndIf
-
- l.Add(x,y,w)
-
- Return FindPath(l,x+TWire.DirX(dir),y+TWire.DirY(dir),dir)
- End Method
-
- Method FindLoop:Int(l:TWireList, ox:Int, oy:Int, x:Int, y:Int, dir:Int)
- If y<0 Or x<0 Or x=Pit.WIDTH Or y=Pit.HEIGHT
- Return False
- EndIf
-
- Local w:TWire=map[x,y]
-
- If Not w
- Return False
- EndIf
-
- dir=w.Traverse(dir)
-
- If dir=TWire.DIR_NONE
- Return False
- EndIf
-
- l.Add(x,y,w)
-
- x:+TWire.DirX(dir)
- y:+TWire.DirY(dir)
-
- If x=ox And y=oy And dir=TWire.DIR_RIGHT
- Return True
- EndIf
-
- Return FindLoop(l,ox,oy,x,y,dir)
- End Method
-
- Method CheckWires:Int()
- Local loop:Int=False
- Local wire:Int=False
-
- For Local y:Int=0 Until Pit.HEIGHT
- Local l:TWireList=New TWireList
-
- If FindPath(l,0,y,TWire.DIR_RIGHT)
- path.AddLast(l)
- EndIf
-
- l=New TWireList
-
- If FindPath(l,Pit.WIDTH-1,y,TWire.DIR_LEFT)
- path.AddLast(l)
- wire=True
- EndIf
- Next
-
- For Local x:Int=0 Until Pit.WIDTH
- Local l:TWireList=New TWireList
-
- If FindPath(l,x,Pit.HEIGHT-1,TWire.DIR_UP)
- path.AddLast(l)
- wire=True
- EndIf
- Next
-
- For Local x:Int=0 Until Pit.WIDTH
- For Local y:Int=0 Until Pit.HEIGHT
- If map[x,y]
- Local l:TWireList=New TWireList
- Select map[x,y].t
- Case TWire.CROSS, TWire.LEFT_RIGHT, TWire.TOP_LEFT, TWire.BOTTOM_LEFT
- If FindLoop(l,x,y,x,y,TWire.DIR_RIGHT)
- path.AddLast(l)
- loop=True
- EndIf
- End Select
- EndIf
- Next
- Next
-
- If loop And wire
- TextParticles.Big("LOOP AND WIRE",255,0,255)
- ElseIf loop
- TextParticles.Big("LOOP",255,0,255)
- ElseIf wire
- TextParticles.Big("WIRE",255,0,255)
- EndIf
-
- Return loop Or wire
- End Method
-
- Method SetSpecial(s:TSpecial)
- special=s
- End Method
-
- Method DropColumn(x:Int, y:Int)
- While y>0
- map[x,y]=map[x,y-1]
- y:-1
- Wend
- map[x,0]=Null
- End Method
-
- Method AnyAbove:Int(x:Int, y:Int)
- While y>=0
- If map[x,y]
- Return True
- EndIf
- y:-1
- Wend
-
- Return False
- End Method
-
- Method Flatten()
- For Local x:Int=0 Until Pit.WIDTH
- Local y:Int=Pit.HEIGHT-1
- Local drop:Int=False
-
- While y>0 And AnyAbove(x,y)
- If map[x,y]
- If drop
- Particles.AddDust(Pit.X(x)+16,Pit.Y(y)+32)
- EndIf
- drop=False
- y:-1
- Else
- DropColumn(x,y)
- EndIf
- Wend
- Next
- End Method
-
- Method Draw:Int()
- Local score:Int=0
-
- SetColor(255,255,255)
- DrawImage(GameGFX.pit_bottomleft,Pit.X(-1),Pit.Y(Pit.HEIGHT))
- DrawImage(GameGFX.pit_bottomright,Pit.X(Pit.WIDTH),Pit.Y(Pit.HEIGHT))
-
- DrawImage(GameGFX.pit_top,Pit.X(-1),Pit.Y(0))
- DrawImage(GameGFX.pit_top,Pit.X(Pit.WIDTH),Pit.Y(0))
- SetColor(trode_col,trode_col,0)
- DrawImage(GameGFX.trode_left,Pit.X(-1),Pit.Y(0))
- DrawImage(GameGFX.trode_right,Pit.X(Pit.WIDTH),Pit.Y(0))
-
- For Local f:Int=0 Until Pit.WIDTH
- SetColor(255,255,255)
- DrawImage(GameGFX.pit_bottom,Pit.X(f),Pit.Y(Pit.HEIGHT))
- SetColor(trode_col,trode_col,0)
- DrawImage(GameGFX.trode_bottom,Pit.X(f),Pit.Y(Pit.HEIGHT))
- Next
-
- For Local f:Int=1 Until Pit.HEIGHT
- SetColor(255,255,255)
- DrawImage(GameGFX.pit_side,Pit.X(-1),Pit.Y(f))
- DrawImage(GameGFX.pit_side,Pit.X(Pit.WIDTH),Pit.Y(f))
- SetColor(trode_col,trode_col,0)
- DrawImage(GameGFX.trode_left,Pit.X(-1),Pit.Y(f))
- DrawImage(GameGFX.trode_right,Pit.X(Pit.WIDTH),Pit.Y(f))
- Next
-
- For Local x:Int=0 Until Pit.WIDTH
- For Local y:Int=0 Until Pit.HEIGHT
- If map[x,y]
- SetColor(255,255,255)
- DrawImage(GameGFX.tile,Pit.X(x),Pit.Y(y))
- SetColor(trode_col,trode_col,0)
- DrawImage(map[x,y].Image(),Pit.X(x),Pit.Y(y))
- EndIf
- Next
- Next
-
- If special
- If Not special.DoSpecial(Self)
- special=Null
- EndIf
- EndIf
-
- Local l:TEasyLink=TEasyLink.Create(path)
- Local check:Int=False
-
- While l.Value()
- Local b:TWireList=TWireList(l.Value())
-
- If b.Draw()
- l.MoveNext()
- Else
- If Not overflow
- score:+b.list.Count()
- For Local e:TWireListEnt=EachIn b.list
- map[e.x,e.y]=Null
- Next
- EndIf
- l.Remove()
- check=True
- EndIf
- Wend
-
- If check
- Sound.Path()
- Flatten()
- CheckWires()
- EndIf
-
- trode_col:+trode_coli
-
- If (trode_col=255 And trode_coli>0) Or (trode_col=200 And trode_coli<0)
- trode_coli=-trode_coli
- EndIf
-
- Return score
- End Method
-End Type
+' Hardwire
+'
+' Copyright (C) 2005 Ian Cowburn (ianc@noddybox.co.uk)
+'
+' This program is free software; you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation; either version 2 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY; without even the implied warranty of
+' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+' GNU General Public License for more details.
+'
+' You should have received a copy of the GNU General Public License
+' along with this program; if not, write to the Free Software
+' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+'
+' -------------------------------------------------------------------------
+'
+' $Id$
+'
+Strict
+Import "types.bmx"
+Import "particle.bmx"
+Import "sounds.bmx"
+
+Type Pit
+ Const WIDTH=10
+ Const HEIGHT=13
+
+ Function X:Int(p:Int)
+ Return 230+p*32
+ End Function
+
+ Function Y:Int(p:Int)
+ Return 120+p*32
+ End Function
+End Type
+
+Type TWire
+ Const CROSS:Int=0
+ Const LEFT_RIGHT:Int=1
+ Const TOP_BOTTOM:Int=2
+ Const TOP_LEFT:Int=3
+ Const TOP_RIGHT:Int=4
+ Const BOTTOM_LEFT:Int=5
+ Const BOTTOM_RIGHT:Int=6
+ Const SPECIAL_BOMB:Int=7
+ Const SPECIAL_TWISTER:Int=8
+ Const SPECIAL_NUKE:Int=9
+ Const SPECIAL_CROSS:Int=10
+
+ Const DIR_NONE:Int=0
+ Const DIR_UP:Int=1
+ Const DIR_RIGHT:Int=2
+ Const DIR_DOWN:Int=3
+ Const DIR_LEFT:Int=4
+
+ Global rotright:Int[]
+ Global rotleft:Int[]
+ Global img:TImage[]
+ Global dir:Int[][]
+ Global dx:Int[]
+ Global dy:Int[]
+
+ Global dirname:String[]
+ Global typename:String[]
+
+ Field t:Int
+
+ Function Init()
+ rotright=[0,2,1,4,6,3,5,7,8,9,10]
+ rotleft=[0,2,1,5,3,6,4,7,8,9,10]
+
+ img=[GameGFX.cross, ..
+ GameGFX.left_right, ..
+ GameGFX.top_bottom, ..
+ GameGFX.top_left, ..
+ GameGFX.top_right, ..
+ GameGFX.bottom_left, ..
+ GameGFX.bottom_right, ..
+ GameGFX.special_bomb, ..
+ GameGFX.special_twister, ..
+ GameGFX.special_nuke, ..
+ GameGFX.special_cross]
+
+ dir=[[DIR_UP,DIR_RIGHT,DIR_DOWN,DIR_LEFT], .. ' CROSS
+ [DIR_NONE,DIR_RIGHT,DIR_NONE,DIR_LEFT], .. ' LEFT_RIGHT
+ [DIR_UP,DIR_NONE,DIR_DOWN,DIR_NONE], .. ' TOP_BOTTOM
+ [DIR_NONE,DIR_UP,DIR_LEFT,DIR_NONE], .. ' TOP_LEFT
+ [DIR_NONE,DIR_NONE,DIR_RIGHT,DIR_UP], .. ' TOP_RIGHT
+ [DIR_LEFT,DIR_DOWN,DIR_NONE,DIR_NONE], .. ' BOTTOM_LEFT
+ [DIR_RIGHT,DIR_NONE,DIR_NONE,DIR_DOWN], .. ' BOTTOM_RIGHT
+ [DIR_NONE,DIR_NONE,DIR_NONE,DIR_NONE], .. ' SPECIAL_BOMB
+ [DIR_NONE,DIR_NONE,DIR_NONE,DIR_NONE], .. ' SPECIAL_TWISTER
+ [DIR_NONE,DIR_NONE,DIR_NONE,DIR_NONE], .. ' SPECIAL_NUKE
+ [DIR_NONE,DIR_NONE,DIR_NONE,DIR_NONE]] ' SPECIAL_CROSS
+
+ dx=[0,0,1,0,-1]
+ dy=[0,-1,0,1,0]
+
+ dirname=["NONE","UP","RIGHT","DOWN","LEFT"]
+ typename=["CROSS","LEFT_RIGHT","TOP_BOTTOM","TOP_LEFT","TOP_RIGHT","BOTTOM_LEFT","BOTTOM_RIGHT","SPECIAL BOMB","SPECIAL TWISTER"]
+ End Function
+
+ Method New()
+ t=Rand(0,6)
+ End Method
+
+ Function Create:TWire(t:Int[])
+ Local o:TWire=New TWire
+ o.t=t[Rand(0,t.length-1)]
+ Return o
+ End Function
+
+ Method Image:TImage()
+ Return img[t]
+ End Method
+
+ Method RotateLeft()
+ t=rotleft[t]
+ End Method
+
+ Method RotateRight()
+ t=rotright[t]
+ End Method
+
+ Method Traverse:Int(d:Int)
+ If d=DIR_NONE
+ Return DIR_NONE
+ EndIf
+
+ Return dir[t][d-1]
+ End Method
+
+ Function DirX:Int(d:Int)
+ Return dx[d]
+ End Function
+
+ Function DirY:Int(d:Int)
+ Return dy[d]
+ End Function
+End Type
+
+Type TPiece Abstract
+ Field x:Int
+ Field y:Int
+ Field ox:Int
+ Field oy:Int
+ Field map:TWire[4,4]
+ Field rot:Int
+ Field offx:Int[4]
+ Field offy:Int[4]
+ Field special:Int
+ Field special_pulse:Int
+ Field col:Int
+ Field coli:Int
+ Field frame:Int
+ Field framed:Int
+ Field framespd:Int
+ Field framei:Int
+ Field pong:Int
+
+ Function Create:TPiece(special:Int)
+ Local o:TPiece
+
+ If special
+ Select Rand(0,3)
+ Case 0
+ o=TPiece(New TPiece_SpecialBomb)
+ Case 1
+ o=TPiece(New TPiece_SpecialTwister)
+ Case 2
+ o=TPiece(New TPiece_SpecialNuke)
+ Case 3
+ o=TPiece(New TPiece_SpecialCross)
+ End Select
+ Else
+ Select Rand(0,5)
+ Case 0
+ o=TPiece(New TPiece_S_Left)
+ Case 1
+ o=TPiece(New TPiece_S_Right)
+ Case 2
+ o=TPiece(New TPiece_L_Left)
+ Case 3
+ o=TPiece(New TPiece_L_Right)
+ Case 4
+ o=TPiece(New TPiece_Square)
+ Case 5
+ o=TPiece(New TPiece_Bar)
+ End Select
+ EndIf
+
+ o.BaseInit(special)
+
+ Return o
+ End Function
+
+ Function CreateSpecific:TPiece(t:Int)
+ Local o:TPiece
+ Local s:Int=False
+
+ Select t
+ Case 0
+ o=TPiece(New TPiece_S_Left)
+ Case 1
+ o=TPiece(New TPiece_S_Right)
+ Case 2
+ o=TPiece(New TPiece_L_Left)
+ Case 3
+ o=TPiece(New TPiece_L_Right)
+ Case 4
+ o=TPiece(New TPiece_Square)
+ Case 5
+ o=TPiece(New TPiece_Bar)
+ Case 6
+ o=TPiece(New TPiece_SpecialBomb)
+ s=True
+ Case 7
+ o=TPiece(New TPiece_SpecialTwister)
+ s=True
+ Case 8
+ o=TPiece(New TPiece_SpecialNuke)
+ s=True
+ Case 9
+ o=TPiece(New TPiece_SpecialCross)
+ s=True
+ Default
+ Return Create(False)
+ End Select
+
+ o.BaseInit(s)
+
+ Return o
+ End Function
+
+ Method Init() Abstract
+
+ Method BaseInit(special:Int)
+ special_pulse=False
+ framespd=5
+ pong=False
+ Init()
+ rot=0
+ ox=offx[rot]
+ oy=offy[rot]
+ self.special=special
+ col=255
+ coli=-1
+ frame=0
+ framed=0
+ framei=1
+ End Method
+
+ Method Draw()
+ If special
+ col:+coli
+ If col=255 Or col=128
+ coli=-coli
+ EndIf
+
+ framed:+1
+ If framed=framespd
+ framed=0
+ If pong
+ frame:+framei
+ If frame=0 Or frame=3
+ framei=-framei
+ EndIf
+ Else
+ frame=(frame+1) Mod 4
+ EndIf
+ EndIf
+
+ For Local px:Int=0 Until 4
+ For Local py:Int=0 Until 4
+ If map[px,py]
+ Local gx:Int=Pit.X(x-ox+px)
+ Local gy:Int=Pit.Y(y-oy+py)
+ SetColor(255,255,255)
+ DrawImage(GameGFX.tile,gx,gy)
+ If special_pulse
+ SetColor(col,col/2,255-col)
+ EndIf
+ DrawImage(map[px,py].Image(),gx,gy,frame)
+ EndIf
+ Next
+ Next
+ Else
+ For Local px:Int=0 Until 4
+ For Local py:Int=0 Until 4
+ If map[px,py]
+ Local gx:Int=Pit.X(x-ox+px)
+ Local gy:Int=Pit.Y(y-oy+py)
+ SetColor(255,255,255)
+ DrawImage(GameGFX.tile,gx,gy)
+ SetColor(128,128,128)
+ DrawImage(map[px,py].Image(),gx,gy)
+ EndIf
+ Next
+ Next
+ EndIf
+ End Method
+
+ Method RotateLeft()
+ If special Then Return
+
+ If rot=0
+ rot=3
+ Else
+ rot:-1
+ EndIf
+
+ ox=offx[rot]
+ oy=offy[rot]
+
+ Local m:TWire[4,4]
+
+ For Local px:Int=0 Until 4
+ For Local py:Int=0 Until 4
+ If map[px,py]
+ map[px,py].RotateLeft()
+ EndIf
+ m[py,3-px]=map[px,py]
+ Next
+ Next
+
+ map=m
+ End Method
+
+ Method RotateRight()
+ If special Then Return
+
+ rot=(rot+1) Mod 4
+
+ ox=offx[rot]
+ oy=offy[rot]
+
+ Local m:TWire[4,4]
+
+ For Local px:Int=0 Until 4
+ For Local py:Int=0 Until 4
+ If map[px,py]
+ map[px,py].RotateRight()
+ EndIf
+ m[3-py,px]=map[px,py]
+ Next
+ Next
+
+ map=m
+ End Method
+
+ Method Collides:Int(gm:TGameMap)
+ For Local px:Int=0 Until 4
+ For Local py:Int=0 Until 4
+ If map[px,py]
+ Local gx:Int=x-ox+px
+ Local gy:Int=y-oy+py
+
+ If gx<0 Or gx>=Pit.WIDTH Or gy>=Pit.HEIGHT
+ Return True
+ EndIf
+
+ If gy>=0 And gm.map[gx,gy]
+ Return True
+ EndIf
+ EndIf
+ Next
+ Next
+
+ Return False
+ End Method
+
+ Method AddToMap(gm:TGameMap)
+ If special
+ gm.SetSpecial(TSpecial(Self))
+ Else
+ For Local px:Int=0 Until 4
+ For Local py:Int=0 Until 4
+ If map[px,py]
+ Local gx:Int=x-ox+px
+ Local gy:Int=y-oy+py
+
+ If gy<0
+ gm.overflow=True
+ Else
+ gm.map[gx,gy]=map[px,py]
+
+ If gy=Pit.HEIGHT-1 Or gm.map[gx,gy+1]
+ Particles.AddDust(Pit.X(gx)+16,Pit.Y(gy)+32)
+ EndIf
+ EndIf
+ EndIf
+ Next
+ Next
+
+ Sound.Click()
+
+ If Not gm.overflow
+ If Not gm.CheckWires()
+ gm.Flatten()
+ gm.CheckWires()
+ EndIf
+ EndIf
+ EndIf
+ End Method
+End Type
+
+Type TSpecial Extends TPiece Abstract
+ Method DoSpecial:Int(gm:TGameMap) Abstract
+End Type
+
+Type TPiece_S_Right Extends TPiece
+ Method Init()
+ map[1,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_RIGHT])
+ map[2,0]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.BOTTOM_LEFT,TWire.LEFT_RIGHT])
+ map[0,1]=TWire.Create([TWire.CROSS,TWire.TOP_RIGHT,TWire.BOTTOM_RIGHT,TWire.LEFT_RIGHT])
+ map[1,1]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT])
+ offx=[1,2,2,0]
+ offy=[1,1,2,2]
+ End Method
+End Type
+
+
+Type TPiece_S_Left Extends TPiece
+ Method Init()
+ map[0,0]=TWire.Create([TWire.CROSS,TWire.TOP_RIGHT,TWire.BOTTOM_RIGHT,TWire.LEFT_RIGHT])
+ map[1,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_LEFT])
+ map[1,1]=TWire.Create([TWire.CROSS,TWire.TOP_RIGHT])
+ map[2,1]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.BOTTOM_LEFT,TWire.LEFT_RIGHT])
+ offx=[1,2,2,0]
+ offy=[1,1,2,2]
+ End Method
+End Type
+
+
+Type TPiece_L_Right Extends TPiece
+ Method Init()
+ map[0,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_RIGHT])
+ map[1,0]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.BOTTOM_LEFT,TWire.LEFT_RIGHT])
+ map[0,1]=TWire.Create([TWire.CROSS,TWire.TOP_BOTTOM])
+ map[0,2]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.TOP_RIGHT,TWire.TOP_BOTTOM])
+ offx=[0,2,3,1]
+ offy=[1,0,2,3]
+ End Method
+End Type
+
+
+Type TPiece_L_Left Extends TPiece
+ Method Init()
+ map[0,0]=TWire.Create([TWire.CROSS,TWire.TOP_RIGHT,TWire.BOTTOM_RIGHT,TWire.LEFT_RIGHT])
+ map[1,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_LEFT])
+ map[1,1]=TWire.Create([TWire.CROSS,TWire.TOP_BOTTOM])
+ map[1,2]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.TOP_RIGHT,TWire.TOP_BOTTOM])
+ offx=[1,2,2,1]
+ offy=[1,1,2,2]
+ End Method
+End Type
+
+
+Type TPiece_Square Extends TPiece
+ Method Init()
+ map[0,0]=TWire.Create([TWire.CROSS])
+ map[1,0]=TWire.Create([TWire.CROSS])
+ map[0,1]=TWire.Create([TWire.CROSS])
+ map[1,1]=TWire.Create([TWire.CROSS])
+ offx=[0,2,2,0]
+ offy=[1,1,3,3]
+ End Method
+End Type
+
+
+Type TPiece_Bar Extends TPiece
+ Method Init()
+ map[1,0]=TWire.Create([TWire.CROSS,TWire.BOTTOM_LEFT,TWire.BOTTOM_RIGHT,TWire.TOP_BOTTOM])
+ map[1,1]=TWire.Create([TWire.CROSS,TWire.TOP_BOTTOM])
+ map[1,2]=TWire.Create([TWire.CROSS,TWire.TOP_BOTTOM])
+ map[1,3]=TWire.Create([TWire.CROSS,TWire.TOP_LEFT,TWire.TOP_RIGHT,TWire.TOP_BOTTOM])
+ offx=[1,1,2,1]
+ offy=[1,1,1,2]
+ End Method
+End Type
+
+Type TPiece_SpecialBomb Extends TSpecial
+ Method Init()
+ map[0,0]=TWire.Create([TWire.SPECIAL_BOMB])
+ offx=[0,0,0,0]
+ offy=[0,0,0,0]
+ End Method
+
+ Method DoSpecial:Int(gm:TGameMap)
+ Draw()
+
+ Local l:TWireList=New TWireList
+
+ If y<Pit.HEIGHT-1
+ Local t:Int=gm.map[x,y+1].t
+
+ For Local px:Int=0 Until Pit.WIDTH
+ For Local py:Int=0 Until Pit.HEIGHT
+ If gm.map[px,py] And gm.map[px,py].t=t
+ l.Add(px,py,gm.map[px,py])
+ EndIf
+ Next
+ Next
+ EndIf
+
+ If l.Count()=0
+ TextParticles.Big("WHAT A WASTE!",255,0,0)
+ Else
+ TextParticles.Big("SMART BOMB!",255,255,0)
+ gm.path.AddLast(l)
+ EndIf
+
+ ExplosionParticles.BlowUp(Pit.X(x),Pit.Y(y))
+
+ Return False
+ End Method
+End Type
+
+Type TPiece_SpecialTwister Extends TSpecial
+ Field rot:Int
+ Field rotd:Int
+
+ Method Init()
+ rot=0
+ rotd=0
+ special_pulse=True
+ map[0,0]=TWire.Create([TWire.SPECIAL_TWISTER])
+ offx=[0,0,0,0]
+ offy=[0,0,0,0]
+ End Method
+
+ Method DoSpecial:Int(gm:TGameMap)
+ Draw()
+
+ If gm.path.Count()
+ Return True
+ EndIf
+
+ If rotd=0
+ rotd=60
+ rot:+1
+ If rot=5
+ ExplosionParticles.BlowUp(Pit.X(x),Pit.Y(y))
+ Return False
+ EndIf
+ TextParticles.Big("TWIST!")
+ Else
+ rotd:-1
+ Return True
+ EndIf
+
+ For Local px:Int=0 Until Pit.WIDTH
+ For Local py:Int=0 Until Pit.HEIGHT
+ If gm.map[px,py]
+ gm.map[px,py].RotateRight()
+ Particles.AddDust(Pit.X(px)+16,Pit.Y(py)+32)
+ EndIf
+ Next
+ Next
+
+ Sound.Click()
+
+ If Not gm.CheckWires()
+ gm.Flatten()
+ gm.CheckWires()
+ EndIf
+
+ Return True
+ End Method
+End Type
+
+Type TPiece_SpecialNuke Extends TSpecial
+ Method Init()
+ special_pulse=True
+ map[0,0]=TWire.Create([TWire.SPECIAL_NUKE])
+ offx=[0,0,0,0]
+ offy=[0,0,0,0]
+ End Method
+
+ Method AddToList(gm:TGameMap, l:TWireList, t:Int)
+ For Local px:Int=0 Until Pit.WIDTH
+ For Local py:Int=0 Until Pit.HEIGHT
+ If gm.map[px,py] And gm.map[px,py].t=t
+ l.Add(px,py,gm.map[px,py])
+ EndIf
+ Next
+ Next
+ End Method
+
+ Method DoSpecial:Int(gm:TGameMap)
+ Draw()
+
+ Local l:TWireList=New TWireList
+
+ If y<Pit.HEIGHT-1 And gm.map[x,y+1]
+ AddToList(gm,l,gm.map[x,y+1].t)
+ EndIf
+
+ If x>0 And gm.map[x-1,y]
+ AddToList(gm,l,gm.map[x-1,y].t)
+ EndIf
+
+ If x<Pit.WIDTH-1 And gm.map[x+1,y]
+ AddToList(gm,l,gm.map[x+1,y].t)
+ EndIf
+
+ If l.Count()=0
+ TextParticles.Big("WHAT A WASTE!",255,0,0)
+ Else
+ TextParticles.Big("SMART NUKE!",255,255,0)
+ gm.path.AddLast(l)
+ EndIf
+
+ ExplosionParticles.BlowUp(Pit.X(x),Pit.Y(y))
+
+ Return False
+ End Method
+End Type
+
+Type TPiece_SpecialCross Extends TSpecial
+
+ Method Init()
+ special_pulse=True
+ pong=True
+ map[0,0]=TWire.Create([TWire.SPECIAL_CROSS])
+ offx=[0,0,0,0]
+ offy=[0,0,0,0]
+ End Method
+
+ Method DoSpecial:Int(gm:TGameMap)
+ Draw()
+
+ TextParticles.Big("SUPER CROSS!",255,255,0)
+
+ For Local px:Int=x+1 Until Pit.WIDTH
+ If gm.map[px,y]
+ gm.map[px,y].t=TWire.CROSS
+ Particles.AddDust(Pit.X(px)+16,Pit.Y(y)+32)
+ EndIf
+ Next
+
+ For Local px:Int=0 Until x
+ If gm.map[px,y]
+ gm.map[px,y].t=TWire.CROSS
+ Particles.AddDust(Pit.X(px)+16,Pit.Y(y)+32)
+ EndIf
+ Next
+
+ For Local py:Int=y+1 Until Pit.HEIGHT
+ If gm.map[x,py]
+ gm.map[x,py].t=TWire.CROSS
+ Particles.AddDust(Pit.X(x)+16,Pit.Y(py)+32)
+ EndIf
+ Next
+
+ If Not gm.CheckWires()
+ gm.Flatten()
+ gm.CheckWires()
+ EndIf
+
+ ExplosionParticles.BlowUp(Pit.X(x),Pit.Y(y))
+
+ Return False
+ End Method
+End Type
+
+
+Type TWireListEnt
+ Field w:TWire
+ Field x:Int
+ Field y:Int
+
+ Function Create:TWireListEnt(x:Int, y:Int, w:TWire)
+ Local o:TWireListEnt=New TWireListEnt
+ o.x=x
+ o.y=y
+ o.w=w
+ Return o
+ End Function
+End Type
+
+
+Type TWireList
+ Field list:TList
+ Field col:Int
+
+ Method New()
+ list=CreateList()
+ col=128
+ End Method
+
+ Method Add(x:Int, y:Int, w:TWire)
+ list.AddLast(TWireListEnt.Create(x,y,w))
+ End Method
+
+ Method Draw:Int()
+ col=Min(255,col+5)
+ SetColor(col,col,col)
+ For Local e:TWireListEnt=EachIn list
+ DrawImage(e.w.Image(),Pit.X(e.x),Pit.Y(e.y))
+ Next
+
+ If col<255
+ Return True
+ Else
+ For Local e:TWireListEnt=EachIn list
+ Particles.AddImage(e.w.Image(),Pit.X(e.x),Pit.Y(e.y))
+ Next
+ Return False
+ EndIf
+ End Method
+
+ Method Count:Int()
+ Return list.Count()
+ End Method
+End Type
+
+
+Type TGameMap
+ Field map:TWire[Pit.WIDTH,Pit.HEIGHT]
+ Field trode_col:Int
+ Field trode_coli:Int
+ Field overflow:Int
+ Field cx:Int
+ Field cy:Int
+ Field path:TList
+ Field special:TSpecial
+
+ Method New()
+ trode_col=0
+ trode_coli=1
+ overflow=False
+ path=CreateList()
+ special=Null
+ End Method
+
+ Method BlockInteract:Int()
+ Return overflow Or path.Count() Or special
+ End Method
+
+ Method FindPath:Int(l:TWireList, x:Int, y:Int, dir:Int)
+ If y<0
+ Return False
+ EndIf
+
+ If x<0 Or x=Pit.WIDTH Or y=Pit.HEIGHT
+ Return True
+ EndIf
+
+ Local w:TWire=map[x,y]
+
+ If Not w
+ Return False
+ EndIf
+
+ dir=w.Traverse(dir)
+
+ If dir=TWire.DIR_NONE
+ Return False
+ EndIf
+
+ l.Add(x,y,w)
+
+ Return FindPath(l,x+TWire.DirX(dir),y+TWire.DirY(dir),dir)
+ End Method
+
+ Method FindLoop:Int(l:TWireList, ox:Int, oy:Int, x:Int, y:Int, dir:Int)
+ If y<0 Or x<0 Or x=Pit.WIDTH Or y=Pit.HEIGHT
+ Return False
+ EndIf
+
+ Local w:TWire=map[x,y]
+
+ If Not w
+ Return False
+ EndIf
+
+ dir=w.Traverse(dir)
+
+ If dir=TWire.DIR_NONE
+ Return False
+ EndIf
+
+ l.Add(x,y,w)
+
+ x:+TWire.DirX(dir)
+ y:+TWire.DirY(dir)
+
+ If x=ox And y=oy And dir=TWire.DIR_RIGHT
+ Return True
+ EndIf
+
+ Return FindLoop(l,ox,oy,x,y,dir)
+ End Method
+
+ Method CheckWires:Int()
+ Local loop:Int=False
+ Local wire:Int=False
+
+ For Local y:Int=0 Until Pit.HEIGHT
+ Local l:TWireList=New TWireList
+
+ If FindPath(l,0,y,TWire.DIR_RIGHT)
+ path.AddLast(l)
+ EndIf
+
+ l=New TWireList
+
+ If FindPath(l,Pit.WIDTH-1,y,TWire.DIR_LEFT)
+ path.AddLast(l)
+ wire=True
+ EndIf
+ Next
+
+ For Local x:Int=0 Until Pit.WIDTH
+ Local l:TWireList=New TWireList
+
+ If FindPath(l,x,Pit.HEIGHT-1,TWire.DIR_UP)
+ path.AddLast(l)
+ wire=True
+ EndIf
+ Next
+
+ For Local x:Int=0 Until Pit.WIDTH
+ For Local y:Int=0 Until Pit.HEIGHT
+ If map[x,y]
+ Local l:TWireList=New TWireList
+ Select map[x,y].t
+ Case TWire.CROSS, TWire.LEFT_RIGHT, TWire.TOP_LEFT, TWire.BOTTOM_LEFT
+ If FindLoop(l,x,y,x,y,TWire.DIR_RIGHT)
+ path.AddLast(l)
+ loop=True
+ EndIf
+ End Select
+ EndIf
+ Next
+ Next
+
+ If loop And wire
+ TextParticles.Big("LOOP AND WIRE",255,0,255)
+ ElseIf loop
+ TextParticles.Big("LOOP",255,0,255)
+ ElseIf wire
+ TextParticles.Big("WIRE",255,0,255)
+ EndIf
+
+ Return loop Or wire
+ End Method
+
+ Method SetSpecial(s:TSpecial)
+ special=s
+ End Method
+
+ Method DropColumn(x:Int, y:Int)
+ While y>0
+ map[x,y]=map[x,y-1]
+ y:-1
+ Wend
+ map[x,0]=Null
+ End Method
+
+ Method AnyAbove:Int(x:Int, y:Int)
+ While y>=0
+ If map[x,y]
+ Return True
+ EndIf
+ y:-1
+ Wend
+
+ Return False
+ End Method
+
+ Method Flatten()
+ For Local x:Int=0 Until Pit.WIDTH
+ Local y:Int=Pit.HEIGHT-1
+ Local drop:Int=False
+
+ While y>0 And AnyAbove(x,y)
+ If map[x,y]
+ If drop
+ Particles.AddDust(Pit.X(x)+16,Pit.Y(y)+32)
+ EndIf
+ drop=False
+ y:-1
+ Else
+ DropColumn(x,y)
+ drop=True
+ EndIf
+ Wend
+ Next
+ End Method
+
+ Method Draw:Int()
+ Local score:Int=0
+
+ SetColor(255,255,255)
+ DrawImage(GameGFX.pit_bottomleft,Pit.X(-1),Pit.Y(Pit.HEIGHT))
+ DrawImage(GameGFX.pit_bottomright,Pit.X(Pit.WIDTH),Pit.Y(Pit.HEIGHT))
+
+ DrawImage(GameGFX.pit_top,Pit.X(-1),Pit.Y(0))
+ DrawImage(GameGFX.pit_top,Pit.X(Pit.WIDTH),Pit.Y(0))
+ SetColor(trode_col,trode_col,0)
+ DrawImage(GameGFX.trode_left,Pit.X(-1),Pit.Y(0))
+ DrawImage(GameGFX.trode_right,Pit.X(Pit.WIDTH),Pit.Y(0))
+
+ For Local f:Int=0 Until Pit.WIDTH
+ SetColor(255,255,255)
+ DrawImage(GameGFX.pit_bottom,Pit.X(f),Pit.Y(Pit.HEIGHT))
+ SetColor(trode_col,trode_col,0)
+ DrawImage(GameGFX.trode_bottom,Pit.X(f),Pit.Y(Pit.HEIGHT))
+ Next
+
+ For Local f:Int=1 Until Pit.HEIGHT
+ SetColor(255,255,255)
+ DrawImage(GameGFX.pit_side,Pit.X(-1),Pit.Y(f))
+ DrawImage(GameGFX.pit_side,Pit.X(Pit.WIDTH),Pit.Y(f))
+ SetColor(trode_col,trode_col,0)
+ DrawImage(GameGFX.trode_left,Pit.X(-1),Pit.Y(f))
+ DrawImage(GameGFX.trode_right,Pit.X(Pit.WIDTH),Pit.Y(f))
+ Next
+
+ For Local x:Int=0 Until Pit.WIDTH
+ For Local y:Int=0 Until Pit.HEIGHT
+ If map[x,y]
+ SetColor(255,255,255)
+ DrawImage(GameGFX.tile,Pit.X(x),Pit.Y(y))
+ SetColor(trode_col,trode_col,0)
+ DrawImage(map[x,y].Image(),Pit.X(x),Pit.Y(y))
+ EndIf
+ Next
+ Next
+
+ If special
+ If Not special.DoSpecial(Self)
+ special=Null
+ EndIf
+ EndIf
+
+ Local l:TEasyLink=TEasyLink.Create(path)
+ Local check:Int=False
+
+ While l.Value()
+ Local b:TWireList=TWireList(l.Value())
+
+ If b.Draw()
+ l.MoveNext()
+ Else
+ If Not overflow
+ score:+b.list.Count()
+ For Local e:TWireListEnt=EachIn b.list
+ map[e.x,e.y]=Null
+ Next
+ EndIf
+ l.Remove()
+ check=True
+ EndIf
+ Wend
+
+ If check
+ Sound.Path()
+ Flatten()
+ CheckWires()
+ EndIf
+
+ trode_col:+trode_coli
+
+ If (trode_col=255 And trode_coli>0) Or (trode_col=200 And trode_coli<0)
+ trode_coli=-trode_coli
+ EndIf
+
+ Return score
+ End Method
+End Type
diff --git a/hardwire.bmx b/hardwire.bmx
index f1f8997..577552f 100644
--- a/hardwire.bmx
+++ b/hardwire.bmx
@@ -1,374 +1,396 @@
-' Hardwire
-'
-' Copyright 2005 Ian Cowburn
-'
-' $Id$
-'
-Strict
-Framework brl.basic
-Import brl.max2d
-Import brl.glmax2d
-?Win32
-Import brl.d3d7max2d
-?
-
-Import noddybox.bitmapfont
-Import noddybox.keysyms
-Import noddybox.gfxmenu
-
-Import "types.bmx"
-Import "gametypes.bmx"
-Import "game.bmx"
-Import "particle.bmx"
-Import "help.bmx"
-
-' ===================================
-' Initialise
-' ===================================
-'
-SeedRnd(MilliSecs())
-
-?Win32
-If Switch("--directx")
- SetGraphicsDriver D3D7Max2DDriver()
-Else
- SetGraphicsDriver GLMax2DDriver()
-EndIf
-?
-
-Graphics 800,600,32,HERTZ
-HideMouse
-
-SetBlend(ALPHABLEND)
-SetAlpha(1.0)
-
-
-' ===================================
-' Globals
-' ===================================
-'
-GameGFX.Init() ' MUST be first
-
-Lookup.Init()
-GameConfig.Load()
-TWire.Init()
-Particles.Init()
-TextParticles.Init()
-ExplosionParticles.Init()
-Sound.Init()
-
-Global bdrop:TMenuBdrop=New TMenuBdrop
-Global quit:Int=False
-Global last_score:Int=0
-
-
-' ===================================
-' Main
-' ===================================
-'
-Menu()
-
-While Not quit
- Local game:TGame=New TGame
- game.SetInitLevel(GameConfig.start_level)
-
- While game.Play()
- Wend
-
- TFadeScreen.DoFadeOut()
-
- GameConfig.Save()
- last_score=game.score
-
- Menu()
-Wend
-
-EndGraphics
-End
-
-
-' ===================================
-' Argument Routines
-' ===================================
-'
-Function Switch:Int(s:String)
- For Local a:String=EachIn AppArgs
- If a=s
- Return True
- EndIf
- Next
-
- Return False
-End Function
-
-
-' ===================================
-' Menu Routines
-' ===================================
-'
-Function Menu()
- Const MENU_PLAY:Int=1
- Const MENU_QUIT:Int=2
- Const MENU_RULES:Int=3
- Const MENU_KEYS:Int=4
- Const MENU_LEFT:Int=5
- Const MENU_RIGHT:Int=6
-
- Local fade:TFadeScreen=TFadeScreen.FadeIn()
- Local done:Int=False
- 'Local menu:TGfxMenu=TGfxMenu.Create(255,0,0,255,255,255,25,bdrop,1)
- Local menu:TGfxMenu=TGfxMenu.Create(255,0,0,255,255,255,15,bdrop,1)
- Local sel:Int
-
- Local defkey:Int=0
-
- Local x1:Int=GraphicsWidth()/3-ImageWidth(GameGFX.play_button)/2
- Local x2:Int=GraphicsWidth()/3*2-ImageWidth(GameGFX.play_button)/2
-
- menu.Add(x1,150,GameGFX.play_button,MENU_PLAY)
- menu.Add(x2,150,GameGFX.rules_button,MENU_RULES)
- menu.Add(x1,250,GameGFX.keys_button,MENU_KEYS)
- menu.Add(x2,250,GameGFX.quit_button,MENU_QUIT)
- menu.Add(x1,350,GameGFX.left_button,MENU_LEFT)
- menu.Add(x2+ImageWidth(GameGFX.play_button)-ImageWidth(GameGFX.right_button),350,GameGFX.right_button,MENU_RIGHT)
-
- Local tx1:Int=(GraphicsWidth()-GameGFX.large.TextWidth("START LEVEL 1"))/2
- Local tx2:Int=tx1+GameGFX.large.TextWidth("START LEVEL ")
-
- Local col:Int=128
- Local coli=1
-
- TextParticles.Clear()
-
- While Not done
- Cls
- SetColor(col,col,255)
- DrawImage(GameGFX.title,0,0)
- SetColor(255,255,255)
-
-?debug
- If KeyHit(KEY_D)
- DebugCode()
- EndIf
-?
-
- col:+coli
-
- If col=128 Or col=255
- coli=-coli
- EndIf
-
- sel=menu.Render(defkey>0)
-
- If defkey>0
-
- If defkey=7
- GameGFX.large.Centre("PRESS A KEY TO GO BACK TO THE MENU",150)
- Else
- GameGFX.large.Centre("DEFINE KEYS",150)
- GameGFX.large.Centre("PRESS ESCAPE TO CANCEL",380)
- EndIf
-
- Local c1:Int=128+128*(defkey=1)
- Local c2:Int=128+128*(defkey=2)
- Local c3:Int=128+128*(defkey=3)
- Local c4:Int=128+128*(defkey=4)
- Local c5:Int=128+128*(defkey=5)
- Local c6:Int=128+128*(defkey=6)
-
- GameGFX.large.Draw("Left",250,180,c1,c1,0)
- GameGFX.large.Draw("Right",250,210,c2,c2,0)
- GameGFX.large.Draw("Rotate Right",250,240,c3,c3,0)
- GameGFX.large.Draw("Rotate Left",250,270,c4,c4,0)
- GameGFX.large.Draw("Drop",250,300,c5,c5,0)
- GameGFX.large.Draw("Pause",250,330,c6,c6,0)
- GameGFX.large.Draw(KeySym(GameConfig.kleft),500,180,c1,c1,0)
- GameGFX.large.Draw(KeySym(GameConfig.kright),500,210,c2,c2,0)
- GameGFX.large.Draw(KeySym(GameConfig.krotright),500,240,c3,c3,0)
- GameGFX.large.Draw(KeySym(GameConfig.krotleft),500,270,c4,c4,0)
- GameGFX.large.Draw(KeySym(GameConfig.kdrop),500,300,c5,c5,0)
- GameGFX.large.Draw(KeySym(GameConfig.kpause),500,330,c6,c6,0)
-
-
- Local k:Int=-1
-
- For Local f:Int=0 To 255
- If KeyHit(f)
- k=f
- Continue
- EndIf
- Next
-
- If k=KEY_ESCAPE
- GameConfig.Load()
- defkey=0
- FlushKeys()
- ElseIf k<>-1
- Select defkey
- Case 1
- GameConfig.kleft=k
- Case 2
- GameConfig.kright=k
- Case 3
- GameConfig.krotright=k
- Case 4
- GameConfig.krotleft=k
- Case 5
- GameConfig.kdrop=k
- Case 6
- GameConfig.kpause=k
- End Select
-
- defkey:+1
-
- If defkey=7
- GameConfig.Save()
- defkey=0
- FlushKeys()
- EndIf
- EndIf
- Else
- If KeyHit(KEY_ESCAPE)
- done=True
- quit=True
- EndIf
-
- TextParticles.Draw()
-
- GameGFX.large.Draw("START LEVEL ",tx1,356)
- GameGFX.large.Draw(GameConfig.start_level,tx2,356,255,255,0)
-
- GameGFX.large.CentreOn("LAST SCORE",200,500)
- GameGFX.large.CentreOn("HIGH SCORE",600,500)
- GameGFX.large.CentreOn(last_score,200,520,255,col,0)
- GameGFX.large.CentreOn(GameConfig.hiscore,600,520,255,col,0)
- EndIf
-
- Select sel
- Case MENU_PLAY
- done=True
- FlushKeys()
- Case MENU_RULES
- FlushKeys()
- Local help:THelp=New THelp
- TFadeScreen.DoFadeOut()
- help.Show()
- TFadeScreen.DoFadeOut()
- fade=TFadeScreen.FadeIn()
- Case MENU_KEYS
- FlushKeys()
- defkey=1
- Case MENU_QUIT
- done=True
- quit=True
- Case MENU_LEFT
- GameConfig.start_level=Max(1,GameConfig.start_level-1)
- GameConfig.Save()
- Case MENU_RIGHT
- GameConfig.start_level=Min(10,GameConfig.start_level+1)
- GameConfig.Save()
- End Select
-
- Rem
- SetScale(2,2)
- GameGFX.font.Centre("HARDWIRE",0,255,255,0)
-
- SetScale(1,1)
- GameGFX.font.Centre("Copyright (c) 2005 Ian C",20,255,0,0)
- EndRem
-
- SetColor(255,255,255)
- DrawImage(GameGFX.pointer,MouseX(),MouseY())
-
- If fade
- If fade.Fade()
- fade.Draw()
- Else
- fade=Null
- EndIf
- EndIf
-
- Flip
- Wend
-
- TextParticles.Clear()
-
- TFadeScreen.DoFadeOut()
-End Function
-
-
-' ===================================
-' Debug
-' ===================================
-'
-?debug
-Function DebugCreate:TPiece(t:Int)
- Local p:TPiece=TPiece.CreateSpecific(t)
- p.x=8
- p.y=-3
- Return p
-End Function
-
-Function DebugCode()
- Local done:Int=False
- Local gm:TGameMap=New TGameMap
- Local t:Int=0
- Local p:TPiece=DebugCreate(t)
-
- While Not done
- Cls
-
- If gm.overflow
- GameGFX.large.Centre("OVERFLOW!",0)
- EndIf
-
- gm.Draw()
-
- p.Draw()
-
- Local k:Int=-1
-
- For Local f:Int=0 To 255
- If KeyHit(f)
- k=f
- Continue
- EndIf
- Next
-
- Select k
- Case KEY_ESCAPE
- done=True
-
- Case KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9
- t=k-KEY_0
- p=DebugCreate(t)
-
- Case KEY_LEFT
- p.x:-1
-
- Case KEY_RIGHT
- p.x:+1
-
- Case KEY_DOWN
- p.y:+1
-
- Case KEY_UP
- p.y:-1
-
- Case KEY_SPACE
- p.RotateRight()
-
- Case KEY_ENTER
- p.AddToMap(gm)
- p=DebugCreate(t)
- End Select
-
- Particles.Draw()
- ExplosionParticles.Draw()
- TextParticles.Draw()
- Sound.Process()
- Flip
- Wend
-End Function
-?
-
+' Hardwire
+'
+' Copyright (C) 2005 Ian Cowburn (ianc@noddybox.co.uk)
+'
+' This program is free software; you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation; either version 2 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY; without even the implied warranty of
+' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+' GNU General Public License for more details.
+'
+' You should have received a copy of the GNU General Public License
+' along with this program; if not, write to the Free Software
+' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+'
+' -------------------------------------------------------------------------
+'
+' $Id$
+'
+Strict
+Framework brl.basic
+Import brl.max2d
+Import brl.glmax2d
+?Win32
+Import brl.d3d7max2d
+?
+
+Import noddybox.bitmapfont
+Import noddybox.keysyms
+Import noddybox.gfxmenu
+
+Import "types.bmx"
+Import "gametypes.bmx"
+Import "game.bmx"
+Import "particle.bmx"
+Import "help.bmx"
+
+' ===================================
+' Initialise
+' ===================================
+'
+SeedRnd(MilliSecs())
+
+?Win32
+If Switch("--directx")
+ SetGraphicsDriver D3D7Max2DDriver()
+Else
+ SetGraphicsDriver GLMax2DDriver()
+EndIf
+?
+
+Graphics 800,600,32,HERTZ
+HideMouse
+
+SetBlend(ALPHABLEND)
+SetAlpha(1.0)
+
+
+' ===================================
+' Globals
+' ===================================
+'
+GameGFX.Init() ' MUST be first
+
+Lookup.Init()
+GameConfig.Load()
+TWire.Init()
+Particles.Init()
+TextParticles.Init()
+ExplosionParticles.Init()
+Sound.Init()
+
+Global bdrop:TMenuBdrop=New TMenuBdrop
+Global quit:Int=False
+Global last_score:Int=0
+
+
+' ===================================
+' Main
+' ===================================
+'
+Menu()
+
+While Not quit
+ Local game:TGame=New TGame
+ game.SetInitLevel(GameConfig.start_level)
+
+ While game.Play()
+ Wend
+
+ TFadeScreen.DoFadeOut()
+
+ GameConfig.Save()
+ last_score=game.score
+
+ Menu()
+Wend
+
+EndGraphics
+End
+
+
+' ===================================
+' Argument Routines
+' ===================================
+'
+Function Switch:Int(s:String)
+ For Local a:String=EachIn AppArgs
+ If a=s
+ Return True
+ EndIf
+ Next
+
+ Return False
+End Function
+
+
+' ===================================
+' Menu Routines
+' ===================================
+'
+Function Menu()
+ Const MENU_PLAY:Int=1
+ Const MENU_QUIT:Int=2
+ Const MENU_RULES:Int=3
+ Const MENU_KEYS:Int=4
+ Const MENU_LEFT:Int=5
+ Const MENU_RIGHT:Int=6
+
+ Local fade:TFadeScreen=TFadeScreen.FadeIn()
+ Local done:Int=False
+ 'Local menu:TGfxMenu=TGfxMenu.Create(255,0,0,255,255,255,25,bdrop,1)
+ Local menu:TGfxMenu=TGfxMenu.Create(255,0,0,255,255,255,15,bdrop,1)
+ Local sel:Int
+
+ Local defkey:Int=0
+
+ Local x1:Int=GraphicsWidth()/3-ImageWidth(GameGFX.play_button)/2
+ Local x2:Int=GraphicsWidth()/3*2-ImageWidth(GameGFX.play_button)/2
+
+ menu.Add(x1,150,GameGFX.play_button,MENU_PLAY)
+ menu.Add(x2,150,GameGFX.rules_button,MENU_RULES)
+ menu.Add(x1,250,GameGFX.keys_button,MENU_KEYS)
+ menu.Add(x2,250,GameGFX.quit_button,MENU_QUIT)
+ menu.Add(x1,350,GameGFX.left_button,MENU_LEFT)
+ menu.Add(x2+ImageWidth(GameGFX.play_button)-ImageWidth(GameGFX.right_button),350,GameGFX.right_button,MENU_RIGHT)
+
+ Local tx1:Int=(GraphicsWidth()-GameGFX.large.TextWidth("START LEVEL 1"))/2
+ Local tx2:Int=tx1+GameGFX.large.TextWidth("START LEVEL ")
+
+ Local col:Int=128
+ Local coli=1
+
+ TextParticles.Clear()
+
+ While Not done
+ Cls
+
+ SetColor(col,col,255)
+ DrawImage(GameGFX.title,0,0)
+ SetColor(255,255,255)
+
+?debug
+ If KeyHit(KEY_D)
+ DebugCode()
+ EndIf
+?
+
+ col:+coli
+
+ If col=128 Or col=255
+ coli=-coli
+ EndIf
+
+ sel=menu.Render(defkey>0)
+
+ If defkey>0
+
+ If defkey=7
+ GameGFX.large.Centre("PRESS A KEY TO GO BACK TO THE MENU",150)
+ Else
+ GameGFX.large.Centre("DEFINE KEYS",150)
+ GameGFX.large.Centre("PRESS ESCAPE TO CANCEL",380)
+ EndIf
+
+ Local c1:Int=128+128*(defkey=1)
+ Local c2:Int=128+128*(defkey=2)
+ Local c3:Int=128+128*(defkey=3)
+ Local c4:Int=128+128*(defkey=4)
+ Local c5:Int=128+128*(defkey=5)
+ Local c6:Int=128+128*(defkey=6)
+
+ GameGFX.large.Draw("Left",250,180,c1,c1,0)
+ GameGFX.large.Draw("Right",250,210,c2,c2,0)
+ GameGFX.large.Draw("Rotate Right",250,240,c3,c3,0)
+ GameGFX.large.Draw("Rotate Left",250,270,c4,c4,0)
+ GameGFX.large.Draw("Drop",250,300,c5,c5,0)
+ GameGFX.large.Draw("Pause",250,330,c6,c6,0)
+ GameGFX.large.Draw(KeySym(GameConfig.kleft),500,180,c1,c1,0)
+ GameGFX.large.Draw(KeySym(GameConfig.kright),500,210,c2,c2,0)
+ GameGFX.large.Draw(KeySym(GameConfig.krotright),500,240,c3,c3,0)
+ GameGFX.large.Draw(KeySym(GameConfig.krotleft),500,270,c4,c4,0)
+ GameGFX.large.Draw(KeySym(GameConfig.kdrop),500,300,c5,c5,0)
+ GameGFX.large.Draw(KeySym(GameConfig.kpause),500,330,c6,c6,0)
+
+
+ Local k:Int=-1
+
+ For Local f:Int=0 To 255
+ If KeyHit(f)
+ k=f
+ Continue
+ EndIf
+ Next
+
+ If k=KEY_ESCAPE
+ GameConfig.Load()
+ defkey=0
+ FlushKeys()
+ ElseIf k<>-1
+ Select defkey
+ Case 1
+ GameConfig.kleft=k
+ Case 2
+ GameConfig.kright=k
+ Case 3
+ GameConfig.krotright=k
+ Case 4
+ GameConfig.krotleft=k
+ Case 5
+ GameConfig.kdrop=k
+ Case 6
+ GameConfig.kpause=k
+ End Select
+
+ defkey:+1
+
+ If defkey=7
+ GameConfig.Save()
+ defkey=0
+ FlushKeys()
+ EndIf
+ EndIf
+ Else
+ If KeyHit(KEY_ESCAPE)
+ done=True
+ quit=True
+ EndIf
+
+ TextParticles.Draw()
+
+ GameGFX.large.Draw("START LEVEL ",tx1,356)
+ GameGFX.large.Draw(GameConfig.start_level,tx2,356,255,255,0)
+
+ GameGFX.large.CentreOn("LAST SCORE",200,500)
+ GameGFX.large.CentreOn("HIGH SCORE",600,500)
+
+ GameGFX.large.CentreOn(Number.Format(last_score),200,520,255,col,0)
+ GameGFX.large.CentreOn(Number.Format(GameConfig.hiscore),600,520,255,col,0)
+ EndIf
+
+ Select sel
+ Case MENU_PLAY
+ done=True
+ FlushKeys()
+ Case MENU_RULES
+ FlushKeys()
+ Local help:THelp=New THelp
+ TFadeScreen.DoFadeOut()
+ help.Show()
+ TFadeScreen.DoFadeOut()
+ fade=TFadeScreen.FadeIn()
+ Case MENU_KEYS
+ FlushKeys()
+ defkey=1
+ Case MENU_QUIT
+ done=True
+ quit=True
+ Case MENU_LEFT
+ GameConfig.start_level=Max(1,GameConfig.start_level-1)
+ GameConfig.Save()
+ Case MENU_RIGHT
+ GameConfig.start_level=Min(10,GameConfig.start_level+1)
+ GameConfig.Save()
+ End Select
+
+ Rem
+ SetScale(2,2)
+ GameGFX.font.Centre("HARDWIRE",0,255,255,0)
+
+ SetScale(1,1)
+ GameGFX.font.Centre("Copyright (c) 2005 Ian C",20,255,0,0)
+ EndRem
+
+ SetColor(255,255,255)
+ DrawImage(GameGFX.pointer,MouseX(),MouseY())
+
+ If fade
+ If fade.Fade()
+ fade.Draw()
+ Else
+ fade=Null
+ EndIf
+ EndIf
+
+ Flip
+ Wend
+
+ TextParticles.Clear()
+
+ TFadeScreen.DoFadeOut()
+End Function
+
+
+' ===================================
+' Debug
+' ===================================
+'
+?debug
+Function DebugCreate:TPiece(t:Int)
+ Local p:TPiece=TPiece.CreateSpecific(t)
+ p.x=8
+ p.y=-3
+ Return p
+End Function
+
+Function DebugCode()
+ Local done:Int=False
+ Local gm:TGameMap=New TGameMap
+ Local t:Int=0
+ Local p:TPiece=DebugCreate(t)
+
+ While Not done
+ Cls
+
+ If gm.overflow
+ GameGFX.large.Centre("OVERFLOW!",0)
+ EndIf
+
+ gm.Draw()
+
+ GameGFX.small.CentreOn(Number.Format(MilliSecs()),200,590)
+ GameGFX.small.CentreOn(Number.Format(MilliSecs()*2),600,590)
+ GameGFX.small.Centre(Number.Format(MilliSecs()*100),590)
+
+ p.Draw()
+
+ Local k:Int=-1
+
+ For Local f:Int=0 To 255
+ If KeyHit(f)
+ k=f
+ Continue
+ EndIf
+ Next
+
+ Select k
+ Case KEY_ESCAPE
+ done=True
+
+ Case KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9
+ t=k-KEY_0
+ p=DebugCreate(t)
+
+ Case KEY_LEFT
+ p.x:-1
+
+ Case KEY_RIGHT
+ p.x:+1
+
+ Case KEY_DOWN
+ p.y:+1
+
+ Case KEY_UP
+ p.y:-1
+
+ Case KEY_SPACE
+ p.RotateRight()
+
+ Case KEY_ENTER
+ p.AddToMap(gm)
+ p=DebugCreate(t)
+ End Select
+
+ Particles.Draw()
+ ExplosionParticles.Draw()
+ TextParticles.Draw()
+ Sound.Process()
+ Flip
+ Wend
+End Function
+?
+
diff --git a/help.bmx b/help.bmx
index ccf3aaa..479bc6a 100644
--- a/help.bmx
+++ b/help.bmx
@@ -1,289 +1,309 @@
-' Hardwire
-'
-' Copyright 2005 Ian Cowburn
-'
-' $Id$
-'
-Strict
-Import brl.pngloader
-
-Import noddybox.bitmapfont
-Import noddybox.gfxmenu
-
-Import "types.bmx"
-
-
-' Included binaries
-'
-Incbin "HELP/help.txt"
-Incbin "HELP/pit.png"
-Incbin "HELP/piece.png"
-Incbin "HELP/wire1.png"
-Incbin "HELP/wire2.png"
-Incbin "HELP/wire3.png"
-Incbin "HELP/loop1.png"
-Incbin "HELP/bomb.png"
-Incbin "HELP/twister.png"
-Incbin "HELP/nuke.png"
-Incbin "HELP/cross.png"
-
-Type THelp
- Const TOP:Int=50
- Const BOTTOM:Int=550
- Field list:TList
- Field pos:Int
- Field item:TLink
- Field del:Int
-
- Method New()
- Local str:TStream=ReadStream("incbin::HELP/help.txt")
-
- Assert str,"Unable to open help file"
-
- list=CreateList()
-
- While Not str.Eof()
- Local line:String=str.ReadLine()
-
- If line.length
- Select line[0]
- Case Asc("#")
- list.AddLast(THelpImage.Create(line[1..]))
- Case Asc("$")
- list.AddLast(THelpAnimImage.Create(line[1..],False))
- Case Asc("~~")
- list.AddLast(THelpAnimImage.Create(line[1..],True))
- Default
- list.AddLast(THelpText.Create(line))
- End Select
- Else
- list.AddLast(THelpBlankLine.Create(line))
- EndIf
- Wend
-
- item=list.LastLink()
- pos=TOP-Current().Height()
- End Method
-
- Method Draw()
- Local y:Int=pos
- Local i:TLink=item
-
- While y<BOTTOM
- Local h:THelpItem=THelpItem(i.Value())
- h.Draw(y)
- y:+h.Height()
- i=i.NextLink()
- If Not i
- i=list.FirstLink()
- EndIf
- Wend
-
- SetColor(0,0,0)
- DrawRect(0,0,GraphicsWidth(),TOP)
- DrawRect(0,BOTTOM,GraphicsWidth(),GraphicsHeight()-BOTTOM)
- For Local f:Int=0 To 8
- SetAlpha(1.0-f*0.125)
- DrawLine(0,TOP+f,GraphicsWidth(),TOP+f)
- DrawLine(0,BOTTOM-f,GraphicsWidth(),BOTTOM-f)
- Next
- SetAlpha(1)
- SetColor(128,128,128)
- DrawLine(0,TOP-1,GraphicsWidth(),TOP-1)
- DrawLine(0,TOP+1,GraphicsWidth(),TOP+1)
- DrawLine(0,BOTTOM-1,GraphicsWidth(),BOTTOM-1)
- DrawLine(0,BOTTOM+1,GraphicsWidth(),BOTTOM+1)
- SetColor(255,255,255)
- DrawLine(0,TOP,GraphicsWidth(),TOP)
- DrawLine(0,BOTTOM,GraphicsWidth(),BOTTOM)
-
- GameGFX.large.Centre("HOW TO PLAY HARDWIRE",0,255,255,0)
- GameGFX.large.Centre("USE UP/DOWN CURSORS TO SCROLL",BOTTOM+10,255,255,0)
- GameGFX.large.Centre("ESCAPE TO EXIT",BOTTOM+30,255,255,0)
- End Method
-
- Method Current:THelpItem()
- Return THelpItem(item.Value())
- End Method
-
- Method Show()
- Local done:Int=False
- Local fade:TFadeScreen=TFadeScreen.FadeIn()
-
- While Not done
- Cls
-
- Draw()
-
- If KeyDown(KEY_DOWN)
- del=Min(del+1,200)
- pos:-del/4+1
- While pos<TOP-Current().Height()
- pos:+Current().Height()
- item=item.NextLink()
- If Not item
- item=list.FirstLink()
- EndIf
- Wend
- ElseIf KeyDown(KEY_UP)
- del=Min(del+1,200)
- pos:+del/4+1
- While pos>TOP
- item=item.PrevLink()
- If Not item
- item=list.LastLink()
- EndIf
- pos:-Current().Height()
- Wend
- ElseIf KeyHit(KEY_ESCAPE)
- FlushKeys()
- done=True
- Else
- del=0
- EndIf
-
- If fade
- If fade.Fade()
- fade.Draw()
- Else
- fade=Null
- EndIf
- EndIf
-
- Flip
- Wend
-
- SetColor(255,255,255)
- End Method
-End Type
-
-Type THelpItem Abstract
- Method Height:Int() Abstract
- Method Draw(y:Int) Abstract
-End Type
-
-Type THelpText Extends THelpItem
- Field txt:String
- Field r:Int
- Field g:Int
- Field b:Int
- Field sc:Int
-
- Function Create:THelpItem(txt:String)
- Local o:THelpText=New THelpText
-
- Select txt[0]
- Case Asc("@")
- o.sc=2
- o.r=255
- o.g=255
- o.b=0
- o.txt=txt[1..]
- Case Asc("!")
- o.sc=1
- o.r=255
- o.g=255
- o.b=0
- o.txt=txt[1..]
- Default
- o.sc=1
- o.r=255
- o.g=255
- o.b=255
- o.txt=txt
- End Select
-
- Return THelpItem(o)
- End Function
-
- Method Height:Int()
- Return GameGFX.large.MaxHeight()*sc
- End Method
-
- Method Draw(y:Int)
- SetScale(sc,sc)
- GameGFX.large.Centre(txt,y,r,g,b)
- SetScale(1,1)
- End Method
-End Type
-
-
-Type THelpBlankLine Extends THelpItem
- Function Create:THelpItem(txt:String)
- Local o:THelpBlankLine=New THelpBlankLine
- Return THelpItem(o)
- End Function
-
- Method Height:Int()
- Return GameGFX.large.MaxHeight()
- End Method
-
- Method Draw(y:Int)
- End Method
-End Type
-
-
-Type THelpImage Extends THelpItem
- Field img:TImage
- Field x:Int
-
- Function Create:THelpItem(url:String)
- Local o:THelpImage=New THelpImage
- o.img=LoadImage(url)
- Assert o.img,"Failed to load help image " + url
- o.x=(GraphicsWidth()-ImageWidth(o.img))/2
- Return THelpItem(o)
- End Function
-
- Method Height:Int()
- Return ImageHeight(img)
- End Method
-
- Method Draw(y:Int)
- SetColor(255,255,255)
- DrawImage(img,x,y)
- End Method
-End Type
-
-
-Type THelpAnimImage Extends THelpItem
- Field img:TImage
- Field x:Int
- Field frame:Int
- Field framei:Int
- Field framed:Int
- Field pong:Int
-
- Function Create:THelpItem(url:String,pong:Int)
- Local o:THelpAnimImage=New THelpAnimImage
- o.img=LoadAnimImage(url,32,32,0,4)
- Assert o.img,"Failed to load help anim image " + url
- o.x=(GraphicsWidth()-32)/2
- o.frame=0
- o.framed=5
- o.framei=1
- o.pong=pong
- Return THelpItem(o)
- End Function
-
- Method Height:Int()
- Return ImageHeight(img)
- End Method
-
- Method Draw(y:Int)
- SetColor(255,255,255)
- DrawImage(img,x,y,frame)
- framed:-1
- If framed=0
- framed=5
- If pong
- frame:+framei
- If frame=0 Or frame=3
- framei=-framei
- EndIf
- Else
- frame=(frame+1) Mod 4
- EndIf
- EndIf
- End Method
-End Type \ No newline at end of file
+' Hardwire
+'
+' Copyright (C) 2005 Ian Cowburn (ianc@noddybox.co.uk)
+'
+' This program is free software; you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation; either version 2 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY; without even the implied warranty of
+' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+' GNU General Public License for more details.
+'
+' You should have received a copy of the GNU General Public License
+' along with this program; if not, write to the Free Software
+' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+'
+' -------------------------------------------------------------------------
+'
+' $Id$
+'
+Strict
+Import brl.pngloader
+
+Import noddybox.bitmapfont
+Import noddybox.gfxmenu
+
+Import "types.bmx"
+
+
+' Included binaries
+'
+Incbin "HELP/help.txt"
+Incbin "HELP/pit.png"
+Incbin "HELP/piece.png"
+Incbin "HELP/wire1.png"
+Incbin "HELP/wire2.png"
+Incbin "HELP/wire3.png"
+Incbin "HELP/loop1.png"
+Incbin "HELP/bomb.png"
+Incbin "HELP/twister.png"
+Incbin "HELP/nuke.png"
+Incbin "HELP/cross.png"
+
+Type THelp
+ Const TOP:Int=50
+ Const BOTTOM:Int=550
+ Field list:TList
+ Field pos:Int
+ Field item:TLink
+ Field del:Int
+ Field bd:TGameBackdrop
+
+ Method New()
+ Local str:TStream=ReadStream("incbin::HELP/help.txt")
+
+ Assert str,"Unable to open help file"
+
+ list=CreateList()
+
+ While Not str.Eof()
+ Local line:String=str.ReadLine()
+
+ If line.length
+ Select line[0]
+ Case Asc("#")
+ list.AddLast(THelpImage.Create(line[1..]))
+ Case Asc("$")
+ list.AddLast(THelpAnimImage.Create(line[1..],False))
+ Case Asc("~~")
+ list.AddLast(THelpAnimImage.Create(line[1..],True))
+ Default
+ list.AddLast(THelpText.Create(line))
+ End Select
+ Else
+ list.AddLast(THelpBlankLine.Create(line))
+ EndIf
+ Wend
+
+ bd=New TGameBackdrop
+ item=list.LastLink()
+ pos=TOP-Current().Height()
+ End Method
+
+ Method Draw()
+ bd.Draw()
+
+ Local y:Int=pos
+ Local i:TLink=item
+
+ While y<BOTTOM
+ Local h:THelpItem=THelpItem(i.Value())
+ h.Draw(y)
+ y:+h.Height()
+ i=i.NextLink()
+ If Not i
+ i=list.FirstLink()
+ EndIf
+ Wend
+
+ SetColor(0,0,0)
+ DrawRect(0,0,GraphicsWidth(),TOP)
+ DrawRect(0,BOTTOM,GraphicsWidth(),GraphicsHeight()-BOTTOM)
+ For Local f:Int=0 To 8
+ SetAlpha(1.0-f*0.125)
+ DrawLine(0,TOP+f,GraphicsWidth(),TOP+f)
+ DrawLine(0,BOTTOM-f,GraphicsWidth(),BOTTOM-f)
+ Next
+ SetAlpha(1)
+ SetColor(128,128,128)
+ DrawLine(0,TOP-1,GraphicsWidth(),TOP-1)
+ DrawLine(0,TOP+1,GraphicsWidth(),TOP+1)
+ DrawLine(0,BOTTOM-1,GraphicsWidth(),BOTTOM-1)
+ DrawLine(0,BOTTOM+1,GraphicsWidth(),BOTTOM+1)
+ SetColor(255,255,255)
+ DrawLine(0,TOP,GraphicsWidth(),TOP)
+ DrawLine(0,BOTTOM,GraphicsWidth(),BOTTOM)
+
+ GameGFX.large.Centre("HOW TO PLAY HARDWIRE",0,255,255,0)
+ GameGFX.large.Centre("USE UP/DOWN CURSORS TO SCROLL",BOTTOM+10,255,255,0)
+ GameGFX.large.Centre("ESCAPE TO EXIT",BOTTOM+30,255,255,0)
+ End Method
+
+ Method Current:THelpItem()
+ Return THelpItem(item.Value())
+ End Method
+
+ Method Show()
+ Local done:Int=False
+ Local fade:TFadeScreen=TFadeScreen.FadeIn()
+
+ While Not done
+ Cls
+
+ Draw()
+
+ If KeyDown(KEY_DOWN)
+ del=Min(del+1,200)
+ pos:-del/4+1
+ While pos<TOP-Current().Height()
+ pos:+Current().Height()
+ item=item.NextLink()
+ If Not item
+ item=list.FirstLink()
+ EndIf
+ Wend
+ ElseIf KeyDown(KEY_UP)
+ del=Min(del+1,200)
+ pos:+del/4+1
+ While pos>TOP
+ item=item.PrevLink()
+ If Not item
+ item=list.LastLink()
+ EndIf
+ pos:-Current().Height()
+ Wend
+ ElseIf KeyHit(KEY_ESCAPE)
+ FlushKeys()
+ done=True
+ Else
+ del=0
+ EndIf
+
+ If fade
+ If fade.Fade()
+ fade.Draw()
+ Else
+ fade=Null
+ EndIf
+ EndIf
+
+ Flip
+ Wend
+
+ SetColor(255,255,255)
+ End Method
+End Type
+
+Type THelpItem Abstract
+ Method Height:Int() Abstract
+ Method Draw(y:Int) Abstract
+End Type
+
+Type THelpText Extends THelpItem
+ Field txt:String
+ Field r:Int
+ Field g:Int
+ Field b:Int
+ Field sc:Int
+
+ Function Create:THelpItem(txt:String)
+ Local o:THelpText=New THelpText
+
+ Select txt[0]
+ Case Asc("@")
+ o.sc=2
+ o.r=255
+ o.g=255
+ o.b=0
+ o.txt=txt[1..]
+ Case Asc("!")
+ o.sc=1
+ o.r=255
+ o.g=255
+ o.b=0
+ o.txt=txt[1..]
+ Default
+ o.sc=1
+ o.r=255
+ o.g=255
+ o.b=255
+ o.txt=txt
+ End Select
+
+ Return THelpItem(o)
+ End Function
+
+ Method Height:Int()
+ Return GameGFX.large.MaxHeight()*sc
+ End Method
+
+ Method Draw(y:Int)
+ SetScale(sc,sc)
+ GameGFX.large.Centre(txt,y,r,g,b)
+ SetScale(1,1)
+ End Method
+End Type
+
+
+Type THelpBlankLine Extends THelpItem
+ Function Create:THelpItem(txt:String)
+ Local o:THelpBlankLine=New THelpBlankLine
+ Return THelpItem(o)
+ End Function
+
+ Method Height:Int()
+ Return GameGFX.large.MaxHeight()
+ End Method
+
+ Method Draw(y:Int)
+ End Method
+End Type
+
+
+Type THelpImage Extends THelpItem
+ Field img:TImage
+ Field x:Int
+
+ Function Create:THelpItem(url:String)
+ Local o:THelpImage=New THelpImage
+ o.img=LoadImage(url,0)
+ Assert o.img,"Failed to load help image " + url
+ o.x=(GraphicsWidth()-ImageWidth(o.img))/2
+ Return THelpItem(o)
+ End Function
+
+ Method Height:Int()
+ Return ImageHeight(img)
+ End Method
+
+ Method Draw(y:Int)
+ SetColor(255,255,255)
+ DrawImage(img,x,y)
+ End Method
+End Type
+
+
+Type THelpAnimImage Extends THelpItem
+ Field img:TImage
+ Field x:Int
+ Field frame:Int
+ Field framei:Int
+ Field framed:Int
+ Field pong:Int
+
+ Function Create:THelpItem(url:String,pong:Int)
+ Local o:THelpAnimImage=New THelpAnimImage
+ o.img=LoadAnimImage(url,32,32,0,4,0)
+ Assert o.img,"Failed to load help anim image " + url
+ o.x=(GraphicsWidth()-32)/2
+ o.frame=0
+ o.framed=5
+ o.framei=1
+ o.pong=pong
+ Return THelpItem(o)
+ End Function
+
+ Method Height:Int()
+ Return ImageHeight(img)
+ End Method
+
+ Method Draw(y:Int)
+ SetColor(255,255,255)
+ DrawImage(img,x,y,frame)
+ framed:-1
+ If framed=0
+ framed=5
+ If pong
+ frame:+framei
+ If frame=0 Or frame=3
+ framei=-framei
+ EndIf
+ Else
+ frame=(frame+1) Mod 4
+ EndIf
+ EndIf
+ End Method
+End Type
diff --git a/particle.bmx b/particle.bmx
index 40a9c24..6e8d469 100644
--- a/particle.bmx
+++ b/particle.bmx
@@ -1,318 +1,334 @@
-' Hardwire
-'
-' Copyright 2005 Ian Cowburn
-'
-' $Id$
-'
-Strict
-Import "types.bmx"
-
-Type TParticle
- Field life:Int
- Field i:TImage
- Field x:Double
- Field y:Double
- Field a:Double
- Field dx:Double
- Field dy:Double
- Field ai:Double
- Field s:Double
- Field si:Double
-
- Function Dust:TParticle(x:Int, y:Int)
- Local o:TParticle=New TParticle
- o.life=50
- o.x=x
- o.y=y
- o.a=1
- o.ai=-0.05
- o.dx=0
- o.dy=0
- o.s=1
- o.si=0.1
- o.i=GameGFX.dust
- Return o
- End Function
-
- Function Image:TParticle(i:TImage, x:Int, y:Int)
- Local o:TParticle=New TParticle
- o.life=120
- o.x=x
- o.y=y
- o.a=1
- o.ai=-0.01
- o.dx=0
- o.dy=-0.1
- o.s=1
- o.si=0
- o.i=i
- Return o
- End Function
-
- Method Update:Int()
- SetAlpha(a)
- SetScale(s,s)
- DrawImage(i,x,y)
- x:+dx
- y:+dy
- life:-1
- a:+ai
- s:+si
- Return life>0
- End Method
-End Type
-
-Type Particles
- Global plist:TList
-
- Function Init()
- plist=CreateList()
- End Function
-
- Function Clear()
- plist.Clear()
- End Function
-
- Function AddDust(x:Int, y:Int)
- plist.AddLast(TParticle.Dust(x,y))
- End Function
-
- Function AddImage(i:TImage, x:Int, y:Int)
- plist.AddLast(TParticle.Image(i,x,y))
- End Function
-
- Function Draw()
- SetColor(255,255,255)
- Local l:TEasyLink=TEasyLink.Create(plist)
-
- While l.Value()
- Local p:TParticle=TParticle(l.Value())
-
- If (p.Update())
- l.MoveNext()
- Else
- l.Remove()
- EndIf
- Wend
- SetAlpha(1)
- SetScale(1,1)
- End Function
-End Type
-
-Type TTextParticle
- Field txt:String
- Field x:Double
- Field y:Double
- Field a:Double
- Field dx:Double
- Field dy:Double
- Field ai:Double
- Field s:Double
- Field si:Double
- Field r:Int
- Field g:Int
- Field b:Int
- Field fnt:TBitmapFont
-
- Function Create:TTextParticle(fnt:TBitmapFont, txt:String, x:Double, y:Double, dx:Double, dy:Double, r:Int, g:Int, b:Int, a:Double, ai:Double, s:Double, si:Double)
- Local o:TTextParticle=New TTextParticle
-
- If x=-1
- x=GraphicsWidth()/2
- EndIf
-
- o.x=x
- o.y=y
- o.a=a
- o.ai=ai
- o.dx=dx
- o.dy=dy
- o.s=s
- o.si=si
- o.txt=txt
- o.r=r
- o.g=g
- o.b=b
- o.fnt=fnt
- Return o
- End Function
-
- Method Update:Int()
- SetAlpha(a)
- SetScale(s,s)
- fnt.CentreOn(txt,x,y,r,g,b)
- x:+dx
- y:+dy
- a:+ai
- s:+si
- Return a>0
- End Method
-End Type
-
-Type TextParticles
- Global plist:TList
- Global sy:Int
- Const sx:Int=646
-
- Function Init()
- plist=CreateList()
- sy=300
- End Function
-
- Function Clear()
- plist.Clear()
- sy=300
- End Function
-
- Function Big(txt:String, r:Int=-1, g:Int=-1, b:Int=-1)
- If r=-1 Then r=Rand(128,255)
- If g=-1 Then g=Rand(128,255)
- If b=-1 Then b=Rand(128,255)
- plist.AddLast(TTextParticle.Create(GameGFX.font,txt,-1,GraphicsHeight()-GameGFX.font.MaxHeight()/2,0,0,r,g,b,1,-0.01,1,0))
- plist.AddLast(TTextParticle.Create(GameGFX.font,txt,-1,GraphicsHeight()-GameGFX.font.MaxHeight()/2,0,0,r,g,b,1,-0.02,1,0.1))
- End Function
-
- Function Score(txt:String)
- Local r:Int=Rand(128,255)
- Local g:Int=Rand(128,255)
- Local b:Int=Rand(128,255)
-
- plist.AddLast(TTextParticle.Create(GameGFX.font,txt,sx,sy,0,0,r,g,b,1,-0.01,1,0))
- plist.AddLast(TTextParticle.Create(GameGFX.font,txt,sx,sy,0,0,r,g,b,1,-0.02,1,0.1))
-
- sy:+GameGFX.font.MaxHeight()
-
- If sy>GraphicsHeight()-20
- sy=300
- EndIf
- End Function
-
- Function Draw()
- Local l:TEasyLink=TEasyLink.Create(plist)
-
- While l.Value()
- Local p:TTextParticle=TTextParticle(l.Value())
-
- If (p.Update())
- l.MoveNext()
- Else
- l.Remove()
- EndIf
- Wend
- SetColor(255,255,255)
- SetAlpha(1)
- SetScale(1,1)
- End Function
-End Type
-
-
-Type TExplosionBase
- Field p:TPixmap[4]
-
- Function Create:TExplosionBase(base:TImage)
- Local o:TExplosionBase=New TExplosionBase
- o.p=New TPixmap[4]
- o.p[0]=GrabFrom(base,0,0)
- o.p[1]=GrabFrom(base,16,0)
- o.p[2]=GrabFrom(base,0,16)
- o.p[3]=GrabFrom(base,16,16)
- Return o
- End Function
-
- Function GrabFrom:TPixmap(i:TImage,x:Int, y:Int)
- Local p:TPixmap=LockImage(i)
- Local ret:TPixmap=p.Copy()
- ret=ResizePixmap(ret,16,16)
- For Local cx:Int=0 Until 16
- For Local cy:Int=0 Until 16
- ret.WritePixel(cx,cy,p.ReadPixel(x+cx,y+cy))
- Next
- Next
- UnlockImage(i)
- Return ret
- End Function
-End Type
-
-Type TExplosion_Old
- Field x:Double
- Field y:Double
- Field dy:Double
- Field dx:Double
- Field p:TPixmap
-
- Function Create:TExplosion(p:TPixmap,x:Double,y:Double,dx:Double,dy:Double)
- Local o:TExplosion=New TExplosion
- o.x=x
- o.y=y
- o.dx=dx
- o.dy=dy
- Return o
- End Function
-
- Method Update:Int()
- DrawPixmap(p,x,y)
- x:+dx
- y:+dy
- dy:+0.05
- Return dx>-16 And dx<GraphicsWidth()+16 And y<GraphicsHeight()
- End Method
-End Type
-
-Type TExplosion
- Field x:Double
- Field y:Double
- Field dy:Double
- Field dx:Double
-
- Function Create:TExplosion(x:Double,y:Double,dx:Double,dy:Double)
- Local o:TExplosion=New TExplosion
- o.x=x
- o.y=y
- o.dx=dx
- o.dy=dy
- Return o
- End Function
-
- Method Update:Int()
- SetColor(Rand(0,255),Rand(0,255),Rand(0,255))
- Plot(x,y)
- x:+dx
- y:+dy
- dy:+0.1
- Return dx>-16 And dx<GraphicsWidth()+16 And y<GraphicsHeight()
- End Method
-End Type
-
-Type ExplosionParticles
- Global plist:TList
-
- Function Init()
- plist=CreateList()
- End Function
-
- Function Clear()
- plist.Clear()
- End Function
-
- Function BlowUp(x:Int, y:Int)
- For Local cx:Int=0 Until 32
- For Local cy:Int=0 Until 32
- plist.AddLast(TExplosion.Create(x+cx,y+cy,Rnd(-2,2),Rnd(-2,2)))
- Next
- Next
- End Function
-
- Function Draw()
- Local l:TEasyLink=TEasyLink.Create(plist)
-
- While l.Value()
- Local p:TExplosion=TExplosion(l.Value())
-
- If (p.Update())
- l.MoveNext()
- Else
- l.Remove()
- EndIf
- Wend
- End Function
-End Type \ No newline at end of file
+' Hardwire
+'
+' Copyright (C) 2005 Ian Cowburn (ianc@noddybox.co.uk)
+'
+' This program is free software; you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation; either version 2 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY; without even the implied warranty of
+' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+' GNU General Public License for more details.
+'
+' You should have received a copy of the GNU General Public License
+' along with this program; if not, write to the Free Software
+' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+'
+' -------------------------------------------------------------------------
+'
+' $Id$
+'
+Strict
+Import "types.bmx"
+
+Type TParticle
+ Field life:Int
+ Field i:TImage
+ Field x:Double
+ Field y:Double
+ Field a:Double
+ Field dx:Double
+ Field dy:Double
+ Field ai:Double
+ Field s:Double
+ Field si:Double
+
+ Function Dust:TParticle(x:Int, y:Int)
+ Local o:TParticle=New TParticle
+ o.life=50
+ o.x=x
+ o.y=y
+ o.a=1
+ o.ai=-0.05
+ o.dx=0
+ o.dy=0
+ o.s=1
+ o.si=0.1
+ o.i=GameGFX.dust
+ Return o
+ End Function
+
+ Function Image:TParticle(i:TImage, x:Int, y:Int)
+ Local o:TParticle=New TParticle
+ o.life=120
+ o.x=x
+ o.y=y
+ o.a=1
+ o.ai=-0.01
+ o.dx=0
+ o.dy=-0.1
+ o.s=1
+ o.si=0
+ o.i=i
+ Return o
+ End Function
+
+ Method Update:Int()
+ SetAlpha(a)
+ SetScale(s,s)
+ DrawImage(i,x,y)
+ x:+dx
+ y:+dy
+ life:-1
+ a:+ai
+ s:+si
+ Return life>0
+ End Method
+End Type
+
+Type Particles
+ Global plist:TList
+
+ Function Init()
+ plist=CreateList()
+ End Function
+
+ Function Clear()
+ plist.Clear()
+ End Function
+
+ Function AddDust(x:Int, y:Int)
+ plist.AddLast(TParticle.Dust(x,y))
+ End Function
+
+ Function AddImage(i:TImage, x:Int, y:Int)
+ plist.AddLast(TParticle.Image(i,x,y))
+ End Function
+
+ Function Draw()
+ SetColor(255,255,255)
+ Local l:TEasyLink=TEasyLink.Create(plist)
+
+ While l.Value()
+ Local p:TParticle=TParticle(l.Value())
+
+ If (p.Update())
+ l.MoveNext()
+ Else
+ l.Remove()
+ EndIf
+ Wend
+ SetAlpha(1)
+ SetScale(1,1)
+ End Function
+End Type
+
+Type TTextParticle
+ Field txt:String
+ Field x:Double
+ Field y:Double
+ Field a:Double
+ Field dx:Double
+ Field dy:Double
+ Field ai:Double
+ Field s:Double
+ Field si:Double
+ Field r:Int
+ Field g:Int
+ Field b:Int
+ Field fnt:TBitmapFont
+
+ Function Create:TTextParticle(fnt:TBitmapFont, txt:String, x:Double, y:Double, dx:Double, dy:Double, r:Int, g:Int, b:Int, a:Double, ai:Double, s:Double, si:Double)
+ Local o:TTextParticle=New TTextParticle
+
+ If x=-1
+ x=GraphicsWidth()/2
+ EndIf
+
+ o.x=x
+ o.y=y
+ o.a=a
+ o.ai=ai
+ o.dx=dx
+ o.dy=dy
+ o.s=s
+ o.si=si
+ o.txt=txt
+ o.r=r
+ o.g=g
+ o.b=b
+ o.fnt=fnt
+ Return o
+ End Function
+
+ Method Update:Int()
+ SetAlpha(a)
+ SetScale(s,s)
+ fnt.CentreOn(txt,x,y,r,g,b)
+ x:+dx
+ y:+dy
+ a:+ai
+ s:+si
+ Return a>0
+ End Method
+End Type
+
+Type TextParticles
+ Global plist:TList
+ Global sy:Int
+ Const sx:Int=646
+
+ Function Init()
+ plist=CreateList()
+ sy=300
+ End Function
+
+ Function Clear()
+ plist.Clear()
+ sy=300
+ End Function
+
+ Function Big(txt:String, r:Int=-1, g:Int=-1, b:Int=-1)
+ If r=-1 Then r=Rand(128,255)
+ If g=-1 Then g=Rand(128,255)
+ If b=-1 Then b=Rand(128,255)
+ plist.AddLast(TTextParticle.Create(GameGFX.font,txt,-1,GraphicsHeight()-GameGFX.font.MaxHeight()/2,0,0,r,g,b,1,-0.01,1,0))
+ plist.AddLast(TTextParticle.Create(GameGFX.font,txt,-1,GraphicsHeight()-GameGFX.font.MaxHeight()/2,0,0,r,g,b,1,-0.02,1,0.1))
+ End Function
+
+ Function Score(txt:String)
+ Local r:Int=Rand(128,255)
+ Local g:Int=Rand(128,255)
+ Local b:Int=Rand(128,255)
+
+ plist.AddLast(TTextParticle.Create(GameGFX.font,txt,sx,sy,0,0,r,g,b,1,-0.01,1,0))
+ plist.AddLast(TTextParticle.Create(GameGFX.font,txt,sx,sy,0,0,r,g,b,1,-0.02,1,0.1))
+
+ sy:+GameGFX.font.MaxHeight()
+
+ If sy>GraphicsHeight()-20
+ sy=300
+ EndIf
+ End Function
+
+ Function Draw()
+ Local l:TEasyLink=TEasyLink.Create(plist)
+
+ While l.Value()
+ Local p:TTextParticle=TTextParticle(l.Value())
+
+ If (p.Update())
+ l.MoveNext()
+ Else
+ l.Remove()
+ EndIf
+ Wend
+ SetColor(255,255,255)
+ SetAlpha(1)
+ SetScale(1,1)
+ End Function
+End Type
+
+
+Type TExplosionBase
+ Field p:TPixmap[4]
+
+ Function Create:TExplosionBase(base:TImage)
+ Local o:TExplosionBase=New TExplosionBase
+ o.p=New TPixmap[4]
+ o.p[0]=GrabFrom(base,0,0)
+ o.p[1]=GrabFrom(base,16,0)
+ o.p[2]=GrabFrom(base,0,16)
+ o.p[3]=GrabFrom(base,16,16)
+ Return o
+ End Function
+
+ Function GrabFrom:TPixmap(i:TImage,x:Int, y:Int)
+ Local p:TPixmap=LockImage(i)
+ Local ret:TPixmap=p.Copy()
+ ret=ResizePixmap(ret,16,16)
+ For Local cx:Int=0 Until 16
+ For Local cy:Int=0 Until 16
+ ret.WritePixel(cx,cy,p.ReadPixel(x+cx,y+cy))
+ Next
+ Next
+ UnlockImage(i)
+ Return ret
+ End Function
+End Type
+
+Type TExplosion_Old
+ Field x:Double
+ Field y:Double
+ Field dy:Double
+ Field dx:Double
+ Field p:TPixmap
+
+ Function Create:TExplosion(p:TPixmap,x:Double,y:Double,dx:Double,dy:Double)
+ Local o:TExplosion=New TExplosion
+ o.x=x
+ o.y=y
+ o.dx=dx
+ o.dy=dy
+ Return o
+ End Function
+
+ Method Update:Int()
+ DrawPixmap(p,x,y)
+ x:+dx
+ y:+dy
+ dy:+0.05
+ Return dx>-16 And dx<GraphicsWidth()+16 And y<GraphicsHeight()
+ End Method
+End Type
+
+Type TExplosion
+ Field x:Double
+ Field y:Double
+ Field dy:Double
+ Field dx:Double
+
+ Function Create:TExplosion(x:Double,y:Double,dx:Double,dy:Double)
+ Local o:TExplosion=New TExplosion
+ o.x=x
+ o.y=y
+ o.dx=dx
+ o.dy=dy
+ Return o
+ End Function
+
+ Method Update:Int()
+ SetColor(Rand(0,255),Rand(0,255),Rand(0,255))
+ Plot(x,y)
+ x:+dx
+ y:+dy
+ dy:+0.1
+ Return dx>-16 And dx<GraphicsWidth()+16 And y<GraphicsHeight()
+ End Method
+End Type
+
+Type ExplosionParticles
+ Global plist:TList
+
+ Function Init()
+ plist=CreateList()
+ End Function
+
+ Function Clear()
+ plist.Clear()
+ End Function
+
+ Function BlowUp(x:Int, y:Int)
+ For Local cx:Int=0 Until 32
+ For Local cy:Int=0 Until 32
+ plist.AddLast(TExplosion.Create(x+cx,y+cy,Rnd(-2,2),Rnd(-2,2)))
+ Next
+ Next
+ End Function
+
+ Function Draw()
+ Local l:TEasyLink=TEasyLink.Create(plist)
+
+ While l.Value()
+ Local p:TExplosion=TExplosion(l.Value())
+
+ If (p.Update())
+ l.MoveNext()
+ Else
+ l.Remove()
+ EndIf
+ Wend
+ End Function
+End Type
diff --git a/sounds.bmx b/sounds.bmx
index 19a2596..95e03c9 100644
--- a/sounds.bmx
+++ b/sounds.bmx
@@ -1,54 +1,70 @@
-' Hardwire
-'
-' Copyright 2005 Ian Cowburn
-'
-' $Id$
-'
-Strict
-Import brl.audio
-Import brl.freeaudioaudio
-Import brl.wavloader
-
-Incbin "SFX/pop.wav"
-Incbin "SFX/click.wav"
-Incbin "SFX/path.wav"
-
-Type Sound
- Global popsfx:TSound
- Global clicksfx:TSound
- Global pathsfx:TSound
-
- Global play_pop:Int
- Global play_click:Int
- Global play_path:Int
-
- Function Init()
- popsfx=LoadSound("incbin::SFX/pop.wav")
- clicksfx=LoadSound("incbin::SFX/click.wav")
- pathsfx=LoadSound("incbin::SFX/path.wav")
- play_pop=False
- play_click=False
- play_path=False
- End Function
-
- Function Pop()
- play_pop=True
- End Function
-
- Function Click()
- play_click=True
- End Function
-
- Function Path()
- play_path=True
- End Function
-
- Function Process()
- If play_pop Then popsfx.Play()
- If play_click Then clicksfx.Play()
- If play_path Then pathsfx.Play()
- play_pop=False
- play_click=False
- play_path=False
- End Function
-End Type
+' Hardwire
+'
+' Copyright (C) 2005 Ian Cowburn (ianc@noddybox.co.uk)
+'
+' This program is free software; you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation; either version 2 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY; without even the implied warranty of
+' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+' GNU General Public License for more details.
+'
+' You should have received a copy of the GNU General Public License
+' along with this program; if not, write to the Free Software
+' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+'
+' -------------------------------------------------------------------------
+'
+' $Id$
+'
+Strict
+Import brl.audio
+Import brl.freeaudioaudio
+Import brl.wavloader
+
+Incbin "SFX/pop.wav"
+Incbin "SFX/click.wav"
+Incbin "SFX/path.wav"
+
+Type Sound
+ Global popsfx:TSound
+ Global clicksfx:TSound
+ Global pathsfx:TSound
+
+ Global play_pop:Int
+ Global play_click:Int
+ Global play_path:Int
+
+ Function Init()
+ popsfx=LoadSound("incbin::SFX/pop.wav")
+ clicksfx=LoadSound("incbin::SFX/click.wav")
+ pathsfx=LoadSound("incbin::SFX/path.wav")
+ play_pop=False
+ play_click=False
+ play_path=False
+ End Function
+
+ Function Pop()
+ play_pop=True
+ End Function
+
+ Function Click()
+ play_click=True
+ End Function
+
+ Function Path()
+ play_path=True
+ End Function
+
+ Function Process()
+ If play_pop Then popsfx.Play()
+ If play_click Then clicksfx.Play()
+ If play_path Then pathsfx.Play()
+ play_pop=False
+ play_click=False
+ play_path=False
+ End Function
+End Type
diff --git a/types.bmx b/types.bmx
index dbe5cbd..8d8d57b 100644
--- a/types.bmx
+++ b/types.bmx
@@ -1,426 +1,460 @@
-' Hardwire
-'
-' Copyright 2005 Ian Cowburn
-'
-' $Id$
-'
-'
-' This should really be called Global.bmx probably...
-'
-Strict
-Import brl.pngloader
-
-Import noddybox.bitmapfont
-Import noddybox.gfxmenu
-
-
-' Included binaries
-'
-Incbin "GFX/font.bmf"
-Incbin "GFX/small.bmf"
-Incbin "GFX/large.bmf"
-Incbin "GFX/pointer.png"
-Incbin "GFX/play_button.png"
-Incbin "GFX/quit_button.png"
-Incbin "GFX/keys_button.png"
-Incbin "GFX/rules_button.png"
-Incbin "GFX/left_button.png"
-Incbin "GFX/right_button.png"
-Incbin "GFX/copper.png"
-Incbin "GFX/copperslice.png"
-Incbin "GFX/dust.png"
-Incbin "GFX/title.png"
-Incbin "GFX/gameover.png"
-Incbin "GFX/bdropstar.png"
-
-Incbin "TILES/tile.png"
-Incbin "TILES/pit_top.png"
-Incbin "TILES/pit_bottomleft.png"
-Incbin "TILES/pit_bottomright.png"
-Incbin "TILES/pit_bottom.png"
-Incbin "TILES/pit_side.png"
-Incbin "TILES/trode_left.png"
-Incbin "TILES/trode_right.png"
-Incbin "TILES/trode_bottom.png"
-Incbin "TILES/top_bottom.png"
-Incbin "TILES/left_right.png"
-Incbin "TILES/cross.png"
-Incbin "TILES/top_left.png"
-Incbin "TILES/top_right.png"
-Incbin "TILES/bottom_left.png"
-Incbin "TILES/bottom_right.png"
-
-Incbin "TILES/special_bomb.png"
-Incbin "TILES/special_twister.png"
-Incbin "TILES/special_nuke.png"
-Incbin "TILES/special_cross.png"
-
-Const HERTZ:Int=60
-
-Type Lookup
- Global si:Double[]
- Global co:Double[]
-
- Function Init()
- si=New Double[360]
- co=New Double[360]
-
- For Local a:Int=0 To 359
- si[a]=Sin(a)
- co[a]=Cos(a)
- Next
- End Function
-End Type
-
-
-Type GameGFX
- Global font:TBitmapFont
- Global small:TBitmapFont
- Global large:TBitmapFont
-
- Global title:TImage
- Global gameover:TImage
-
- Global pointer:TImage
- Global copper:TImage
- Global copperslice:TImage
- Global dust:TImage
-
- Global play_button:TImage
- Global quit_button:TImage
- Global left_button:TImage
- Global right_button:TImage
- Global rules_button:TImage
- Global keys_button:TImage
-
- Global tile:TImage
-
- Global pit_top:TImage
- Global pit_bottomleft:TImage
- Global pit_bottomright:TImage
- Global pit_bottom:TImage
- Global pit_side:TImage
-
- Global trode_left:TImage
- Global trode_right:TImage
- Global trode_bottom:TImage
-
- Global top_bottom:Timage
- Global left_right:Timage
- Global cross:Timage
- Global top_left:Timage
- Global top_right:Timage
- Global bottom_left:Timage
- Global bottom_right:Timage
-
- Global special_bomb:TImage
- Global special_twister:TImage
- Global special_nuke:TImage
- Global special_cross:TImage
-
- Global bdropstar:TImage
-
- Function SafeLoadImage:TImage(p:String, mode:Int)
- Local i:TImage=LoadImage(p,mode)
- Assert i,"Failed to load " + p
- Return i
- End Function
-
- Function SafeLoadAnimImage:TImage(p:String, w:Int, h:Int, f:Int, c:Int, mode:Int)
- Local i:TImage=LoadAnimImage(p,w,h,f,c,mode)
- Assert i,"Failed to load " + p
- Return i
- End Function
-
- Function Init()
- font=TBitmapFont.Load("incbin::GFX/font.bmf",0)
- small=TBitmapFont.Load("incbin::GFX/small.bmf",0)
- large=TBitmapFont.Load("incbin::GFX/large.bmf",0)
-
- Assert font,"Failed to load incbin::GFX/font.bmf"
- Assert small,"Failed to load incbin::GFX/small.bmf"
- Assert large,"Failed to load incbin::GFX/large.bmf"
-
- title=SafeLoadImage("incbin::GFX/title.png",0)
- gameover=SafeLoadImage("incbin::GFX/gameover.png",0)
- MidHandleImage(gameover)
-
- pointer=SafeLoadImage("incbin::GFX/pointer.png",0)
-
- copper=SafeLoadImage("incbin::GFX/copper.png",0)
- copperslice=SafeLoadImage("incbin::GFX/copperslice.png",0)
-
- dust=SafeLoadImage("incbin::GFX/dust.png",FILTEREDIMAGE)
- MidHandleImage(dust)
-
- play_button=SafeLoadImage("incbin::GFX/play_button.png",0)
- quit_button=SafeLoadImage("incbin::GFX/quit_button.png",0)
- rules_button=SafeLoadImage("incbin::GFX/rules_button.png",0)
- keys_button=SafeLoadImage("incbin::GFX/keys_button.png",0)
- left_button=SafeLoadImage("incbin::GFX/left_button.png",0)
- right_button=SafeLoadImage("incbin::GFX/right_button.png",0)
-
- tile=SafeLoadImage("incbin::TILES/tile.png",0)
-
- pit_top=SafeLoadImage("incbin::TILES/pit_top.png",0)
- pit_bottom=SafeLoadImage("incbin::TILES/pit_bottom.png",0)
- pit_bottomleft=SafeLoadImage("incbin::TILES/pit_bottomleft.png",0)
- pit_bottomright=SafeLoadImage("incbin::TILES/pit_bottomright.png",0)
- pit_side=SafeLoadImage("incbin::TILES/pit_side.png",0)
-
- trode_left=SafeLoadImage("incbin::TILES/trode_left.png",0)
- trode_right=SafeLoadImage("incbin::TILES/trode_right.png",0)
- trode_bottom=SafeLoadImage("incbin::TILES/trode_bottom.png",0)
-
- top_bottom=SafeLoadImage("incbin::TILES/top_bottom.png",0)
- left_right=SafeLoadImage("incbin::TILES/left_right.png",0)
- cross=SafeLoadImage("incbin::TILES/cross.png",0)
- top_left=SafeLoadImage("incbin::TILES/top_left.png",0)
- top_right=SafeLoadImage("incbin::TILES/top_right.png",0)
- bottom_left=SafeLoadImage("incbin::TILES/bottom_left.png",0)
- bottom_right=SafeLoadImage("incbin::TILES/bottom_right.png",0)
-
- special_bomb=SafeLoadAnimImage("incbin::TILES/special_bomb.png",32,32,0,4,DYNAMICIMAGE)
- special_twister=SafeLoadAnimImage("incbin::TILES/special_twister.png",32,32,0,4,DYNAMICIMAGE)
- special_nuke=SafeLoadAnimImage("incbin::TILES/special_nuke.png",32,32,0,4,DYNAMICIMAGE)
- special_cross=SafeLoadAnimImage("incbin::TILES/special_cross.png",32,32,0,4,DYNAMICIMAGE)
-
- bdropstar=SafeLoadAnimImage("incbin::GFX/bdropstar.png",8,8,0,6,0)'FILTEREDIMAGE)
- End Function
-End Type
-
-Type GameConfig
- Global kleft:Int
- Global kright:Int
- Global krotright:Int
- Global krotleft:Int
- Global kdrop:Int
- Global kpause:Int
- Global start_level:Int
- Global hiscore:Int
-
- Function Load()
- Local s:TStream=ReadStream("hardwire.config")
-
- If s=Null
- kleft=KEY_LEFT
- kright=KEY_RIGHT
- krotright=KEY_UP
- krotleft=KEY_DOWN
- kdrop=KEY_SPACE
- kpause=KEY_P
- start_level=1
- hiscore=0
- Return
- EndIf
-
- s=LittleEndianStream(s)
-
- kleft=s.ReadInt()
- kright=s.ReadInt()
- krotright=s.ReadInt()
- krotleft=s.ReadInt()
- kdrop=s.ReadInt()
- kpause=s.ReadInt()
- start_level=s.ReadInt()
- hiscore=s.ReadInt()
-
- s.Close()
- End Function
-
- Function Save()
- Local s:TStream=WriteStream("hardwire.config")
-
- If s=Null
- Return
- EndIf
-
- s=LittleEndianStream(s)
-
- s.WriteInt(kleft)
- s.WriteInt(kright)
- s.WriteInt(krotright)
- s.WriteInt(krotleft)
- s.WriteInt(kdrop)
- s.WriteInt(kpause)
- s.WriteInt(start_level)
- s.WriteInt(hiscore)
-
- s.Close()
- End Function
-EndType
-
-Type TEasyLink
- Field l:TLink
-
- Function Create:TEasyLink(l:TList)
- Local o:TEasyLink=New TEasyLink
- o.l=l.FirstLink()
- Return o
- End Function
-
- Method Value:Object()
- If l
- Return l.Value()
- Else
- Return Null
- EndIf
- End Method
-
- Method MoveNext()
- If l
- l=l.NextLink()
- EndIf
- End Method
-
- Method Remove()
- Local ol:TLink=l
- MoveNext()
- ol.Remove()
- End Method
-End Type
-
-
-Type TMenuBdrop Extends TGfxMenuBackdrop
- Field msg:String
- Field msgp:Int
- Field msgx:Int
- Field msgy:Int
-
- Method New()
- msg=" "
- msg=" "
- msg:+"Welcome to Hardwire. "
- msg:+"Hardwire was written using BlitzMax -- http://www.blitzbasic.com/ -- and a variety of tools available at "
- msg:+"http://www.noddybox.demon.co.uk/ Please feel free to forward this game to whoever you hate enough "
- msg:+"to inflict this monstrosity upon. Enjoy. This game written under the influence of Slay Radio -- http://www.slayradio.org"
-
- msgx=0
- msgp=0
- msgy=560
- End Method
-
- Method Create:TGfxMenuBackdrop()
- Return Self
- End Method
-
- Method Update()
- GameGFX.large.Draw(msg[..80],msgx,msgy)
-
- msgx:-2
- If msgx<-GameGFX.large.TextWidth(msg[0..1])
- msgx:+GameGFX.large.TextWidth(msg[0..1])
- msg=msg[1..]+msg[0..1]
- EndIf
- End Method
-End Type
-
-Type TFadeScreen
- Field a:Double
- Field ai:Double
-
- Function Create:TFadeScreen(a:Double, ai:Double)
- Local o:TFadeScreen=New TFadeScreen
- o.a=a
- o.ai=ai
- Return o
- End Function
-
- Function FadeOut:TFadeScreen()
- Return Create(0,0.05)
- End Function
-
- Function FadeIn:TFadeScreen()
- Return Create(1,-0.05)
- End Function
-
- Function DoFadeOut()
- Local fade:TFadeScreen=TFadeScreen.FadeOut()
- Local pm:TPixmap=GrabPixmap(0,0,GraphicsWidth(),GraphicsHeight())
-
- While fade.Fade()
- Cls
- DrawPixmap(pm,0,0)
- fade.Draw()
- Flip
- Wend
- End Function
-
- Method Fade:Int()
- a:+ai
- Return a>0 And a<1
- End Method
-
- Method Draw()
- Local r:Int,g:Int,b:Int
- Local oa:Double=GetAlpha()
- GetColor(r,g,b)
- SetAlpha(a)
- SetColor(0,0,0)
- DrawRect(0,0,GraphicsWidth(),GraphicsHeight())
- SetColor(r,g,b)
- SetAlpha(oa)
- End Method
-End Type
-
-Type TGameBackdropStar
- Field x:Double
- Field y:Double
- Field dy:Double
- Field r:Int
- Field g:Int
- Field b:Int
- Field frame:Int
- Field cnt:Int
-
- Method New()
- x=Rnd(0,GraphicsWidth())
- y=Rnd(0,GraphicsHeight())
- dy=Rnd(0.1,2)
- r=Rand(128,255)
- g=Rand(128,255)
- b=Rand(128,255)
- frame=Rand(0,5)
- cnt=5
- End Method
-
- Method Draw(anim:Int)
- If anim
- frame=(frame+1) Mod 6
- EndIf
-
- y:+dy
- If y>GraphicsHeight()+8
- y=-8
- EndIf
- SetColor(r,g,b)
- DrawImage(GameGFX.bdropstar,x,y,frame)
- End Method
-End Type
-
-
-Type TGameBackdrop
- Field num:Int
- Field star:TGameBackdropStar[]
- Field cnt:Int
-
- Method New()
- num=100
- star=New TGameBackdropStar[num]
- cnt=5
-
- For Local f:Int=0 Until num
- star[f]=New TGameBackdropStar
- Next
- End Method
-
- Method Draw()
- For Local f:Int=0 Until num
- star[f].Draw(cnt=0)
- Next
- cnt:-1
- If cnt=-1
- cnt=5
- EndIf
- End Method
-End Type \ No newline at end of file
+' Hardwire
+'
+' Copyright (C) 2005 Ian Cowburn (ianc@noddybox.co.uk)
+'
+' This program is free software; you can redistribute it and/or modify
+' it under the terms of the GNU General Public License as published by
+' the Free Software Foundation; either version 2 of the License, or
+' (at your option) any later version.
+'
+' This program is distributed in the hope that it will be useful,
+' but WITHOUT ANY WARRANTY; without even the implied warranty of
+' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+' GNU General Public License for more details.
+'
+' You should have received a copy of the GNU General Public License
+' along with this program; if not, write to the Free Software
+' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+'
+' -------------------------------------------------------------------------
+'
+' $Id$
+'
+'
+' This should really be called Global.bmx probably...
+'
+Strict
+Import brl.pngloader
+
+Import noddybox.bitmapfont
+Import noddybox.gfxmenu
+
+
+' Included binaries
+'
+Incbin "GFX/font.bmf"
+Incbin "GFX/small.bmf"
+Incbin "GFX/large.bmf"
+Incbin "GFX/pointer.png"
+Incbin "GFX/play_button.png"
+Incbin "GFX/quit_button.png"
+Incbin "GFX/keys_button.png"
+Incbin "GFX/rules_button.png"
+Incbin "GFX/left_button.png"
+Incbin "GFX/right_button.png"
+Incbin "GFX/copper.png"
+Incbin "GFX/copperslice.png"
+Incbin "GFX/dust.png"
+Incbin "GFX/title.png"
+Incbin "GFX/gameover.png"
+Incbin "GFX/bdropstar.png"
+
+Incbin "TILES/tile.png"
+Incbin "TILES/pit_top.png"
+Incbin "TILES/pit_bottomleft.png"
+Incbin "TILES/pit_bottomright.png"
+Incbin "TILES/pit_bottom.png"
+Incbin "TILES/pit_side.png"
+Incbin "TILES/trode_left.png"
+Incbin "TILES/trode_right.png"
+Incbin "TILES/trode_bottom.png"
+Incbin "TILES/top_bottom.png"
+Incbin "TILES/left_right.png"
+Incbin "TILES/cross.png"
+Incbin "TILES/top_left.png"
+Incbin "TILES/top_right.png"
+Incbin "TILES/bottom_left.png"
+Incbin "TILES/bottom_right.png"
+
+Incbin "TILES/special_bomb.png"
+Incbin "TILES/special_twister.png"
+Incbin "TILES/special_nuke.png"
+Incbin "TILES/special_cross.png"
+
+Const HERTZ:Int=60
+
+Type Lookup
+ Global si:Double[]
+ Global co:Double[]
+
+ Function Init()
+ si=New Double[360]
+ co=New Double[360]
+
+ For Local a:Int=0 To 359
+ si[a]=Sin(a)
+ co[a]=Cos(a)
+ Next
+ End Function
+End Type
+
+
+Type GameGFX
+ Global font:TBitmapFont
+ Global small:TBitmapFont
+ Global large:TBitmapFont
+
+ Global title:TImage
+ Global gameover:TImage
+
+ Global pointer:TImage
+ Global copper:TImage
+ Global copperslice:TImage
+ Global dust:TImage
+
+ Global play_button:TImage
+ Global quit_button:TImage
+ Global left_button:TImage
+ Global right_button:TImage
+ Global rules_button:TImage
+ Global keys_button:TImage
+
+ Global tile:TImage
+
+ Global pit_top:TImage
+ Global pit_bottomleft:TImage
+ Global pit_bottomright:TImage
+ Global pit_bottom:TImage
+ Global pit_side:TImage
+
+ Global trode_left:TImage
+ Global trode_right:TImage
+ Global trode_bottom:TImage
+
+ Global top_bottom:Timage
+ Global left_right:Timage
+ Global cross:Timage
+ Global top_left:Timage
+ Global top_right:Timage
+ Global bottom_left:Timage
+ Global bottom_right:Timage
+
+ Global special_bomb:TImage
+ Global special_twister:TImage
+ Global special_nuke:TImage
+ Global special_cross:TImage
+
+ Global bdropstar:TImage
+
+ Function SafeLoadImage:TImage(p:String, mode:Int)
+ Local i:TImage=LoadImage(p,mode)
+ Assert i,"Failed to load " + p
+ Return i
+ End Function
+
+ Function SafeLoadAnimImage:TImage(p:String, w:Int, h:Int, f:Int, c:Int, mode:Int)
+ Local i:TImage=LoadAnimImage(p,w,h,f,c,mode)
+ Assert i,"Failed to load " + p
+ Return i
+ End Function
+
+ Function Init()
+ font=TBitmapFont.Load("incbin::GFX/font.bmf",0)
+ small=TBitmapFont.Load("incbin::GFX/small.bmf",0)
+ large=TBitmapFont.Load("incbin::GFX/large.bmf",0)
+
+ Assert font,"Failed to load incbin::GFX/font.bmf"
+ Assert small,"Failed to load incbin::GFX/small.bmf"
+ Assert large,"Failed to load incbin::GFX/large.bmf"
+
+ title=SafeLoadImage("incbin::GFX/title.png",0)
+ gameover=SafeLoadImage("incbin::GFX/gameover.png",0)
+ MidHandleImage(gameover)
+
+ pointer=SafeLoadImage("incbin::GFX/pointer.png",0)
+
+ copper=SafeLoadImage("incbin::GFX/copper.png",0)
+ copperslice=SafeLoadImage("incbin::GFX/copperslice.png",0)
+
+ dust=SafeLoadImage("incbin::GFX/dust.png",FILTEREDIMAGE)
+ MidHandleImage(dust)
+
+ play_button=SafeLoadImage("incbin::GFX/play_button.png",0)
+ quit_button=SafeLoadImage("incbin::GFX/quit_button.png",0)
+ rules_button=SafeLoadImage("incbin::GFX/rules_button.png",0)
+ keys_button=SafeLoadImage("incbin::GFX/keys_button.png",0)
+ left_button=SafeLoadImage("incbin::GFX/left_button.png",0)
+ right_button=SafeLoadImage("incbin::GFX/right_button.png",0)
+
+ tile=SafeLoadImage("incbin::TILES/tile.png",0)
+
+ pit_top=SafeLoadImage("incbin::TILES/pit_top.png",0)
+ pit_bottom=SafeLoadImage("incbin::TILES/pit_bottom.png",0)
+ pit_bottomleft=SafeLoadImage("incbin::TILES/pit_bottomleft.png",0)
+ pit_bottomright=SafeLoadImage("incbin::TILES/pit_bottomright.png",0)
+ pit_side=SafeLoadImage("incbin::TILES/pit_side.png",0)
+
+ trode_left=SafeLoadImage("incbin::TILES/trode_left.png",0)
+ trode_right=SafeLoadImage("incbin::TILES/trode_right.png",0)
+ trode_bottom=SafeLoadImage("incbin::TILES/trode_bottom.png",0)
+
+ top_bottom=SafeLoadImage("incbin::TILES/top_bottom.png",0)
+ left_right=SafeLoadImage("incbin::TILES/left_right.png",0)
+ cross=SafeLoadImage("incbin::TILES/cross.png",0)
+ top_left=SafeLoadImage("incbin::TILES/top_left.png",0)
+ top_right=SafeLoadImage("incbin::TILES/top_right.png",0)
+ bottom_left=SafeLoadImage("incbin::TILES/bottom_left.png",0)
+ bottom_right=SafeLoadImage("incbin::TILES/bottom_right.png",0)
+
+ special_bomb=SafeLoadAnimImage("incbin::TILES/special_bomb.png",32,32,0,4,DYNAMICIMAGE)
+ special_twister=SafeLoadAnimImage("incbin::TILES/special_twister.png",32,32,0,4,DYNAMICIMAGE)
+ special_nuke=SafeLoadAnimImage("incbin::TILES/special_nuke.png",32,32,0,4,DYNAMICIMAGE)
+ special_cross=SafeLoadAnimImage("incbin::TILES/special_cross.png",32,32,0,4,DYNAMICIMAGE)
+
+ bdropstar=SafeLoadAnimImage("incbin::GFX/bdropstar.png",8,8,0,6,0)'FILTEREDIMAGE)
+ End Function
+End Type
+
+Type GameConfig
+ Global kleft:Int
+ Global kright:Int
+ Global krotright:Int
+ Global krotleft:Int
+ Global kdrop:Int
+ Global kpause:Int
+ Global start_level:Int
+ Global hiscore:Int
+
+ Function Load()
+ Local s:TStream=ReadStream("hardwire.config")
+
+ If s=Null
+ kleft=KEY_LEFT
+ kright=KEY_RIGHT
+ krotright=KEY_UP
+ krotleft=KEY_DOWN
+ kdrop=KEY_SPACE
+ kpause=KEY_P
+ start_level=1
+ hiscore=0
+ Return
+ EndIf
+
+ s=LittleEndianStream(s)
+
+ kleft=s.ReadInt()
+ kright=s.ReadInt()
+ krotright=s.ReadInt()
+ krotleft=s.ReadInt()
+ kdrop=s.ReadInt()
+ kpause=s.ReadInt()
+ start_level=s.ReadInt()
+ hiscore=s.ReadInt()
+
+ s.Close()
+ End Function
+
+ Function Save()
+ Local s:TStream=WriteStream("hardwire.config")
+
+ If s=Null
+ Return
+ EndIf
+
+ s=LittleEndianStream(s)
+
+ s.WriteInt(kleft)
+ s.WriteInt(kright)
+ s.WriteInt(krotright)
+ s.WriteInt(krotleft)
+ s.WriteInt(kdrop)
+ s.WriteInt(kpause)
+ s.WriteInt(start_level)
+ s.WriteInt(hiscore)
+
+ s.Close()
+ End Function
+EndType
+
+Type TEasyLink
+ Field l:TLink
+
+ Function Create:TEasyLink(l:TList)
+ Local o:TEasyLink=New TEasyLink
+ o.l=l.FirstLink()
+ Return o
+ End Function
+
+ Method Value:Object()
+ If l
+ Return l.Value()
+ Else
+ Return Null
+ EndIf
+ End Method
+
+ Method MoveNext()
+ If l
+ l=l.NextLink()
+ EndIf
+ End Method
+
+ Method Remove()
+ Local ol:TLink=l
+ MoveNext()
+ ol.Remove()
+ End Method
+End Type
+
+
+Type TMenuBdrop Extends TGfxMenuBackdrop
+ Field msg:String
+ Field msgp:Int
+ Field msgx:Int
+ Field msgy:Int
+
+ Method New()
+ msg=" "
+ msg=" "
+ msg:+"Welcome to Hardwire. "
+ msg:+"Hardwire was written using BlitzMax -- http://www.blitzbasic.com/ -- and a variety of tools available at "
+ msg:+"http://www.noddybox.demon.co.uk/ Please feel free to forward this game to whoever you hate enough "
+ msg:+"to inflict this monstrosity upon. Enjoy. This game written under the influence of Slay Radio -- http://www.slayradio.org"
+
+ msgx=0
+ msgp=0
+ msgy=560
+ End Method
+
+ Method Create:TGfxMenuBackdrop()
+ Return Self
+ End Method
+
+ Method Update()
+ GameGFX.large.Draw(msg[..80],msgx,msgy)
+
+ msgx:-2
+ If msgx<-GameGFX.large.TextWidth(msg[0..1])
+ msgx:+GameGFX.large.TextWidth(msg[0..1])
+ msg=msg[1..]+msg[0..1]
+ EndIf
+ End Method
+End Type
+
+Type TFadeScreen
+ Field a:Double
+ Field ai:Double
+
+ Function Create:TFadeScreen(a:Double, ai:Double)
+ Local o:TFadeScreen=New TFadeScreen
+ o.a=a
+ o.ai=ai
+ Return o
+ End Function
+
+ Function FadeOut:TFadeScreen()
+ Return Create(0,0.05)
+ End Function
+
+ Function FadeIn:TFadeScreen()
+ Return Create(1,-0.05)
+ End Function
+
+ Function DoFadeOut()
+ Local fade:TFadeScreen=TFadeScreen.FadeOut()
+ Local pm:TPixmap=GrabPixmap(0,0,GraphicsWidth(),GraphicsHeight())
+
+ While fade.Fade()
+ Cls
+ DrawPixmap(pm,0,0)
+ fade.Draw()
+ Flip
+ Wend
+ End Function
+
+ Method Fade:Int()
+ a:+ai
+ Return a>0 And a<1
+ End Method
+
+ Method Draw()
+ Local r:Int,g:Int,b:Int
+ Local oa:Double=GetAlpha()
+ GetColor(r,g,b)
+ SetAlpha(a)
+ SetColor(0,0,0)
+ DrawRect(0,0,GraphicsWidth(),GraphicsHeight())
+ SetColor(r,g,b)
+ SetAlpha(oa)
+ End Method
+End Type
+
+Type TGameBackdropStar
+ Field x:Double
+ Field y:Double
+ Field dy:Double
+ Field r:Int
+ Field g:Int
+ Field b:Int
+ Field frame:Int
+ Field cnt:Int
+
+ Method New()
+ x=Rnd(0,GraphicsWidth())
+ y=Rnd(0,GraphicsHeight())
+ dy=Rnd(0.1,2)
+ r=Rand(128,255)
+ g=Rand(128,255)
+ b=Rand(128,255)
+ frame=Rand(0,5)
+ cnt=5
+ End Method
+
+ Method Draw(anim:Int)
+ If anim
+ frame=(frame+1) Mod 6
+ EndIf
+
+ y:+dy
+ If y>GraphicsHeight()+8
+ y=-8
+ EndIf
+ SetColor(r,g,b)
+ DrawImage(GameGFX.bdropstar,x,y,frame)
+ End Method
+End Type
+
+
+Type TGameBackdrop
+ Field num:Int
+ Field star:TGameBackdropStar[]
+ Field cnt:Int
+
+ Method New()
+ num=100
+ star=New TGameBackdropStar[num]
+ cnt=5
+
+ For Local f:Int=0 Until num
+ star[f]=New TGameBackdropStar
+ Next
+ End Method
+
+ Method Draw()
+ For Local f:Int=0 Until num
+ star[f].Draw(cnt=0)
+ Next
+ cnt:-1
+ If cnt=-1
+ cnt=5
+ EndIf
+ End Method
+End Type
+
+
+Type Number
+ Function Format:String(num:Int)
+ Local c:Int=0
+ Local ret:String=""
+ Local a:String=String.FromInt(num)
+
+ For Local f:Int=a.length-1 To 0 Step -1
+ If ret.length And (c Mod 3)=0
+ ret=","+ret
+ EndIf
+ ret=a[f..f+1]+ret
+ c:+1
+ Next
+ Return ret
+ End Function
+End Type