The following code uses GPIO buttons 1, 2, 3, 4 for controls. It will work on any BrightSign model that has a video output and a GPIO port.
REM REM The game of Snake REM demonstrates BrightScript programming concepts REM June 22, 2008 REM REM Every BrightScript program must have a single Main() REM Sub Main() game_board=newGameBoard() While true game_board.SetSnake(newSnake(game_board.StartX(), game_board.StartY())) game_board.Draw() game_board.EventLoop() if game_board.GameOver() then ExitWhile End While End Sub REM ******************************************************* REM ******************************************************* REM *************** ********************* REM *************** GAME BOARD OBJECT ********************* REM *************** ********************* REM ******************************************************* REM ******************************************************* REM REM An example BrightScript constructor. "newGameBoard()" is regular Function of module scope REM BrightScript Objects are "dynamic" and created at runtime. They have no "class". REM The object container is a BrightScript Component of type roAssocitiveArray (AA). REM The AA is used to hold member data and member functions. REM Function newGameBoard() As Object game_board=CreateObject("roAssociativeArray") ' Create a BrightScript Component of type/class roAssociativeArray game_board.Init=gbInit ' Add an entry to the AA of type roFunction with value gbDraw (a sub defined in this module) game_board.Draw=gbDraw game_board.SetSnake=gbSetSnake game_board.EventLoop=gbEventLoop game_board.GameOver=gbGameOver game_board.StartX=gbStartX game_board.StartY=gbStartY game_board.Init() ' Call the Init member function (which is gbInit) return game_board End Function REM REM gbInit() is a member function of the game_board BrightScript Object. REM When it is called, the "this" pointer "m" is set to the appropriate instance by REM the BrightScript bytecode interpreter REM Function gbInit() As Void REM REM button presses go to this message port REM m.buttons = CreateObject("roMessagePort") m.gpio = CreateObject("roGpioControlPort") m.gpio.SetPort(m.buttons) REM REM determine optimal size and position for the snake gameboard REM CELLWID=16 ' each cell on game in pixels width CELLHI=16 ' each cell in pix height MAXWIDE=30 ' max width (in cells) of game board MAXHI=30 ' max height (in cells) of game board vidmode=CreateObject("roVideoMode") w=cint(vidmode.GetResX()/CELLWID) if w>MAXWIDE then w = MAXWIDE h=cint(vidmode.GetResY()/CELLHI) if h>MAXHI then h=MAXHI xpix = cint((vidmode.GetResX() - w*CELLWID)/2) ' center game board on screen ypix = cint((vidmode.GetResY() - h*CELLHI)/2) ' center game board on screen REM REM Create Text Field with square char cell size REM meta=CreateObject("roAssociativeArray") meta.AddReplace("CharWidth",CELLWID) meta.AddReplace("CharHeight",CELLHI) meta.AddReplace("BackgroundColor",&H202020) 'very dark grey meta.AddReplace("TextColor",&H00FF00) ' Green m.text_field=CreateObject("roTextField",xpix,ypix,w,h,meta) if type(m.text_field)<>"roTextField" then print "unable to create roTextField 1" stop endif End Function REM REM As Object refers to type BrightScript Component REM m the "this" pointer REM Sub gbSetSnake(snake As Object) m.snake=snake End Sub Function gbStartX() As Integer return cint(m.text_field.GetWidth()/2) End Function Function gbStartY() As Integer return cint(m.text_field.GetHeight()/2) End Function Function gbEventLoop() As Void tick_count=0 while true msg=wait(250, m.buttons) ' wait for a button, or 250ms (1/4 a second) timeout if type(msg)="roGpioButton" then if msg.GetInt()=1 m.snake.TurnNorth() if msg.GetInt()=2 m.snake.TurnSouth() if msg.GetInt()=3 m.snake.TurnEast() if msg.GetInt()=4 m.snake.TurnWest() else 'here if time out happened, move snake forward tick_count=tick_count+1 if tick_count=6 then tick_count=0 if m.snake.MakeLonger(m.text_field) then return else if m.snake.MoveForward(m.text_field) then return endif endif end while End Function Sub gbDraw() REM REM given a roTextField Object in "m.text_field", draw a box around its edge REM solid=191 ' use asc("*") if graphics not enabled m.text_field.Cls() for w=0 to m.text_field.GetWidth()-1 print #m.text_field,@w,chr(solid); print #m.text_field,@m.text_field.GetWidth()*(m.text_field.GetHeight()-1)+w,chr(solid); end for for h=1 to m.text_field.GetHeight()-2 print #m.text_field,@h*m.text_field.GetWidth(),chr(solid); print #m.text_field,@h*m.text_field.GetWidth()+m.text_field.GetWidth()-1,chr(solid); end for m.snake.Draw(m.text_field) End Sub Function gbGameOver() As Boolean msg$= " G A M E O V E R " msg0$=" " width = m.text_field.GetWidth() height = m.text_field.GetHeight() while true print #m.text_field,@width*(height/2-1)+(width-len(msg$))/2,msg$; sleep(300) print #m.text_field,@width*(height/2-1)+(width-len(msg$))/2,msg0$; sleep(150) REM GetMessage returns the message object, or an int 0 if no message available If m.buttons.GetMessage() <> invalid Then Return False endwhile End Function REM ******************************************************* REM ******************************************************* REM ****************** *********************** REM ****************** SNAKE OBJECT *********************** REM ****************** *********************** REM ******************************************************* REM ******************************************************* REM REM construct a new snake BrightScript object REM Function newSnake(x As Integer, y As Integer) As Object ' Create AA BrightScript Component; the container for a "BrightScript Object" snake=CreateObject("roAssociativeArray") snake.Draw=snkDraw snake.TurnNorth=snkTurnNorth snake.TurnSouth=snkTurnSouth snake.TurnEast=snkTurnEast snake.TurnWest=snkTurnWest snake.MoveForward=snkMoveForward snake.MakeLonger=snkMakeLonger snake.AddSegment=snkAddSegment snake.EraseEndBit=snkEraseEndBit REM REM a "snake" is a list of line segments REM a line segment is an roAssociativeArray that conains a length and direction (given by the x,y delta needed to move as it is drawn) REM snake.seg_list = CreateObject("roList") snake.AddSegment(1,0,3) REM REM The X,Y pos is the position of the head of the snake REM snake.snake_X=x snake.snake_Y=y snake.body=191 ' use asc("*") if graphics not enabled. snake.dx=1 ' default snake direction / move offset snake.dy=0 ' default snake direction / move offset return snake End Function Sub snkDraw(text_field As Object) x=m.snake_X y=m.snake_Y for each seg in m.seg_list xdelta=seg.xDelta ydelta=seg.yDelta for j=1 to seg.Len text_field.SetCursorPos(x, y) text_field.SendByte(m.body) x=x+xdelta y=y+ydelta end for end for End Sub Sub snkEraseEndBit(text_field As Object) x=m.snake_X y=m.snake_Y for each seg in m.seg_list x=x+seg.Len*seg.xDelta y=y+seg.Len*seg.yDelta end for text_field.SetCursorPos(x, y) text_field.SendByte(32) ' 32 is ascii space, could use asc(" ") End Sub Function snkMoveForward(text_field As Object)As Boolean m.EraseEndBit(text_field) tail=m.seg_list.GetTail() REM REM the following shows how you can use an AA's member functions to perform the same REM functions the BrightScript . operator does behind the scenes for you (when used on an AA). REM there is not point to this longer method other than illustration REM len=tail.Lookup("Len") ' same as len = tail.Len (or tail.len, BrightScript syntax is not case sensative) len = len-1 if len=0 then m.seg_list.RemoveTail() else tail.AddReplace("Len",len) ' same as tail.Len=len endif return m.MakeLonger(text_field) End Function Function snkMakeLonger(text_field As Object) As Boolean m.snake_X=m.snake_X+m.dx m.snake_Y=m.snake_Y+m.dy text_field.SetCursorPos(m.snake_X, m.snake_Y) if text_field.GetValue()=m.body then return true text_field.SendByte(m.body) head = m.seg_list.GetHead() head.Len=head.Len+1 return false End Function Sub snkAddSegment(dx As Integer, dy As Integer, len as Integer) aa=CreateObject("roAssociativeArray") aa.AddReplace("xDelta",-dx) ' line segments draw from head to tail aa.AddReplace("yDelta",-dy) aa.AddReplace("Len",len) m.seg_list.AddHead(aa) End Sub Sub snkTurnNorth() if m.dx<>0 or m.dy<>-1 then m.dx=0:m.dy=-1:m.AddSegment(m.dx, m.dy, 0) 'north End Sub Sub snkTurnSouth() if m.dx<>0 or m.dy<>1 then m.dx=0:m.dy=1:m.AddSegment(m.dx, m.dy, 0) 'south End Sub Sub snkTurnEast() if m.dx<>-1 or m.dy<>0 then m.dx=-1:m.dy=0:m.AddSegment(m.dx, m.dy, 0) 'east End Sub Sub snkTurnWest() if m.dx<>1 or m.dy<>0 then m.dx=1:m.dy=0:m.AddSegment(m.dx, m.dy, 0) 'west End Sub