summaryrefslogtreecommitdiff
path: root/gametypes.bmx
diff options
context:
space:
mode:
Diffstat (limited to 'gametypes.bmx')
-rw-r--r--gametypes.bmx478
1 files changed, 478 insertions, 0 deletions
diff --git a/gametypes.bmx b/gametypes.bmx
new file mode 100644
index 0000000..b12972b
--- /dev/null
+++ b/gametypes.bmx
@@ -0,0 +1,478 @@
+' Hardwire
+'
+' Copyright 2005 Ian Cowburn
+'
+' $Id$
+'
+Strict
+Import "types.bmx"
+Import "particle.bmx"
+Import "sounds.bmx"
+
+Type Pit
+ Const WIDTH=10
+ Const HEIGHT=14
+
+ Function X:Int(p:Int)
+ Return 230+p*32
+ End Function
+
+ Function Y:Int(p:Int)
+ Return 96+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 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]
+ rotleft=[0,2,1,5,3,6,4]
+
+ img=[GameGFX.cross,GameGFX.left_right,GameGFX.top_bottom,GameGFX.top_left,GameGFX.top_right,GameGFX.bottom_left,GameGFX.bottom_right]
+
+ ' CROSS LEFT_RIGHT TOP_BOTTOM TOP_LEFT TOP_RIGHT BOTTOM_LEFT BOTTOM_RIGHT
+ dir=[[DIR_UP,DIR_RIGHT,DIR_DOWN,DIR_LEFT], [DIR_NONE,DIR_RIGHT,DIR_NONE,DIR_LEFT], [DIR_UP,DIR_NONE,DIR_DOWN,DIR_NONE], [DIR_NONE,DIR_UP,DIR_LEFT,DIR_NONE], [DIR_NONE,DIR_NONE,DIR_RIGHT,DIR_UP], [DIR_LEFT,DIR_DOWN,DIR_NONE,DIR_NONE], [DIR_RIGHT,DIR_NONE,DIR_NONE,DIR_DOWN]]
+
+ 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"]
+ End Function
+
+ Method New()
+ t=Rand(0,6)
+ End Method
+
+ Function Create:TWire(t:Int)
+ Local o:TWire=New TWire
+ o.t=t
+ 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 TFallingBlock
+ Field w:TWire
+ Field x:Int
+ Field y:Double
+ Field yi:Double
+
+ Function Create:TFallingBlock(x:Int, y:Double)
+ Local o:TFallingBlock=New TFallingBlock
+ o.w=New TWire
+ o.x=x
+ o.y=y
+ o.yi=0
+ Return o
+ End Function
+
+ Method Update()
+ y:+yi
+ yi=Max(4.0,yi+0.1)
+ End Method
+
+ Method Draw()
+ SetColor(255,255,255)
+ DrawImage(GameGFX.tile,Pit.X(x),y)
+ SetColor(128,128,128)
+ DrawImage(w.Image(),Pit.X(x),y)
+ 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=Max(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
+End Type
+
+Type TGameMap
+ Field map:TWire[Pit.WIDTH,Pit.HEIGHT]
+ Field trode_col:Int
+ Field trode_coli:Int
+ Field overflow:Int
+ Field top:Int[Pit.WIDTH]
+ Field drop:TList
+ Field cx:Int
+ Field cy:Int
+ Field path:TList
+
+ Method New()
+ trode_col=0
+ trode_coli=1
+ overflow=False
+ drop=CreateList()
+ path=CreateList()
+ CalcTop()
+ cx=0
+ cy=Pit.HEIGHT-2
+ End Method
+
+ Method CalcTop()
+ For Local x:Int=0 Until Pit.WIDTH
+ top[x]=-1
+ For Local y:Int=Pit.Height-1 To 0 Step -1
+ If Not map[x,y]
+ top[x]=y
+ Exit
+ EndIf
+ Next
+ Next
+ End Method
+
+ Method AddRow(y:Int=-32)
+ If BlockInteract() Then Return
+
+ For Local x:Int=0 Until Pit.WIDTH
+ drop.AddLast(TFallingBlock.Create(x,y))
+ Next
+ End Method
+
+ Method BlockInteract:Int()
+ Return overflow Or path.Count()
+ 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
+ Return True
+ EndIf
+
+ Return FindLoop(l,ox,oy,x,y,dir)
+ End Method
+
+ Method CheckWires()
+ 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)
+ 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)
+ 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_LEFT)
+ path.AddLast(l)
+ EndIf
+ End Select
+ EndIf
+ Next
+ Next
+ End Method
+
+ Method CursorLeft()
+ If BlockInteract() Then Return
+ cx=Max(0,cx-1)
+ End Method
+
+ Method CursorRight()
+ If BlockInteract() Then Return
+ cx=Min(Pit.WIDTH-2,cx+1)
+ End Method
+
+ Method CursorUp()
+ If BlockInteract() Then Return
+ cy=Max(0,cy-1)
+ End Method
+
+ Method CursorDown()
+ If BlockInteract() Then Return
+ cy=Min(Pit.HEIGHT-2,cy+1)
+ End Method
+
+ Method Rotate()
+ If BlockInteract() Then Return
+ Local done:Int=False
+ For Local x:Int=0 To 1
+ For Local y:Int=0 To 1
+ If map[cx+x,cy+y]
+ map[cx+x,cy+y].RotateRight()
+ done=True
+ EndIf
+ Next
+ Next
+
+ If done
+ Sound.Click()
+ EndIf
+
+ CheckWires()
+ 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(128,128,128)
+ DrawImage(map[x,y].Image(),Pit.X(x),Pit.Y(y))
+ EndIf
+ Next
+ Next
+
+ If BlockInteract()
+ For Local b:TFallingBlock=EachIn drop
+ b.Draw()
+ Next
+
+ 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
+ For Local y:Int=e.y To 1 Step -1
+ map[e.x,y]=map[e.x,y-1]
+ Next
+ map[e.x,0]=Null
+ Particles.AddDust(Pit.X(e.x)+16,Pit.Y(e.y)+32)
+ check=True
+ Next
+ EndIf
+ l.Remove()
+ EndIf
+ Wend
+
+ If check
+ Sound.Path()
+ CalcTop()
+ CheckWires()
+ EndIf
+ Else
+ Local hit:Int=False
+
+ Local l:TEasyLink=TEasyLink.Create(drop)
+
+ While l.Value()
+ Local b:TFallingBlock=TFallingBlock(l.Value())
+ Local t:Int=Pit.Y(top[b.x])'-ImageHeight(GameGFX.tile)
+
+ b.Update()
+
+ If b.y>t
+ If top[b.x]=-1
+ overflow=True
+ b.y=t
+ l.MoveNext()
+ Else
+ hit=True
+ map[b.x,top[b.x]]=b.w
+ Particles.AddDust(Pit.X(b.x)+16,Pit.Y(top[b.x])+32)
+ l.Remove()
+ EndIf
+ Else
+ b.Draw()
+ l.MoveNext()
+ EndIf
+ Wend
+
+ If hit And Not overflow
+ Sound.Click()
+ CheckWires()
+ CalcTop()
+ EndIf
+ EndIf
+
+ SetColor(trode_col,trode_col,0)
+ DrawImage(GameGFX.cursor,Pit.X(cx),Pit.Y(cy))
+
+ 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