This page demonstrates some code needed for a tetris clone that has more features such as: ability to end a game and start a new one, without exiting the program, ability to pause the game, ability to rotate pieces left OR right, ability to drop pieces instantly, the next piece is shown on-screen, ghost piece (for instant drop) is shown, animated line erase, simple animation displayed when player clears lines or levels up, uses some fancier looking blocks, background gridlines.

Start with setting up the graphics:
Graphics 800, 600 ;2D graphics at a resolution of 800x600 SetBuffer BackBuffer() ;do all drawing to the back drawing buffer
Seed the random number generator:
SeedRnd MilliSecs() ;needed to get random numbers
Dimension the arrays that you will need:
Dim Board(9, 22) ;10x20 game board (+3 rows above the board) Dim BlockColor(7, 2) ;stores r,g,b colors (0-2) for each of the 7 pieces Dim Piece(28, 3, 3) ;28 (4x4) piece descriptions (7 pieces in each of 4 rotations) Dim LineToErase(4) ;keeps track of which lines to erase (with animation)
Read in the color data for the pieces:
For iter = 1 To 7 ;loop through seven pieces Read BlockColor(iter, 0) ;read the red amount Read BlockColor(iter, 1) ;read the green amount Read BlockColor(iter, 2) ;read the blue amount Next Data 255, 255, 0;yellow ;color of square Data 0, 128, 255;turquoise ;color of line Data 0, 0, 255 ;blue ;color of left L Data 255, 128, 0;orange ;color of right L Data 255, 0, 0 ;red ;color of left s Data 0, 255, 0 ;green ;color of right s Data 128, 0, 255;purple ;color of tee
Read the piece descriptions into the description array:
For iter = 1 To 28 ;loop through 28 descriptions (7x4)
For yiter = 0 To 3 ;loop through the rows of the description
For xiter = 0 To 3 ;loop through the columns of the description
Read Piece(iter, xiter, yiter) ;read in the data (0=blank, 1=filled)
Next
Next ;example of right L 0100
Next ;as a 4x4 matrix 0100
;in its 90deg rotation 0110
;piece descriptions ;(right L rot 1) 0000
Data 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;square
Data 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 ;line
Data 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;left L
Data 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;right L
Data 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;left s
Data 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;right s
Data 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;tee up
;rotated 90 degrees cw
Data 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;square
Data 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0 ;line rot 1
Data 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ;left L rot 1
Data 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 ;right L rot 1
Data 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ;left s sideways
Data 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ;right s sideways
Data 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 ;tee right
;rotated 180 degrees cw
Data 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;square
Data 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0 ;line rot 2
Data 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 ;left L rot 2
Data 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 ;right L rot 2
Data 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;left s
Data 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;right s
Data 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 ;tee down
;rotated 270 degrees cw
Data 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ;square
Data 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 ;line rot 3
Data 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 ;left L rot 3
Data 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ;right L rot 3
Data 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ;left s sideways
Data 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ;right s sideways
Data 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 ;tee leftWe’ll set up some screen origins just so that we don’t have to offset all of our drawing commands.
Global OrigBoardX = 210 ;board origin Global OrigBoardY = 5 Global OrigLevelLinesX = 500 ;level & lines origin Global OrigLevelLinesY = 186 Global OrigNextPieceX = 600 ;next piece origin Global OrigNextPieceY = 75 Global OrigMessAreaX = 500 ;message area origin Global OrigMessAreaY = 300 Global OrigKeyMapX = 0 ;key mapping text origin Global OrigKeyMapY = 300
Next, we’ll type in these Global variables so that we can use them anywhere within the code: (notice that EndOfGame is being initialized as True)
Global Level ;current game level Global Lines ;number of lines remaining to clear to level up Global EndOfGame = True ;flag used to determine if a game is running or not Global CurrentPiece ;the current piece (1-7) that is falling Global CurPieceX ;the current pieces X position Global CurPieceY ;the Y position Global CurPieceRot ;the rotation (0-3) of the current piece Global NextPiece ;the next piece (1-7) that will fall Global GhostPieceY ;Y position of the Ghost piece Global RepeatSpeed ;time (milliseconds) between L or R keypresses Global RepeatDelay ;if true then makes delay between keypresses longer Global NowTime Global LastDropTime Global DropSpeed Global DropDelay Global GamePaused Global PauseTime Global NumLines Global ClearLines Global BlockToErase# Global Points Global PointColorFade Global LevelUpColorFade
And we need just a few more Globals to keep track of keypresses:
Global KeyEsc Global KeyPause Global KeyRotate Global KeyRotateLeft Global KeyLeft Global KeyRight Global KeyDwn Global KeyInstantDrop Global KeyN Global KeyQ
And now we’re ready to type in the Main loop:
Repeat
Cls
DrawBoard()
DrawInfo()
If GamePaused
DrawPauseMessage()
Else
DrawBoardBlocks()
DrawNextPiece()
If Not ClearLines
If Not EndOfGame Then DrawGhostPiece()
DrawCurrentPiece()
EndIf
EndIf
ProcessInputs()
If Not EndOfGame
If Not ClearLines
If Not GamePaused
If KeyDwn
DropDelay = 35
Else
DropDelay = DropSpeed
EndIf
NowTime = MilliSecs()
If (NowTime > LastDropTime + DropDelay) Or KeyInstantDrop
LastDropTime = NowTime
If Not DropPiece()
If Not PlacePiece()
EndGame()
EndIf
EndIf
EndIf
EndIf
Else
LineClearer()
EndIf
Else
PrintGameOver()
EndIf
Flip
Until KeyHit(1);Esc key
EndAnd now we can enter in each of the functions we’ll need. A function to handle player input:
Function ProcessInputs()
KeyEsc = KeyHit(1) ;Esc key
KeyPause = KeyHit(25) Or KeyHit(197) ;P key, Pause key
KeyRotate = KeyHit(57) Or KeyHit(45) ;spacebar, X key
KeyRotateLeft = KeyHit(44) ;Z key
KeyLeft = KeyDown(203) ;left key
KeyRight = KeyDown(205) ;right key
KeyDwn = KeyDown(208) ;down key
KeyInstantDrop = KeyHit(200) ;up key
KeyN = KeyHit(49) ;N key
KeyQ = KeyHit(16) ;Q key
If Not EndOfGame
If KeyRotate Then RotatePiece() ;space key or X key
If KeyRotateLeft Then RotatePiece(True); Z key
If (Not KeyLeft) And (Not KeyRight)
RepeatDelay = True
Else
If RepeatSpeed < NowTime
If RepeatDelay
RepeatSpeed = NowTime + 150
RepeatDelay = False
Else
RepeatSpeed = NowTime + 30
EndIf
If keyLeft Then MoveLeft()
If keyRight Then MoveRight()
EndIf
EndIf
If KeyInstantDrop Then CurPieceY = GhostPieceY
If KeyEsc Or KeyPause
If GamePaused
GamePaused = False
LastDropTime = LastDropTime + MilliSecs() - PauseTime
Else
GamePaused = True
PauseTime = MilliSecs()
EndIf
EndIf
If KeyQ Then EndGame() ;quit game
Else
If KeyN Then StartNewGame() ;new game
If KeyEsc Then End
EndIf
End FunctionUnfinished… Download it the full Source Code…

