Quantcast Pong - eLua Wiki
Locked History Attachments

Pong

Information


Runs on: EK-LM3S8962, EK-LM3S6965

eLua Libs Used: EK-LM3S89(...), disp

Description


A tribute to the classics, as well as an addictive way of spending your time, this examples proves without any doubt that you can write games with eLua. This variant of the well known "pong" games plays on the OLED display of your LM3S board, using the on-board switches to control your paddle. Hit the ball, collect or avoid the "bonuses", a keep on trying to beat that highscore :) The code is just complex enough to give you a fair idea about the possibilities of eLua.

Videos


Pictures


foto_pong.jpg

eLua Pong v1.0

Code

   1 -------------------------------------------------------------------------------
   2 --
   3 --		eLua Pong Game
   4 --
   5 -- LED Lab @ PUC-Rio - 2009
   6 --   Dado Sutter
   7 --   Ives Negreiros
   8 --   Ricardo Rosa
   9 --   Pedro Bittencourt
  10 --   Teo Benjamin
  11 --
  12 
  13 -- Initial Version by Dado Sutter, Fev 2009
  14 --    This had only the ball bouncing on walls, paddle and paddle movement
  15 --
  16 -- Greatly enhanced by Teo Benjamin in Aug/Sep 2009, adding:
  17 --    Score, resizeable paddles, levels/speeds, items
  18 --
  19 --
  20 -------------------------------------------------------------------------------
  21 
  22 local canvas = {}
  23 -- canvas.x                     -- Horizontal display size
  24 -- canvas.y                     -- Vertical display size
  25 
  26 local paddle = {}
  27 -- paddle.size                  -- Actual Paddle size = ( 6 * ( paddle.size + 1 ) ) + 2
  28 -- paddle.max_size              -- Max paddle.size value -> Constant
  29 -- paddle.min_size              -- Min paddle.size value -> Constant
  30 -- paddle.y                            -- Paddle's Y position ( X position not needed, always 0 )
  31 
  32 local ball = {}
  33 -- ball.x                       -- Ball's X position
  34 -- ball.y                       -- Ball's Y position -> starts at a random position
  35 -- ball.dx                      -- Ball's X movement ( 1 = moving right; -1 = moving left )
  36 -- ball.dy                      -- Ball's Y movement ( 1 = moving down; -1 = moving up )
  37 -- ball.char                    -- The char that is printed for the ball -> Constant
  38 
  39 local item = {}
  40 -- item.x                       -- Item's X position
  41 -- item.y                       -- Item's Y position ( fix for each item )
  42 -- item.char                    -- This is the char that represents the item ( if false, there is no item )
  43 -- item.all_chars                     -- A table that contains all the possibles item chars. Initialized by upload_items() function
  44 
  45 -- Define all constants
  46 local tmr_id = 1
  47 paddle.max_size = 4
  48 paddle.min_size = 0
  49 ball.char = "*"
  50 local delay_incr = 2000
  51 
  52 
  53 -- Define all "global" variables as program local ones.
  54 -- The values are initialized at the main loop.
  55 
  56 local score                    -- Player's score
  57 local dscore                   -- How many points for each paddle hit
  58 local delay_time               -- This value is used for the main delay, to make the game speed faster or slower
  59 local paddle_hits              -- Counts the number of hits on paddle
  60 local highscore                -- Current Highscore
  61 
  62 item.all_chars = {}
  63 local pressed = {}             -- pressed[ button ] is true if the corresponding button was pressed, or nil if not
  64 
  65 local kit = require( pd.board() )  -- This variable is used as a pin assignments for the specific board
  66 
  67 local itemFunction = {
  68 ["L"] = function ()
  69     draw_paddle( paddle.y, 0, 0 )
  70     if paddle.size < paddle.max_size then
  71       paddle.size = paddle.size + 1
  72     end
  73     draw_paddle( paddle.y, 11, 0 )
  74   end,
  75 ["S"] = function ()
  76     draw_paddle( paddle.y, 0, 0 )
  77     if paddle.size > paddle.min_size then
  78       paddle.size = paddle.size - 1
  79     end
  80     draw_paddle( paddle.y, 11, 0 )
  81   end,
  82 
  83 ["?"] = function ()
  84     item.char = item.all_chars[ math.random( #item.all_chars ) ]
  85     use_item()
  86   end,
  87 
  88 ["*"] = function ()
  89   end,
  90 
  91 ["P"] = function ()
  92     score = score + dscore
  93   end,
  94 
  95 ["D"] = function ()
  96     score = score * 2
  97   end,
  98 
  99 ["Z"] = function ()
 100     lm3s.disp.print( tostring( score ), 111, 89, 0 )
 101     score = 0
 102   end,
 103 
 104 ["T"] = function ()
 105     lm3s.disp.print( ball.char, ball.x, ball.y, 0 )
 106     ball.y = math.random( 82 )
 107     lm3s.disp.print( ball.char, ball.x, ball.y, 15 )
 108   end,
 109 ["F"] = function()
 110     if delay_time >= 1000 then
 111       delay_time = delay_time - 1000
 112     end
 113   end,
 114 }
 115 
 116 -- Updates Y paddle position and draw it using the draw_paddle( ... ) function
 117 function update_paddle_pos()
 118   if kit.btn_pressed( kit.BTN_UP ) then
 119     if ( paddle.y > 0 ) then
 120       paddle.y = paddle.y - 1
 121       draw_paddle( paddle.y, 11, -1 )
 122     else
 123       tmr.delay( 1, 1700 )
 124     end
 125   elseif kit.btn_pressed( kit.BTN_DOWN ) then
 126     if ( paddle.y + ( paddle.size*6 ) + 1 < 90 ) then
 127       paddle.y = paddle.y + 1
 128       draw_paddle( paddle.y, 11, 1 )
 129     else
 130       tmr.delay( 1, 1600 )
 131     end
 132   else
 133     draw_paddle( paddle.y, 11, 0 )
 134     tmr.delay( 1, 300 ) -- Maintain function processing time aprox the same
 135   end
 136 end
 137 
 138 -- Draw the paddle in the display. This function is used by update_paddle_pos() function
 139 function draw_paddle( y, color, movement )
 140   if ( movement == 0 ) then
 141     for i = 0, paddle.size, 1 do
 142       lm3s.disp.print( "|", 0, y + ( i * 6 ),  color )
 143     end
 144   elseif ( movement > 0 ) then      -- Paddle moving Down
 145     if y < 8 then
 146       lm3s.disp.print( "|", 0, 0,  0 )
 147     else
 148       lm3s.disp.print( "|", 0, y - 8 , 0 )
 149     end
 150     for i = 0, paddle.size, 1 do
 151       lm3s.disp.print( "|", 0, y + ( i * 6 ),  color )
 152     end
 153   elseif ( movement < 0 ) then    -- Paddle moving Up
 154     lm3s.disp.print( "|", 0, y + ( ( paddle.size + 1 ) * 6 ) + 2 , 0 )
 155     for i = 0, paddle.size, 1 do
 156       lm3s.disp.print( "|", 0, y + ( i * 6 ),  color )
 157     end
 158   end
 159 end
 160 
 161 -- Updates the ( X, Y ) ball position and prints the corresponding char
 162 function update_ball_pos()
 163   if( ( ball.x + 5 >= canvas.x ) or ( ball.x <= 4 ) ) then
 164     ball.dx = -ball.dx;
 165     if ball.dx == -1 and item.char == false then
 166       createItem()
 167     end
 168   end
 169   if( ( ball.y >= 90 - ball.dy ) or ( ball.y <= 1 - ball.dy ) ) then
 170     ball.dy = -ball.dy;
 171   end
 172   lm3s.disp.print( ball.char, ball.x, ball.y, 0 )
 173   ball.x, ball.y = ( ball.x + ball.dx ), ( ball.y + ball.dy );
 174   lm3s.disp.print( ball.char, ball.x, ball.y, 15 )
 175 end
 176 
 177 
 178 -- Draw the top wall and erase the last one. Used to move it
 179 function draw_wall( x )
 180   for i = 0, canvas.y, 7 do                    -- Erase the wall
 181     lm3s.disp.print( "|", canvas.x + 1, i, 0 )
 182   end
 183   canvas.x = x
 184   for i = 0, canvas.y, 7 do                    -- Draw a new wall
 185     lm3s.disp.print( "|", canvas.x + 1, i, 6 )
 186   end
 187 end
 188 
 189 -- Item Functions
 190 function createItem()
 191   item.char = item.all_chars[ math.random( #item.all_chars ) ]
 192   item.x = canvas.x - 10
 193   item.y = ball.y
 194 end
 195 
 196 -- Upload the itens from table itemFunction into the table item.all_chars
 197 -- Must be used to initialize the items
 198 function upload_items()
 199   for k,v in pairs( itemFunction ) do
 200     table.insert( item.all_chars, k )
 201   end
 202 end
 203 
 204 -- Updates the item X position
 205 function update_item_pos()
 206   if item.char then
 207     if ( item.x <= 4 ) then
 208       if ( ( item.y + 8 < paddle.y ) or ( item.y > paddle.y + ( paddle.size * 6 ) + 8 ) ) == false then
 209         use_item()
 210       end
 211       lm3s.disp.print( item.char, item.x, item.y, 0 )
 212       item.char = false
 213       return
 214     end
 215     lm3s.disp.print( item.char, item.x, item.y, 0 )
 216     item.x = item.x - 2
 217     lm3s.disp.print( item.char, item.x, item.y, 10 )
 218   end
 219 end
 220 
 221 -- Uses the item's function
 222 function use_item()
 223   itemFunction[ item.char ]()
 224 end
 225 
 226 -- Checks if a button was clicked ( pressed and released )
 227 -- Returns true or false
 228 function button_clicked( button )
 229   if kit.btn_pressed( button ) then
 230     pressed[ button ] = true
 231   else
 232     if pressed[ button ] then
 233       pressed[ button ] = nil
 234       return true
 235     end
 236     pressed[ button ] = nil
 237   end
 238   return false
 239 end
 240 
 241 ------------ MAIN ------------
 242 upload_items()
 243 lm3s.disp.init( 1000000 )
 244 
 245 tmr.start( tmr_id )
 246 --menu()
 247 math.randomseed( tmr.read( tmr_id ) )    -- If you use the menu function, the time will be used as a seed to the random function
 248 --tmr.stop( tmr_id )
 249 
 250 collectgarbage( "collect" )
 251 
 252 
 253 
 254 
 255 
 256 ---------------------------------------------------------------------------------------------------------
 257 ---------------------------------------------------------------------------------------------------------
 258 --                                                                                                     --
 259 --                                        GAME START                                                   --
 260 --                                                                                                     --
 261 ---------------------------------------------------------------------------------------------------------
 262 ---------------------------------------------------------------------------------------------------------
 263 
 264 repeat
 265   canvas.x = 124
 266   canvas.y = 97
 267   ball.x = 5
 268   ball.y = math.random( ( canvas.y - 8 ) / 2 ) + ( canvas.y / 4 )
 269   ball.dx = 1
 270   ball.dy = 1
 271   paddle.y = ball.y - 4
 272   item.x = 0
 273   item.y = 0
 274   score = 0
 275   dscore = 1
 276   item.char = false
 277   paddle.size = 2
 278   delay_time = 10000
 279   paddle_hits = 0
 280 
 281   lm3s.disp.clear()
 282 
 283   draw_wall( canvas.x )
 284   draw_paddle( paddle.y, 11, 0 )
 285 
 286   while ( true ) do
 287     for i = 0, 1 do
 288       update_paddle_pos()
 289     end
 290     tmr.delay ( 0, delay_time )
 291     update_ball_pos()
 292     update_item_pos()
 293     if ( ball.x <= 4 ) then
 294       if ( ( ball.y + 8 < paddle.y ) or ( ball.y > paddle.y + ( paddle.size * 6 ) + 8 ) ) then  -- If this is true, you lose
 295         break
 296     else                                                                     -- Else, you score
 297         score = score + dscore
 298         paddle_hits = paddle_hits + 1
 299       end
 300     end
 301 
 302     if button_clicked( kit.BTN_RIGHT ) and delay_time > 0 then   -- If the right button is clicked, increase the level
 303       delay_time = delay_time - delay_incr
 304       dscore = dscore + 1
 305     end
 306     if button_clicked( kit.BTN_LEFT ) and dscore > 0 then    -- If the left button is clicked, decrease the level
 307       delay_time = delay_time + delay_incr
 308       dscore = dscore - 1
 309     end
 310 
 311     if ( paddle_hits == 5 ) and canvas.x > 80 then  -- After 5 hits in a row, move the wall until canvas.x = 80
 312       paddle_hits = 0
 313       draw_wall( canvas.x - 5 )
 314     end
 315     lm3s.disp.print( tostring( dscore ), 118, 0, 6 )
 316     lm3s.disp.print( tostring( score ), 111, 89, 6 )
 317     collectgarbage( "collect" )
 318   end
 319 -------------------------------------------
 320 -- Game Over
 321 -------------------------------------------
 322   if score >= ( highscore or 0 ) then
 323     highscore = score
 324   end
 325   lm3s.disp.clear()
 326   lm3s.disp.print( "Game Over :(", 30, 20, 11 )
 327   lm3s.disp.print( "Your score was "..tostring( score ), 15, 40, 11 )
 328   lm3s.disp.print( "Highscore: "..tostring( highscore ), 15, 50, 11 )
 329   lm3s.disp.print( "SELECT to restart", 6, 70, 11 )
 330   enough = true
 331   for i=1, 100000 do
 332     if kit.btn_pressed( kit.BTN_SELECT ) then
 333       enough = false
 334       break
 335     end
 336   end
 337 until ( enough )
 338 
 339 lm3s.disp.off()
 340 

Files