Quantcast TetrIves - eLua Wiki
Locked History Attachments

TetrIves

Information


Runs on: EK-LM3S8962, EK-LM3S6965

Description


Tetris doesn't need any introduction at all, so just start the game, grab the on-board switches and start making lines after lines on your OLED display. Once you're done playing, you might want to take a look at the code. This example is fairly complex, large, uses eLua specific techniques (explicit memory management with calls to the garbage collector) and might serve as a good base for your own code.

Videos


eLua Tetrives v1.0

Code

   1 -------------------------------------------------------------------------------
   2 --
   3 --          eLua Tetris Game
   4 --
   5 -- LED Lab @ PUC-Rio - 2009
   6 --   Dado Sutter
   7 --   Ives Negreiros
   8 --   Ricardo Rosa
   9 --   Pedro Bittencourt
  10 --   Rafael Barmak
  11 --   Teo Benjamin
  12 --
  13 -- Initial Version by Ives Negreiros, August 2009
  14 --
  15 ---------------------------------------------------------------------------------
  16 local Vmax = 22                        -- Number of pieces in vertical +1
  17 local Hmax = 12                        -- Number of pieces horizontally + 2
  18 local score = 0                        -- Player's score
  19 local highscore = 0                    -- Player's highscore
  20 local next_piece = 0                   -- Code for the next piece
  21 local PieceV = 0                       -- Vertical position of the piece
  22 local PieceH = 0                       -- Horizontal position of the piece
  23 local level = 1                        -- Level
  24 local rotate_type = 0                  -- Type of rotation for each piece
  25 local total_lines = 0                  -- Total number of lines made by player
  26 local seed = 0                         -- Variable used to make math.random return a diferent value each time
  27 local game_map = {}                    -- Table for the game map
  28 for i = 1, Vmax, 1 do
  29   game_map[ i ] = {}
  30 end
  31 
  32 -- Initial information
  33 local platform = require( pd.board() )
  34 lm3s.disp.init( 1000000 )
  35 
  36 lm3s.disp.print( "eLua Tetrives", 30, 10, 11 )
  37 lm3s.disp.print( "Press SELECT -->", 30, 40, 11 )
  38 while platform.btn_pressed( platform.BTN_SELECT ) == false do
  39   seed = seed + 1
  40 end
  41 
  42 math.randomseed( seed )
  43 lm3s.disp.clear()
  44 
  45 function scan_piece( next_piece )      -- This function selec the next piece based on return of math.random function
  46   if( next_piece == 1 ) then
  47     next_piece_map = { { 1, 1 }, { 1, 1 } }
  48     next_rotate_type = 0
  49 
  50   elseif( next_piece == 2 ) then
  51     next_piece_map = { { 1, 1, 0 }, { 0, 1, 1 }, { 0, 0, 0 } }
  52     next_rotate_type = 1
  53 
  54   elseif( next_piece == 3 ) then
  55     next_piece_map = { { 0, 1, 1 }, { 1, 1, 0 }, { 0, 0, 0 } }
  56     next_rotate_type = 1
  57 
  58   elseif( next_piece == 4 ) then
  59     next_piece_map = { { 0, 0, 1 }, { 1, 1, 1 }, { 0, 0, 0 } }
  60     next_rotate_type = 2
  61 
  62   elseif( next_piece == 5 ) then
  63     next_piece_map = { { 1, 0, 0 }, { 1, 1, 1 }, { 0, 0, 0 } }
  64     next_rotate_type = 2
  65 
  66   elseif( next_piece == 6 ) then
  67     next_piece_map = { { 0, 1, 0 }, { 1, 1, 1 }, { 0, 0, 0 } }
  68     next_rotate_type = 2
  69 
  70   elseif( next_piece == 7 ) then
  71     next_piece_map = { {0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }
  72     next_rotate_type = 4
  73   end
  74 end
  75 
  76 function draw_walls()                  -- This function draws the walls and the base of game piece screen
  77   for i = 6, 63, 3 do
  78     lm3s.disp.print( "|", 3, i, 11 )
  79   end
  80   for i = 3, 118, 4 do
  81 	lm3s.disp.print( "-", i, 2, 11 )
  82 	lm3s.disp.print( "-", i, 65, 11 )
  83   end
  84 end
  85 
  86 function sound()                       -- This function beeps
  87   pwm.start( 1 )
  88   tmr.delay( 0, 20000 )
  89   pwm.stop( 1 )
  90 end
  91 
  92 function print_data()                  -- This function writes the score and level on screen
  93   lm3s.disp.print( "Score:"..tostring( score ), 0, 88, 8 )
  94   lm3s.disp.print( "Level:"..tostring( level ), 0, 80, 8 )
  95 end
  96 
  97 function draw_piece()                  -- This function draws the piece on the screen
  98   for i in ipairs( piece_map ) do
  99     for j in ipairs( piece_map[ i ] ) do
 100       if( piece_map[ i ][ j ] == 1 ) then
 101         lm3s.disp.print( "*", ( PieceV + i - 1 ) * 6, ( PieceH + j - 1 ) * 6, 11 )
 102       end
 103     end
 104   end
 105 end
 106 
 107 function erase_piece()                 -- This function erases the piece on the screen
 108   for i in ipairs( piece_map ) do
 109     for j in ipairs( piece_map[ i ] ) do
 110       if( piece_map[ i ][ j ] == 1 ) then
 111         lm3s.disp.print( "*", ( PieceV + i - 1 ) * 6, ( PieceH + j - 1 ) * 6, 0 )
 112       end
 113     end
 114   end
 115 end
 116 
 117 function move_down()                   -- This function moves the piece down if there is no obstacle in the way, else create new piece
 118   free = 0                              -- It also test the lines (see function test_line for further explanation)
 119   for i in ipairs( piece_map ) do
 120     for j in ipairs( piece_map[ i ] ) do
 121       if( piece_map[ i ][ j ] == 1 ) then
 122         if( game_map[ PieceV + i - 1 ][ PieceH + j ] == 0 ) then
 123           free = free + 1
 124         end
 125       end
 126     end
 127   end
 128   if ( free == 4 ) then
 129     erase_piece()
 130     PieceV = PieceV - 1
 131     draw_piece()
 132   else
 133     for i in ipairs( piece_map ) do
 134       for j in ipairs( piece_map[ i ] ) do
 135         if( piece_map[ i ][ j ] == 1 ) then
 136           game_map[ PieceV + i ][ PieceH + j ] = 1
 137         end
 138       end
 139     end
 140     test_line()
 141     create_new_piece()
 142   end
 143 end
 144 
 145 function move_left()                   -- This function moves the piece left if there is no obstacle in the way
 146   free = 0
 147   for i in ipairs( piece_map ) do
 148     for j in ipairs( piece_map[ i ] ) do
 149       if( piece_map[ i ][ j ] == 1 ) then
 150         if( game_map[ PieceV + i ][ PieceH + j - 1 ] == 0 ) then
 151           free = free + 1
 152         end
 153       end
 154     end
 155   end
 156   if ( free == 4 ) then
 157     erase_piece()
 158     PieceH = PieceH - 1
 159     draw_piece()
 160   end
 161 end
 162 
 163 function move_right()                  -- This function moves the piece right if there is no obstacle in the way
 164   free = 0
 165   for i in ipairs( piece_map ) do
 166     for j in ipairs( piece_map[ i ] ) do
 167       if( piece_map[ i ][ j ] == 1 ) then
 168         if( game_map[ PieceV + i ][ PieceH + j + 1 ] == 0 ) then
 169           free = free + 1
 170         end
 171       end
 172     end
 173   end
 174   if ( free == 4 ) then
 175     erase_piece()
 176     PieceH = PieceH + 1
 177     draw_piece()
 178   end
 179 end
 180 
 181 function rotate()                      -- This function rotate the pieces
 182   piecerot = {}
 183   for i = 1, 4, 1 do
 184     piecerot[ i ] = {}
 185   end
 186   free = 0
 187   erase_piece()
 188   if ( rotate_type == 1 or rotate_type == 2 ) then
 189     for i in ipairs( piece_map ) do              -- this loop test if each part of piece can rotate
 190       for j in ipairs( piece_map[ i ] ) do
 191         if( piece_map[ i ][ j ] == 1 ) then
 192           if( game_map[ PieceV + j ][ 4 - i + PieceH ] == 0 ) then
 193             free = free + 1
 194           end
 195         end
 196       end
 197     end
 198     if( free == 4 ) then               -- If all the parts of piece can rotate, then 'free' will be equals to four
 199       if( rotate_type == 2 ) then
 200         rotate_type = 1
 201       end
 202       for i in ipairs( piece_map ) do            -- This loop rotates the piece
 203         for j in ipairs( piece_map[ i ] ) do
 204           piecerot[ i ][ j ] = piece_map[ j ][ 4 - i ]     -- This is the equation of the rotation function for this type of rotation
 205         end
 206       end
 207       piece_map = piecerot
 208     end
 209 
 210   elseif ( rotate_type == 3 ) then      -- This part works like the upper part, but for another type of rotation
 211     for i in ipairs( piece_map ) do
 212       for j in ipairs( piece_map[ i ] ) do
 213         if( piece_map[ i ][ j ] == 1 ) then
 214           if( game_map[ 4 - j + PieceV ][ PieceH + i ] == 0 ) then
 215             free = free + 1
 216           end
 217         end
 218       end
 219     end
 220     if( free == 4 ) then
 221       rotate_type =  2
 222       for i in ipairs( piece_map ) do
 223         for j in ipairs( piece_map[ i ] ) do
 224           piecerot[ i ][ j ] = piece_map[ 4 - j ][ i ]
 225         end
 226       end
 227       piece_map = piecerot
 228     end
 229 
 230   elseif ( rotate_type == 4 ) then     -- This part works like the upper part, but for another type of rotation
 231     for i in ipairs( piece_map ) do
 232       for j in ipairs( piece_map[ i ] ) do
 233         if( piece_map[ i ][ j ] == 1 ) then
 234           if( game_map[ PieceV + j ][ PieceH + i ] == 0 ) then
 235             free = free + 1
 236           end
 237         end
 238       end
 239     end
 240     if(free == 4 ) then
 241       for i in ipairs( piece_map ) do
 242         for j in ipairs( piece_map [ i ] ) do
 243           piecerot[ i ][ j ] = piece_map[ j ][ i ]
 244         end
 245       end
 246       piece_map = piecerot
 247     end
 248   end
 249   draw_piece()
 250   sound()
 251 end
 252 
 253 function remove_line( line )
 254   for i = line, Vmax - 2, 1 do
 255     for j = 2, Hmax - 1, 1 do
 256       lm3s.disp.print( "*", ( i - 1 ) * 6, ( j - 1 ) * 6, 0 )
 257       game_map[ i ][ j ] = game_map[ i + 1 ][ j ]
 258       if( game_map[ i ][ j ] == 1 ) then
 259         lm3s.disp.print( "*", ( i - 1 ) * 6, ( j - 1 ) * 6, 11 )
 260       end
 261     end
 262   end
 263 end
 264 
 265 function test_line()                   -- This function tests the lines, if there is a full line, then this
 266   lines = 0                            -- function removes this line and move down everything that is upper to it
 267   i = 2
 268   while ( i<Vmax ) do
 269     j = 2
 270     while ( j<Hmax ) do
 271       if( game_map[i][j] == 0 ) then
 272         break
 273       elseif( j == Hmax - 1 ) then
 274         remove_line( i )
 275         lines = lines + 1
 276         i = i - 1
 277         break
 278       end
 279       j = j + 1
 280     end
 281     i = i + 1
 282   end
 283   total_lines = total_lines + lines
 284   score = score + 100 * level * lines * lines    -- This is the euqation for the score value
 285   if( total_lines >= 8 and level < 4 ) then
 286     level = level + 1
 287     total_lines = 0
 288   end
 289 end
 290 
 291 function create_new_piece()            -- This Function creates a new piece
 292   piece_map = next_piece_map
 293   rotate_type = next_rotate_type
 294   PieceV = 18
 295   PieceH = 4
 296   next_piece = math.random( 7 )
 297   scan_piece ( next_piece )
 298   for i = 1, 2, 1 do
 299     for j = 1, 4, 1 do
 300       lm3s.disp.print( "*", 94 + ( j * 6 ), 78 + ( i * 6 ), 0 )
 301     end
 302   end
 303   for i in ipairs( next_piece_map ) do
 304     if( i == 3 ) then
 305       break
 306     end
 307     for j in ipairs( next_piece_map[ i ] ) do
 308       if( next_piece_map[ i ][ j ] == 1 ) then
 309         lm3s.disp.print( "*", 94 + ( j * 6 ), 78 + ( ( 3 - i ) * 6 ), 11 )
 310       end
 311     end
 312   end
 313   draw_piece()
 314 end
 315 
 316 ---------------------------------------------------------------------------------
 317 --																			   --
 318 --				                 MAIN LOOP							           --
 319 --																			   --
 320 ---------------------------------------------------------------------------------
 321 repeat
 322 
 323   for i in ipairs( game_map ) do       -- This loop create the border of game's map
 324     for j = 1, Hmax, 1 do
 325       if( j == 1 or j == Hmax or i == 1 or i == Vmax ) then
 326         game_map[ i ][ j ] = 1
 327       else
 328         game_map[ i ][ j ] = 0
 329       end
 330     end
 331   end
 332   level = 1                            -- This statements sets the level and score from the beginning
 333   score = 0
 334   pwm.setclock( 1, 25000000 )          -- This statements sets the PWM for the sound function
 335   pwm.setup( 1, 1000, 70 )
 336   draw_walls()
 337   next_piece = math.random(7)
 338   scan_piece ( next_piece )
 339   create_new_piece()
 340   collectgarbage( "collect" )
 341   while true do                        -- This loop refreshes the data and responds the player's input
 342     print_data ()
 343     Tmax = 11 - 2 * level              -- This statement raises the speed based on the level
 344     for i = 1, Tmax, 1 do
 345       if platform.btn_pressed( platform.BTN_UP ) then
 346         move_left()
 347       end
 348       if platform.btn_pressed( platform.BTN_DOWN ) then
 349         move_right()
 350       end
 351       if platform.btn_pressed( platform.BTN_RIGHT ) then
 352         rotate()
 353       end
 354       if platform.btn_pressed( platform.BTN_LEFT ) then   -- If the player presses "down", the piece drops instantly and a point is added to score
 355         score = score + 1
 356         tmr.delay( 1, 30000 )
 357         break
 358       end
 359       tmr.delay( 1, 70000 )
 360     end
 361     move_down()
 362     if( game_map[ PieceV + 2 ][ PieceH + 2 ] == 1 ) then   -- If this condition is true then game over
 363       break
 364     end
 365     collectgarbage( "collect" )
 366   end
 367 
 368   if score > highscore then
 369     highscore = score
 370   end
 371   lm3s.disp.clear()                         -- This statements displays the game over screen
 372   lm3s.disp.print( "Game Over :(", 30, 20, 11 )
 373   lm3s.disp.print( "Your score was "..tostring( score ), 0, 40, 11 )
 374   lm3s.disp.print( "Highscore: "..tostring( highscore ), 15, 50, 11 )
 375   lm3s.disp.print( "SELECT to restart", 6, 70, 11 )
 376   enough = true                        -- If the player presses select before the time reach 1000000ms, then restart the game
 377   for i=1, 1000000 do
 378     if platform.btn_pressed( platform.BTN_SELECT ) then
 379       enough = false
 380       break
 381     end
 382   end
 383   lm3s.disp.clear()
 384 until ( enough )
 385 lm3s.disp.off()
 386 

Files