RosettaCodeData/Task/Snake/Liberty-BASIC/snake.basic

192 lines
4.0 KiB
Plaintext

' ================================
' SIMPLE SNAKE GAME - Liberty BASIC
' ================================
' Graphics constants
global cellSize, gridWidth, gridHeight
global snakeLength, foodX, foodY, gamespeed
global gridOffsetY, score
cellSize = 20
gridWidth = 20
gridHeight = 20
gridOffsetY = 20
foodX = 0
foodY = 0
gamespeed = 333
score = 0
' Movement directions
global dirX, dirY
dirX = 1 : dirY = 0 ' start moving right
' Snake body array
dim snakeX(400)
dim snakeY(400)
snakeLength = 5
' Initialize snake position in center
for i = 1 to snakeLength
snakeX(i) = 10 - i
snakeY(i) = 10
next
' Create first food position
call newFood
' Open graphics window
WindowWidth = cellSize * gridWidth + 10
WindowHeight = cellSize * gridHeight + 60
open "SNAKE GAME - WASD to Move" for graphics_nsb_nf as #g
#g "trapclose [quit]"
#g "down; fill white; flush"
' Force focus
#g "setfocus"
' Enable character input
#g "when characterInput [keypress]"
' Start game timer
[startGame]
timer gamespeed, [gameTick]
wait
[gameTick]
' Move snake segments
for i = snakeLength to 2 step -1
snakeX(i) = snakeX(i-1)
snakeY(i) = snakeY(i-1)
next
' Head moves in current direction
snakeX(1) = snakeX(1) + dirX
snakeY(1) = snakeY(1) + dirY
' Wall collision ends game
if snakeX(1) < 0 or snakeX(1) >= gridWidth _
or snakeY(1) < 0 or snakeY(1) >= gridHeight then
call gameOver
wait
end if
' Check self collision
for i = 2 to snakeLength
if snakeX(1) = snakeX(i) and snakeY(1) = snakeY(i) then
call gameOver
wait
end if
next
' Check food collision
if snakeX(1) = foodX and snakeY(1) = foodY then
snakeLength = snakeLength + 1
score = score + 10
' Initialize new tail segment at same spot as previous tail
snakeX(snakeLength) = snakeX(snakeLength - 1)
snakeY(snakeLength) = snakeY(snakeLength - 1)
' Speed up the game
timer 0
gamespeed = max(gamespeed - 5, 150)
timer gamespeed, [gameTick]
call newFood
end if
call redraw
wait
[keypress]
key$ = Inkey$
key$ = lower$(key$)
select case key$
case "w"
if dirY <> 1 then dirX = 0 : dirY = -1
case "a"
if dirX <> 1 then dirX = -1 : dirY = 0
case "s"
if dirY <> -1 then dirX = 0 : dirY = 1
case "d"
if dirX <> -1 then dirX = 1 : dirY = 0
case chr$(27) ' ESC
call gameOver
wait
end select
wait
[quit]
close #g
end
sub redraw
' Clear screen
#g "cls"
' Draw top banner background
#g "color lightgray"
#g, "backcolor lightgray"
#g "place 0 0"
#g "boxfilled "; (gridWidth * cellSize); " "; gridOffsetY
' Draw banner text
#g "color black"
#g "font Courier_New 10"
#g "place 5 15"
#g "\"; "Score: "; score; " Speed: "; gamespeed; "ms"
' Draw food
call drawBlock foodX, foodY, "red"
' Draw snake
for i = 1 to snakeLength
call drawBlock snakeX(i), snakeY(i), "green"
next
#g "flush"
end sub
sub drawBlock x, y, color$
x1 = x * cellSize
y1 = gridOffsetY + y * cellSize
x2 = x1 + cellSize
y2 = y1 + cellSize
#g "color "; color$
#g, "backcolor "; color$
#g "place "; x1; " "; y1
#g "boxfilled "; x2; " "; y2
end sub
sub newFood
overlap = 1
while overlap = 1
foodX = int(rnd(0) * gridWidth)
foodY = int(rnd(0) * gridHeight)
overlap = 0
for i = 1 to snakeLength
if foodX = snakeX(i) and foodY = snakeY(i) then
overlap = 1
exit for
end if
next
wend
end sub
sub gameOver
timer 0
#g "cls"
#g "color black"
#g, "backcolor white"
#g "place 110 200"
#g "font Courier_New 24 bold"
#g "\"; "GAME OVER!"
#g "place 110 250"
#g "font Courier_New 16"
#g "\"; "Score: "; score
#g "flush"
end sub