;
; Snake:
; The Game you've Seen a Thousand Times
; Rehashed Again!
;
; Daniel Demski
; ; To Do:
; -powerups: --tailscatter(extrafood), --stop food movement, Faster(bigger), Kill Enemies,
; Smaller, GoThroughBarriers, Blockades-To-Food, power-down(the Un-powerup)
; -enemies start out longer when your score is higher
; -enemies create blockades
; -enemies pay more attention to your location at higher point levels
; -Different types of enemies: blockadeers, what else?
; -Snakes colliding head-on should both die
; -Hi-score saved
; X-Make food pieces bounce off of each other
; -make powerups fade away instead of just dissappear
; -make messages fade rather than dissappear
; -make a sound when you get a powerup
; -make a main menu, with choice between 1p and 2p modes,graphics modes,sound,possibly game options
; -limited number of lives, after which board resets (in 1p) or you can't restart (in 2p)
AppTitle "Snake"
Global width=800, height=600
Graphics width, height
ClsColor 0,100,80
Global font=LoadFont (Arial,64,True,False,False)
Global small=LoadFont (Arial,14,False,False,True)
SetBuffer FrontBuffer()
SetFont font: Color 0,200,100:Text width/2,height/3,"Loading...",True,True
Color 0,200,100: Rect 100,width/2,50,40: Delay 100;;;
Global end_sound = LoadSound("Ship_exp.wav")
Global eat_sound = LoadSound("eat.wav")
Global en_eat_sound = eat_sound
Global powerup_eat_sound = eat_sound
Global gamemusic = LoadSound("whatever.wav")
Global pausemusic = LoadSound("pause.wav")
Color 0,200,100: Rect 100,width/2,78,40: Delay 100;;;
LoopSound (gamemusic)
LoopSound (pausemusic)
PlaySound (gamemusic)
Color 0,200,100: Rect 100,width/2,156,40,1: Delay 100;;;
Global p1head= CreateImage (10,10)
Global p2head= CreateImage (10,10)
Global enhead= CreateImage (10,10)
Global p1body= CreateImage (10,10)
Global p2body= CreateImage (10,10)
Global enbody= CreateImage (7,7)
Global piece= CreateImage (10,10)
Global xpiece= CreateImage (8,8)
Global buffer= CreateImage (1,1)
Global power= CreateImage (10,10)
Global p1ate=0,p2ate=0
Global p1direction = 5
Global p1dicertion = 5
Global p2direction = 5
Global p2dicertion = 5
Global p1gamestate = -1
Global p2gamestate = -1
Global p1stateflag = 1
Global p2stateflag = 1
Global p1message$
Global p2message$
Global p1messagetimer=0
Global p2messagetimer=0
Global p1points = 0
Global p2points = 0
Global time = MilliSecs()
Global tick = MilliSecs()
SeedRnd MilliSecs()
SetBuffer FrontBuffer():Color 0,200,100: Rect 100,width/2,234,40,1: Delay 100;;;
SetBuffer ImageBuffer(p1body)
Color 0,255,100: Oval 1,1,8,8,1
SetBuffer FrontBuffer():Color 0,200,100: Rect 100,width/2,301,40,1: Delay 100;;;
SetBuffer ImageBuffer(p2body)
Color 255,255,0: Oval 1,1,8,8,1
SetBuffer ImageBuffer(enbody)
Color 150,0,255: Oval 1,1,5,5,1
Color 113,0,192: Oval 1,1,5,5,0
SetBuffer FrontBuffer():Color 0,200,100: Rect 100,width/2,379,40,1: Delay 100;;;
SetBuffer ImageBuffer(p1head)
Color 150,255,100: Oval 0,0,10,10,1
SetBuffer FrontBuffer():Color 0,200,100: Rect 100,width/2,415,40,1: Delay 100;;;
SetBuffer ImageBuffer(p2head)
Color 255,225,100: Oval 0,0,10,10,1
SetBuffer ImageBuffer(enhead)
Color 150,100,255: Oval 0,0,7,7,1
Color 113,75,192: Oval 0,0,7,7,0
SetBuffer FrontBuffer():Color 0,200,100: Rect 100,width/2,472,40,1: Delay 100;;;
SetBuffer ImageBuffer(piece)
Color 120,200,0: Oval 0,0,10,10,1; 117,50,0 ; 0,150,75
Color 90,150,0: Oval 0,0,10,10,0
SetBuffer FrontBuffer():Color 0,200,100: Rect 100,width/2,540,40,1: Delay 100;;;
SetBuffer ImageBuffer(xpiece)
Color 120,200,0: Oval 0,0,8,8,1
Color 90,150,0: Oval 0,0,8,8,0
SetBuffer FrontBuffer():Color 0,200,100: Rect 100,width/2,568,40,1: Delay 100;;;
SetBuffer ImageBuffer(power)
Color 200,50,50: Oval 0,0,10,10,1
Color 255,64,64: Oval 0,0,10,10,0
SetBuffer FrontBuffer():Color 0,200,100: Rect 100,width/2,582,40,1: Delay 100;;;
SetBuffer BackBuffer()
Type p1snake
Field x,y
End Type
Type p2snake
Field x,y
End Type
Dim ensnake(500)
Type enemy
Field ate
Field snake.ensnake
Field direction, dicertion
Field gamestate
Field thoughts
Field pattern
Field apple.food
End Type
Type ensnake
Field x,y
Field frst.ensnake,lst.ensnake,bfr.ensnake,aftr.ensnake
End Type
Type powerup
Field x,y,time
Field power
Field activated
Field targ1.p1snake
Field targ2.p2snake
Field targf.food
Field targx.xfood
End Type
Global numpowers=2
Global currpower=Rand(1,numpowers)
Type food
Field x#,y#
Field speed#,direction,friction#
Field xmod,ymod
End Type
Global maxspeed = 9
Type xfood
Field x#,y#
Field speed#,direction,friction#
Field xmod,ymod
End Type
seed()
Function seed()
p1reset()
p1reset()
p2reset()
p2reset()
For c=1 To 12
Food.food= New food
Food\x#=Rnd(0,width-10)
Food\y#=Rnd(0,height-10)
Food\speed#=0
Food\direction=0
Food\xmod=1
Food\ymod=1
Next
End Function
Function p1reset()
p1Snake.p1snake = New p1snake
p1Snake\x=0
p1Snake\y=0
p1Snake.p1snake = New p1snake
p1Snake\x=10
p1Snake\y=10
p1Snake.p1snake = New p1snake
p1Snake\x=20
p1Snake\y=20
p1Snake.p1snake = New p1snake
p1Snake\x=30
p1Snake\y=30
p1Snake.p1snake = New p1snake
p1Snake\x=40
p1Snake\y=40
p1direction=5
p1dicertion=5
p1stateflag=1
p1gamestate=0
p1points=75
End Function
Function p2reset()
p2Snake.p2snake = New p2snake
p2Snake\x=width-10
p2Snake\y=height-10
p2Snake.p2snake = New p2snake
p2Snake\x=width-20
p2Snake\y=height-20
p2Snake.p2snake = New p2snake
p2Snake\x=width-30
p2Snake\y=height-30
p2Snake.p2snake = New p2snake
p2Snake\x=width-40
p2Snake\y=height-40
p2Snake.p2snake = New p2snake
p2Snake\x=width-50
p2Snake\y=height-50
p2direction=5
p2dicertion=5
p2stateflag=1
p2gamestate=0
p2points=75
End Function
Delay 100
While Not KeyHit(1); normal game mode
.unpaused
If KeyHit(197)
Goto paused
EndIf
If KeyHit(18)
createEnemy()
EndIf
; If ChannelPlaying (pausemusic)
; StopChannel (pausemusic)
; PlaySound (gamemusic)
; EndIf
Cls
SetFont font
Color 0,200,0: Text (width/2),(height/3),p1points,True,True
Color 200,200,0: Text (width/2),(2*(height/3)),p2points,True,True
If p1messagetimer>0
SetFont font: Color 0,200,0: Text (width/2),(height/5),p1message,True,True
p1messagetimer=p1messagetimer-1
EndIf
If p2messagetimer>0
SetFont font: Color 200,200,0: Text (width/2),(4*(height/5)),p2message,True,True
p2messagetimer=p2messagetimer-1
EndIf
If p1gamestate=1
SetFont small:Color 0,200,0: Text (width/2),(height/5+39),"PRESS ENTER TO RESTART",True,False
EndIf
If p2gamestate=1
SetFont small:Color 200,200,0:Text (width/2),(4*(height/5)+39),"PRESS ENTER TO RESTART",True,False
EndIf
If ( MilliSecs()-time>350 And KeyDown(57)=False ) Or ( MilliSecs()-time>35 And KeyDown(57)=True )
CheckKeys()
Updatep1Snake()
Updatep2Snake()
UpdateEnemy()
time=MilliSecs()
If p1gamestate=0 Then p1points=p1points-1
If p2gamestate=0 Then p2points=p2points-1
EndIf
If ( MilliSecs()-tick>30 And KeyDown(57)=False ) Or ( MilliSecs()-tick>3 And KeyDown(57)=True )
UpdateFood()
UpdateFoodEatenp1()
UpdateFoodEatenp2()
UpdateFoodEatenEn()
tick=MilliSecs()
EndIf
If p1points<1 Then p1gamestate=1: p1message="Ha! You Starved!": p1messagetimer=1000
If p2points<1 Then p2gamestate=1: p2message="Ha! You Starved!": p2messagetimer=1000
If KeyDown(59) Then p1points=p1points+100; cheat
Check1()
Check2()
UpdatePowerups()
DrawFood()
Drawp1Snake()
Drawp2Snake()
DrawEnemy()
DrawPowerups()
Flip
Wend
While Not KeyHit(1); Paused game mode
.paused
If KeyHit(197)
Goto unpaused
EndIf
; If ChannelPlaying (gamemusic)
; StopChannel (gamemusic)
; PlaySound (pausemusic)
; EndIf
SetFont font: Color 200,0,0: Text (width/2),(height/2),"The Game is Paused!",True,True
SetFont small: Text (width/2),(height/2+32),"PRESS 'PAUSE' KEY TO CONTINUE",True,False
Text (width/2),(height/2+46),"OR 'ESC' TO EXIT",True,False
Flip
If KeyHit(28); cheat
p1reset()
p2reset()
EndIf
Wend
Function Check1()
If p1gamestate = 1
If p1stateflag=1
PlaySound(end_sound)
p1stateflag=0
For a.p1snake=Each p1snake
Delete a
Next
EndIf
If KeyHit(28)
p1reset()
p1reset()
EndIf
EndIf
End Function
Function Check2()
If p2gamestate = 1
If p2stateflag=1
PlaySound(end_sound)
p2stateflag=0
For b.p2snake=Each p2snake
Delete b
Next
EndIf
If KeyHit(28)
p2reset()
p2reset()
EndIf
EndIf
End Function
Function CheckKeys()
If KeyHit(200) And p1dicertion<>3Then p1direction=1
If KeyHit(205) And p1dicertion<>4Then p1direction=2
If KeyHit(208) And p1dicertion<>1Then p1direction=3
If KeyHit(203) And p1dicertion<>2Then p1direction=4
If KeyHit(17) And p2dicertion<>3Then p2direction=1
If KeyHit(32) And p2dicertion<>4Then p2direction=2
If KeyHit(31) And p2dicertion<>1Then p2direction=3
If KeyHit(30) And p2dicertion<>2Then p2direction=4
End Function
Function Updatep1Snake()
If p1gamestate=0
; Get the last snake's position
p1Snake.p1snake=Last p1snake
X=p1Snake\x
Y=p1Snake\y
; Move over one unit in current direction
Select p1direction
Case 1 Y=Y-10: p1dicertion=1
Case 2 X=X+10: p1dicertion=2
Case 3 Y=Y+10: p1dicertion=3
Case 4 X=X-10: p1dicertion=4
Case 5 X=X+10:Y=Y+10
End Select
; Create head
p1Snake.p1snake=New p1snake
p1Snake\x=X
p1Snake\y=Y
h.p1snake=Last p1snake
; gameover if head exits 'map'
If h\x<0 Or h\x>(width-10) Or h\y<0 Or h\y>(height-10)
p1gamestate = 1: p1message= "Ha! You Went Off the Edge!": p1messagetimer=1000
EndIf
; gameover if head overlaps with body
h=Before h
.p1 Repeat
If ImagesOverlap (p1head,X,Y,p1body,h\x,h\y)
p1gamestate = 1: p1message= "Ha! You Ran Into Yourself!": p1messagetimer=1000
EndIf
h=Before h
Until h=Null
; gameover if you collide with the other guy
h.p1snake=Last p1snake
For e.p2snake=Each p2snake
If ImagesOverlap(p1head,h\x,h\y,p2body,e\x,e\y)
p1gamestate = 1: p1message= "Ha! You Ran into Yellow!": p1messagetimer=1000
EndIf
Next
; powerups
For pow.powerup=Each powerup
If ImagesOverlap (p1head,h\x,h\y,power,pow\x,pow\y)
; Select pow\power
; Case 1
; h.p1snake=First p1snake
; If h<>Last p1snake
; Repeat
; xf.xfood=New xfood
; xf\x#=h\x
; xf\y#=h\y
; xf\speed=Rnd(3,maxspeed)
; xf\direction=Rnd(0,359)
; xf\xmod=1
; xf\ymod=1
; Delete h
; h=After h
; Until h=Last p1snake
; EndIf
; Case 2
; For f.food=Each food
; f\speed=0
; Next
; End Select
; Delete pow
pow\activated=1
EndIf
h.p1snake=Last p1snake
Next
updatefoodeatenp1()
; continue if it doesn't run into food and it hasn't collided with an obstruction yet
If p1gamestate = 0 And p1ate<=0
h.p1snake=First p1snake
If h<>Last p1snake Then Delete h
Else p1ate=p1ate-1
EndIf
EndIf
End Function
Function Updatep2Snake()
If p2gamestate=0
; Get the last snake's position
p2Snake.p2snake=Last p2snake
X=p2Snake\x
Y=p2Snake\y
; Move over one unit in current direction
Select p2direction
Case 1 Y=Y-10: p2dicertion=1
Case 2 X=X+10: p2dicertion=2
Case 3 Y=Y+10: p2dicertion=3
Case 4 X=X-10: p2dicertion=4
Case 5 X=X-10:Y=Y-10
End Select
; Create head
p2Snake.p2snake=New p2snake
p2Snake\x=X
p2Snake\y=Y
h.p2snake=Last p2snake
; gameover if head exits 'map'
If h\x<0 Or h\x>(width-10) Or h\y<0 Or h\y>(height-10)
p2gamestate = 1: p2message= "Ha! You Went Off the Edge!": p2messagetimer=1000
EndIf
; gameover if head overlaps with body
h=Before h
.p2 Repeat
If ImagesOverlap (p2head,X,Y,p2body,h\x,h\y)
p2gamestate = 1: p2message= "Ha! You Ran Into Yourself!": p2messagetimer=1000
EndIf
h=Before h
Until h=Null
; gameover if you collide with the other guy
h.p2snake=Last p2snake
For e.p1snake=Each p1snake
If ImagesOverlap(p2head,h\x,h\y,p1body,e\x,e\y)
p2gamestate = 1: p2message= "Ha! You Ran into Green!": p2messagetimer=1000
EndIf
Next
; powerups
For pow.powerup=Each powerup
If ImagesOverlap (p2head,h\x,h\y,power,pow\x,pow\y)
; Select pow\power
; Case 1
; h.p2snake=First p2snake
; If h<>Last p2snake
; Repeat
; xf.xfood=New xfood
; xf\x#=h\x
; xf\y#=h\y
; xf\speed=Rnd(3,maxspeed)
; xf\direction=Rnd(0,359)
; xf\xmod=1
; xf\ymod=1
; Delete h
; h=After h
; Until h=Last p2snake
; EndIf
; Case 2
; For f.food=Each food
; f\speed=0
; Next
; End Select
; Delete pow
pow\activated=2
EndIf
h.p2snake=Last p2snake
Next
updatefoodeatenp2()
; continue if it doesn't run into food and it hasn't collided with an obstruction yet
If p2gamestate = 0 And p2ate<=0
h.p2snake=First p2snake
If h<>Last p2snake Then Delete h
Else p2ate=p2ate-1
EndIf
EndIf
End Function
Function CreateEnemy()
e.enemy=New enemy
e\ate=10
e\snake=New ensnake
e\snake\x=(20)
e\snake\y=Rand(height-10)
e\snake\frst=e\snake
e\snake\lst=e\snake
e\snake\bfr=Null
e\snake\aftr=Null
e\direction=2
e\dicertion=2
e\gamestate=0
e\thoughts=Rand(0,3)
e\pattern=Rand(0,2)
End Function
Function UpdateEnemy()
For e.enemy=Each enemy
MoveEnemy(e)
UpdateFoodEatenEn()
If e\ate>0
e\ate = e\ate-1
Else
of.ensnake=e\snake\frst
nf.ensnake=of\aftr
Delete of
n.ensnake=nf\aftr
While Not n=Null
n\frst=nf
n=n\aftr
Wend
EndIf
Next
End Function
Function MoveEnemy(e.enemy)
; e\dicertion=e\direction
; e\direction=2; A really simple AI that doesn't even count as one right now, for testing purposes only.
Select pattern
Case 0; Goes either towards the food nearest player or the food nearest it; complex alg.
rating=200000
; choicef.food=Null
p1.p1snake=Last p1snake
p2.p2snake=Last p2snake
For f.food=Each food
dex=f\x-e\snake\x
If dex<0 Then dex=dex*-1
dey=f\y-e\snake\y
If dey<0 Then dey=dey*-1
diste=dex+dey
If p1gamestate=0
dp1x=f\x-p1\x
If dp1x<0 Then dp1x=dp1x*-1
dp1y=f\y-p1\y
If dp1y<0 Then dp1y=dp1y*-1
distp1=dp1x+dp1y
Else
distp1=1500
EndIf
If p2gamestate=0
dp2x=f\x-p2\x
If dp2x<0 Then dp2x=dp2x*-1
dp2y=f\y-p2\y
If dp2y<0 Then dp2y=dp2y*-1
distp2=dp2x+dp2y
Else
distp2=1500
EndIf
If distp1>distp2
distp=distp1
who=1
Else
distp=distp2
who=2
EndIf
If p1points>p2points Then score=p1points Else score=p2points
If p1gamestate=0
dep1x=p1\x-e\snake\x
If dep1x<0 Then dep1x=dep1x*-1
dep1y=p1\y-e\snake\y
If dep1y<0 Then dep1y=dep1y*-1
dep1=dep1x+dep1y
Else
dep1=1500
EndIf
If p2gamestate=0
dep2x=p2\x-e\snake\x
If dep2x<0 Then dep2x=dep2x*-1
dep2y=p2\y-e\snake\y
If dep2y<0 Then dep2y=dep2y*-1
dep2=dep2x+dep2y
Else
dep2=1500
EndIf
If who=1 Then dep=dep1 Else dep=dep2
dp#=distp*(score/dep) ; number in parens is how many times bigger the score
;has To be than the dist. between e and p For dp# To be
de#=diste*(4) ;more important than de#.
thisrating=dp+de
If thisrating<rating
rating=thisrating
e\apple.food=f
EndIf
Next
Case 1; go towards nearest food
dist=1500
For f.food=Each food
dex=f\x-e\snake\x
If dex<0 Then dex=dex*-1
dey=f\y-e\snake\y
If dey<0 Then dey=dey*-1
diste=dex+dey
If diste<dist
dist=diste
e\apple.food=f
EndIf
Next
Case 2; go towards the food closest to Player
p1.p1snake=Last p1snake
p2.p2snake=Last p2snake
dist=1500
For f.food=Each food
If p1gamestate=0
dex=f\x-p1\x
If dex<0 Then dex=dex*-1
dey=f\y-p1\y
If dey<0 Then dey=dey*-1
distep1=dex+dey
Else
distep1=1500
EndIf
If p2gamestate=0
dex=f\x-p1\x
If dex<0 Then dex=dex*-1
dey=f\y-p1\y
If dey<0 Then dey=dey*-1
distep1=dex+dey
Else
distep2=1500
EndIf
If distep1>distep2 Then diste=distep1 Else diste=distep2
If diste<dist
dist=diste
e\apple.food=f
EndIf
Next
End Select
difx=e\apple\x-e\snake\x
dify=e\apple\y-e\snake\y
If difx<0 Then afx=difx*-1 Else afx=difx
If dify<0 Then afy=dify*-1 Else afy=dify
; The four 'approach' styles
Select e\thoughts
Case 0; 'Oblique' approach
If afx>afy And difx>0 And dify>0 Then e\direction=2
If afx<afy And difx>0 And dify>0 Then e\direction=3
If afx>afy And difx<0 And dify>0 Then e\direction=4
If afx<afy And difx<0 And dify>0 Then e\direction=3
If afx>afy And difx>0 And dify<0 Then e\direction=2
If afx<afy And difx>0 And dify<0 Then e\direction=1
If afx>afy And difx<0 And dify<0 Then e\direction=4
If afx<afy And difx<0 And dify<0 Then e\direction=1
Case 1; 'Horizontal' approach
If afx>5
If difx>0 Then e\direction=2 Else e\direction=4
Else
If dify>0 Then e\direction=3 Else e\direction=1
EndIf
Case 2; 'Vertical' approach
If afy>5
If dify>0 Then e\direction=3 Else e\direction=1
Else
If difx>0 Then e\direction=2 Else e\direction=4
EndIf
Case 3; 'Random' approach
If Rand(0,1)=True
If dify>0 Then e\direction=3 Else e\direction=1
Else
If difx>0 Then e\direction=2 Else e\direction=4
EndIf
End Select
; actual movement- doesn't include deleting tail, just creating head.
X=e\snake\x
Y=e\snake\y
Select e\direction; Turn this normal again sometime, won't you?
Case 1
If dicertion<>1
Y=Y-7: dicertion=3
Else
X=X+7: dicertion=4
EndIf
Case 2
If dicertion<>2
X=X+7: dicertion=4
Else
Y=Y+7: dicertion=1
EndIf
Case 3
If dicertion<>3
Y=Y+7: dicertion=1
Else
X=X-7: dicertion=2
EndIf
Case 4
If dicertion<>4
X=X-7: dicertion=2
Else
Y=Y-7: dicertion=3
EndIf
End Select
h.ensnake=New ensnake
h\x=X
h\y=Y
h\bfr=e\snake
h\aftr=Null
h\frst=e\snake\frst
h\lst=h
e\snake=h
o.ensnake=e\snake\frst
While o\aftr<>Null
o\lst=h
o=o\aftr
Wend
o\aftr=h
o\lst=h
If KeyHit(14)
error.xfood=New xfood
Delete error
speed=error\speed ; --an attempt at making me be able to crash the program when I desire
EndIf
End Function
Function DrawEnemy()
For e.enemy=Each enemy
DrawImage enhead,e\snake\x,e\snake\y
en.ensnake=e\snake\Bfr
While en<>Null
DrawImage enbody,en\x,en\y
en=en\bfr
Wend
Next
End Function
Function UpdateFoodEatenp1()
If p1gamestate<1
h.p1snake=Last p1snake
For f.food=Each food
If ImagesCollide(p1head,h\x,h\y,0,piece,f\x#,f\y#,0)
p1ate=p1ate+1: p1points=p1points+25
PlaySound(eat_sound)
MoveFood(f)
EndIf
Next
For xf.xfood=Each xfood
If ImagesCollide(p1head,h\x,h\y,0,xpiece,xf\x#,xf\y#,0)
p1ate=p1ate+1
1points=p1points+10
PlaySound(eat_sound)
Delete xf
EndIf
Next
EndIf
End Function
Function UpdateFoodEatenp2()
If p2gamestate<1
h.p2snake=Last p2snake
For f.food=Each food
If ImagesCollide(p2head,h\x,h\y,0,piece,f\x#,f\y#,0)
p2ate=p2ate+1: p2points=p2points+25
PlaySound(eat_sound)
MoveFood(f)
EndIf
Next
For xf.xfood=Each xfood
If ImagesCollide(p2head,h\x,h\y,0,xpiece,xf\x#,xf\y#,0)
p2ate=p2ate+1: p2points=p2points+10
PlaySound(eat_sound)
Delete xf
EndIf
Next
EndIf
End Function
Function UpdateFoodEatenEn()
For e.enemy=Each enemy
If e\gamestate<1
For f.food=Each food
If ImagesCollide(enhead,e\snake\x,e\snake\y,0,piece,f\x#,f\y#,0)
e\ate=e\ate+1
PlaySound(en_eat_sound)
MoveFood(f)
EndIf
Next
For xf.xfood=Each xfood
If ImagesCollide(enhead,e\snake\x,e\snake\y,0,xpiece,xf\x#,xf\y#,0)
e\ate=e\ate+1
PlaySound(en_eat_sound)
Delete xf
EndIf
Next
EndIf
Next
End Function
Function Drawp1Snake()
If p1gamestate=0
; Draw snake
For b.p1snake=Each p1snake
If b<>Last p1snake Then DrawImage p1body,b\x,b\y
Next
h.p1snake=Last p1snake
DrawImage p1head,h\x,h\y
EndIf
End Function
Function Drawp2Snake()
If p2gamestate=0
; Draw snake
For b.p2snake=Each p2snake
If b<>Last p2snake Then DrawImage p2body,b\x,b\y
Next
h.p2snake=Last p2snake
DrawImage p2head,h\x,h\y
EndIf
End Function
Function UpdateFood()
For f.food=Each food
; move
f\x#=(f\x#+f\xmod*(Cos(f\direction)*f\speed#))
f\y#=(f\y#+f\ymod*(Sin(f\direction)*f\speed#))
;decelerate
f\speed=f\speed*f\friction
;bounce off walls
If f\x#<0 Or f\x#>(width-10)
f\xmod=f\xmod*(-1)
EndIf
If f\y#<0 Or f\y#>(height-10)
f\ymod=f\ymod*(-1)
EndIf
; bounce off snakes
one=False
two=False
three=False
four=False
For b.p1snake=Each p1snake
If ImagesOverlap (p1body,b\x,b\y,piece,f\x#,f\y#) And (b<>Last p1snake)
If ImagesOverlap(p1body,b\x,b\y,buffer,f\x#,f\y#) Then one=True
If ImagesOverlap(p1body,b\x,b\y,buffer,f\x#+10,f\y#) Then two=True
If ImagesOverlap(p1body,b\x,b\y,buffer,f\x#,f\y#+10) Then three=True
If ImagesOverlap(p1body,b\x,b\y,buffer,f\x#+10,f\y#+10) Then four=True
EndIf
Next
For d.p2snake=Each p2snake
If ImagesOverlap (p2body,d\x,d\y,piece,f\x#,f\y#)
If ImagesOverlap(p2body,d\x,d\y,buffer,f\x#,f\y#) Then one=True
If ImagesOverlap(p2body,d\x,d\y,buffer,f\x#+10,f\y#) Then two=True
If ImagesOverlap(p2body,d\x,d\y,buffer,f\x#,f\y#+10) Then three=True
If ImagesOverlap(p2body,d\x,d\y,buffer,f\x#+10,f\y#+10) Then four=True
EndIf
Next
If (one=True And two=True) Or (three=True And four=True)
f\yMod=f\yMod*(-1)
f\x#=(f\x#+f\xmod*(Cos(f\direction)*f\speed#))
f\y#=(f\y#+f\ymod*(Sin(f\direction)*f\speed#))
Else If (one=True And three=True) Or (two=True And four=True)
f\xMod=f\xMod*(-1)
f\x#=(f\x#+f\xmod*(Cos(f\direction)*f\speed#))
f\y#=(f\y#+f\ymod*(Sin(f\direction)*f\speed#))
Else If (one = True)
f\xMod=f\xMod*(-1)
f\yMod=f\yMod*(-1)
f\x#=(f\x#+f\xmod*(Cos(f\direction)*f\speed#))
f\y#=(f\y#+f\ymod*(Sin(f\direction)*f\speed#))
Else If (two = True)
f\xMod=f\xMod*(-1)
f\yMod=f\yMod*(-1)
f\x#=(f\x#+f\xmod*(Cos(f\direction)*f\speed#))
f\y#=(f\y#+f\ymod*(Sin(f\direction)*f\speed#))
Else If (three = True)
f\xMod=f\xMod*(-1)
f\yMod=f\yMod*(-1)
f\x#=(f\x#+f\xmod*(Cos(f\direction)*f\speed#))
f\y#=(f\y#+f\ymod*(Sin(f\direction)*f\speed#))
Else If (four = True)
f\xMod=f\xMod*(-1)
f\yMod=f\yMod*(-1)
f\x#=(f\x#+f\xmod*(Cos(f\direction)*f\speed#))
f\y#=(f\y#+f\ymod*(Sin(f\direction)*f\speed#))
EndIf
Next
For x.xfood=Each xfood
x\x#=(x\x#+x\xmod*(Cos(x\direction)*x\speed#))
x\y#=(x\y#+x\ymod*(Sin(x\direction)*x\speed#))
;decelerate
x\speed=x\speed*x\friction
; If x\speed>0
; x\speed=x\speed*0.965
; Else x\speed=0
; EndIf
If x\x#<0 Or x\x#>(width-10)
x\xmod=x\xmod*(-1)
EndIf
If x\y#<0 Or x\y#>(height-10)
x\ymod=x\ymod*(-1)
EndIf
one=False
two=False
three=False
four=False
For b.p1snake=Each p1snake
If ImagesOverlap (p1body,b\x,b\y,piece,x\x#,x\y#)
If ImagesOverlap(p1body,b\x,b\y,buffer,x\x#,x\y#) Then one=True
If ImagesOverlap(p1body,b\x,b\y,buffer,x\x#+10,x\y#) Then two=True
If ImagesOverlap(p1body,b\x,b\y,buffer,x\x#,x\y#+10) Then three=True
If ImagesOverlap(p1body,b\x,b\y,buffer,x\x#+10,x\y#+10) Then four=True
EndIf
Next
For d.p2snake=Each p2snake
If ImagesOverlap (p2body,d\x,d\y,piece,x\x#,x\y#)
If ImagesOverlap(p2body,d\x,d\y,buffer,x\x#,x\y#) Then one=True
If ImagesOverlap(p2body,d\x,d\y,buffer,x\x#+10,x\y#) Then two=True
If ImagesOverlap(p2body,d\x,d\y,buffer,x\x#,x\y#+10) Then three=True
If ImagesOverlap(p2body,d\x,d\y,buffer,x\x#+10,x\y#+10) Then four=True
EndIf
Next
If (one=True And two=True) Or (three=True And four=True)
x\yMod=x\yMod*(-1)
x\x#=(x\x#+x\xmod*(Cos(x\direction)*x\speed#))
x\y#=(x\y#+x\ymod*(Sin(x\direction)*x\speed#))
Else If (one=True And three=True) Or (two=True And four=True)
x\xMod=x\xMod*(-1)
x\x#=(x\x#+x\xmod*(Cos(x\direction)*x\speed#))
x\y#=(x\y#+x\ymod*(Sin(x\direction)*x\speed#))
Else If (one = True)
x\xMod=x\xMod*(-1)
x\yMod=x\yMod*(-1)
x\x#=(x\x#+x\xmod*(Cos(x\direction)*x\speed#))
x\y#=(x\y#+x\ymod*(Sin(x\direction)*x\speed#))
Else If (two = True)
x\xMod=x\xMod*(-1)
x\yMod=x\yMod*(-1)
x\x#=(x\x#+x\xmod*(Cos(x\direction)*x\speed#))
x\y#=(x\y#+x\ymod*(Sin(x\direction)*x\speed#))
Else If (three = True)
x\xMod=x\xMod*(-1)
x\yMod=x\yMod*(-1)
x\x#=(x\x#+x\xmod*(Cos(x\direction)*x\speed#))
x\y#=(x\y#+x\ymod*(Sin(x\direction)*x\speed#))
Else If (four = True)
x\xMod=x\xMod*(-1)
x\yMod=x\yMod*(-1)
x\x#=(x\x#+x\xmod*(Cos(x\direction)*x\speed#))
x\y#=(x\y#+x\ymod*(Sin(x\direction)*x\speed#))
EndIf
Next
End Function
Function DrawFood()
For f.food=Each food
DrawImage piece,f\x#,f\y#
DrawImage buffer,f\x,f\y#
DrawImage buffer,f\x#+10,f\y#
DrawImage buffer,f\x#,f\y#+10
DrawImage buffer,f\x#+10,f\y#+10
Next
For x.xfood=Each xfood
DrawImage xpiece,x\x#,x\y#
DrawImage buffer,x\x,x\y#
DrawImage buffer,x\x#+10,x\y#
DrawImage buffer,x\x#,x\y#+10
DrawImage buffer,x\x#+10,x\y#+10
Next
End Function
Function MoveFood(f.food)
Repeat
f\x#=Rnd(0,width-10)
f\y#=Rnd(0,height-10)
p1snakethere=False
For b.p1snake=Each p1snake
If ImagesOverlap (piece,f\x#,f\y#,p1body,b\x,b\y) And b<>Last p1snake
p1snakethere=True
EndIf
Next
p2snakethere=False
For d.p2snake=Each p2snake
If ImagesOverlap (piece,f\x#,f\y#,p1body,d\x,d\y) And d<>Last p2snake
p2snakethere=True
EndIf
Next
Until (p1snakethere=False And p2snakethere=False)
If p1points>p2points Then mark#=p1points
If p2points>p1points Then mark#=p2points
If p1points=p2points Then mark#=p1points
f\speed#=(Rnd(0,mark#/150)/5)
If f\speed#>maxspeed Then f\speed#=maxspeed
f\direction=Rnd(0,359)
f\xmod=1
f\ymod=1
f\friction=1
End Function
Function CreatePowerup()
pow.powerup=New powerup
pow\x=Rnd(0,width-10)
pow\y=Rnd(0,height-10)
pow\power=currpower
i=currpower
Repeat
currpower=Rnd(1,numpowers)
Until i<>currpower
pow\activated=0
pow\time=Rand(1000,2000)
End Function
Function UpdatePowerups()
For p.powerup=Each powerup
If p\activated>0
Select p\power
Case 1
Select p\activated
Case 1
If p1messagetimer=0
p1message="You lost your tail!"
p1messagetimer=600
EndIf
targ1.p1snake=First p1snake
If targ1<>Last p1snake And targ1<>Null
xf.xfood=New xfood
xf\x#=targ1\x: xf\y#=targ1\y
xf\speed#=Rnd(3,maxspeed)
xf\direction=Rand(0,359)
xf\xmod=1: xf\ymod=1
xf\friction=0.965
Delete targ1
Else
Delete p
EndIf
Case 2
If p2messagetimer=0
p2message="You lost your tail!"
p2messagetimer=600
EndIf
targ2.p2snake=First p2snake
If targ2<>Last p2snake And targ2<>Null
xf.xfood=New xfood
xf\x#=targ2\x: xf\y#=targ2\y
xf\speed#=Rnd(3,maxspeed)
xf\direction=Rand(0,359)
xf\xmod=1: xf\ymod=1
xf\friction=0.965
Delete targ2
Else
Delete p
EndIf
End Select
Case 2
For targf.food=Each food
targf\friction=0.965
Select p\activated
Case 1
p1message="Food stopped moving!"
p1messagetimer=600
Case 2
p2message="Food stopped moving!"
p2messagetimer=600
End Select
Next
Delete p
End Select
Else
If p\time>0 Then p\time=p\time-1 Else Delete p
EndIf
Next
End Function
Function DrawPowerups()
For p.powerup=Each powerup
If p\activated=0
DrawImage power,p\x,p\y
EndIf
Next
End Function
Function EventTimer()
If p1points>p2points Then score=p1points
If p2points>p1points Then score=p2points
If p1points=p2points Then score=Rand(p1points,p2points)
If score>10000 Then score=10000
score=score*2
If (Rand(score,22222)>22220) And (Last powerup=Null)
CreatePowerup()
EndIf
End Function