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
|
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
