diff options
author | William Wilgus <me.theuser@yahoo.com> | 2018-10-17 18:35:02 -0400 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2018-11-05 00:30:46 -0500 |
commit | 85079483c5595c2a04774ae9fbf529719eaec9fa (patch) | |
tree | bc57bf5d59bff3c03afa4b06949b39ed48f90e34 | |
parent | d9f9def505b367b9361ba96d33e6edf1687716fb (diff) | |
download | rockbox-85079483c5595c2a04774ae9fbf529719eaec9fa.tar.gz rockbox-85079483c5595c2a04774ae9fbf529719eaec9fa.zip |
Lua Boomshine Update with circles + levels
added a few more levels and increased difficulty based on level
Rliimage allows us to use circles in boomshine
Optimized some of the code to exceed the speed of the original
Change-Id: I68eb74f8b68fcdc8a9d022cd172374744425f15d
-rw-r--r-- | apps/plugins/boomshine.lua | 278 |
1 files changed, 193 insertions, 85 deletions
diff --git a/apps/plugins/boomshine.lua b/apps/plugins/boomshine.lua index 1729cbbf8c..63ac6b11fa 100644 --- a/apps/plugins/boomshine.lua +++ b/apps/plugins/boomshine.lua | |||
@@ -11,6 +11,7 @@ | |||
11 | See http://www.yvoschaap.com/chainrxn/ and http://www.k2xl.com/games/boomshine/ | 11 | See http://www.yvoschaap.com/chainrxn/ and http://www.k2xl.com/games/boomshine/ |
12 | 12 | ||
13 | Copyright (C) 2009 by Maurus Cuelenaere | 13 | Copyright (C) 2009 by Maurus Cuelenaere |
14 | Copyright (C) 2018 William Wilgus -- Added circles, blit cursor, hard levels | ||
14 | 15 | ||
15 | This program is free software; you can redistribute it and/or | 16 | This program is free software; you can redistribute it and/or |
16 | modify it under the terms of the GNU General Public License | 17 | modify it under the terms of the GNU General Public License |
@@ -21,14 +22,32 @@ | |||
21 | KIND, either express or implied. | 22 | KIND, either express or implied. |
22 | 23 | ||
23 | ]]-- | 24 | ]]-- |
24 | |||
25 | require "actions" | 25 | require "actions" |
26 | -- [[only save the actions we are using]] | ||
27 | actions_pla = {} | ||
28 | for key, val in pairs(rb.actions) do | ||
29 | for _, v in ipairs({"PLA_", "TOUCHSCREEN"}) do | ||
30 | if string.find (key, v) then | ||
31 | actions_pla[key] = val | ||
32 | break | ||
33 | end | ||
34 | end | ||
35 | end | ||
36 | rb.actions = nil | ||
37 | rb.contexts = nil | ||
38 | ------------------------------------- | ||
39 | |||
40 | local _LCD = rb.lcd_framebuffer() | ||
41 | local BSAND = 0x8 | ||
42 | local rocklib_image = getmetatable(rb.lcd_framebuffer()) | ||
43 | local _ellipse = rocklib_image.ellipse | ||
26 | 44 | ||
27 | local CYCLETIME = rb.HZ / 50 | 45 | local CYCLETIME = rb.HZ / 50 |
28 | local HAS_TOUCHSCREEN = rb.action_get_touchscreen_press ~= nil | 46 | local HAS_TOUCHSCREEN = rb.action_get_touchscreen_press ~= nil |
29 | local DEFAULT_BALL_SIZE = rb.LCD_HEIGHT > rb.LCD_WIDTH and rb.LCD_WIDTH / 30 | 47 | local DEFAULT_BALL_SIZE = rb.LCD_HEIGHT > rb.LCD_WIDTH and rb.LCD_WIDTH / 30 |
30 | or rb.LCD_HEIGHT / 30 | 48 | or rb.LCD_HEIGHT / 30 |
31 | local MAX_BALL_SPEED = DEFAULT_BALL_SIZE / 2 | 49 | local MAX_BALL_SPEED = DEFAULT_BALL_SIZE / 2 |
50 | local DEC_BALL_SPEED = DEFAULT_BALL_SIZE / 8 | ||
32 | local DEFAULT_FOREGROUND_COLOR = rb.lcd_get_foreground ~= nil | 51 | local DEFAULT_FOREGROUND_COLOR = rb.lcd_get_foreground ~= nil |
33 | and rb.lcd_get_foreground() | 52 | and rb.lcd_get_foreground() |
34 | or 0 | 53 | or 0 |
@@ -46,7 +65,15 @@ local levels = { | |||
46 | {30, 45}, | 65 | {30, 45}, |
47 | {37, 50}, | 66 | {37, 50}, |
48 | {48, 55}, | 67 | {48, 55}, |
49 | {55, 60} | 68 | {59, 60}, |
69 | {29, 30}, | ||
70 | {24, 25}, | ||
71 | {19, 20}, | ||
72 | {14, 15}, | ||
73 | {9, 10}, | ||
74 | {10, 10}, | ||
75 | {4, 5}, | ||
76 | {5, 5} | ||
50 | } | 77 | } |
51 | 78 | ||
52 | local Ball = { | 79 | local Ball = { |
@@ -55,16 +82,44 @@ local Ball = { | |||
55 | implosion = false | 82 | implosion = false |
56 | } | 83 | } |
57 | 84 | ||
58 | function Ball:new(o) | 85 | local function create_cursor(size) |
86 | local cursor | ||
87 | if not HAS_TOUCHSCREEN then | ||
88 | cursor = rb.new_image(size, size) | ||
89 | cursor:clear(0) | ||
90 | local sz2 = size / 2 | ||
91 | local sz4 = size / 4 | ||
92 | |||
93 | cursor:line(1, 1, sz4, 1, 1) | ||
94 | cursor:line(1, 1, 1, sz4, 1) | ||
95 | |||
96 | cursor:line(1, size, sz4, size, 1) | ||
97 | cursor:line(1, size, 1, size - sz4, 1) | ||
98 | |||
99 | cursor:line(size, size, size - sz4, size, 1) | ||
100 | cursor:line(size, size, size, size - sz4, 1) | ||
101 | |||
102 | cursor:line(size, 1, size - sz4, 1, 1) | ||
103 | cursor:line(size, 1, size, sz4, 1) | ||
104 | |||
105 | --crosshairs | ||
106 | cursor:line(sz2 - sz4, sz2, sz2 + sz4, sz2, 1) | ||
107 | cursor:line(sz2, sz2 - sz4, sz2, sz2 + sz4, 1) | ||
108 | end | ||
109 | return cursor | ||
110 | end | ||
111 | |||
112 | function Ball:new(o, level) | ||
113 | level = level or 1 | ||
59 | if o == nil then | 114 | if o == nil then |
60 | o = { | 115 | o = { |
61 | x = math.random(0, rb.LCD_WIDTH - self.size), | 116 | x = math.random(0, rb.LCD_WIDTH - self.size), |
62 | y = math.random(0, rb.LCD_HEIGHT - self.size), | 117 | y = math.random(0, rb.LCD_HEIGHT - self.size), |
63 | color = random_color(), | 118 | color = random_color(), |
64 | up_speed = Ball:generateSpeed(), | 119 | up_speed = Ball:generateSpeed(level), |
65 | right_speed = Ball:generateSpeed(), | 120 | right_speed = Ball:generateSpeed(level), |
66 | explosion_size = math.random(2*self.size, 4*self.size), | 121 | explosion_size = math.random(2*self.size, 4*self.size), |
67 | life_duration = math.random(rb.HZ, rb.HZ*5) | 122 | life_duration = math.random(rb.HZ / level, rb.HZ*5), |
68 | } | 123 | } |
69 | end | 124 | end |
70 | 125 | ||
@@ -73,8 +128,10 @@ function Ball:new(o) | |||
73 | return o | 128 | return o |
74 | end | 129 | end |
75 | 130 | ||
76 | function Ball:generateSpeed() | 131 | function Ball:generateSpeed(level) |
77 | local speed = math.random(-MAX_BALL_SPEED, MAX_BALL_SPEED) | 132 | local ballspeed = MAX_BALL_SPEED - (DEC_BALL_SPEED * (level - 1)) |
133 | if ballspeed < 2 then ballspeed = 2 end | ||
134 | local speed = math.random(-ballspeed, ballspeed) | ||
78 | if speed == 0 then | 135 | if speed == 0 then |
79 | speed = 1 -- Make sure all balls move | 136 | speed = 1 -- Make sure all balls move |
80 | end | 137 | end |
@@ -82,39 +139,48 @@ function Ball:generateSpeed() | |||
82 | return speed | 139 | return speed |
83 | end | 140 | end |
84 | 141 | ||
142 | function Ball:draw_exploded() | ||
143 | --[[ | ||
144 | --set_foreground(self.color) | ||
145 | --rb.lcd_fillrect(self.x, self.y, self.size, self.size) | ||
146 | ]] | ||
147 | |||
148 | _ellipse(_LCD, self.x, self.y, | ||
149 | self.x + self.size, self.y + self.size , self.color, nil, true) | ||
150 | end | ||
151 | |||
85 | function Ball:draw() | 152 | function Ball:draw() |
86 | --[[ | 153 | --[[ |
87 | I know these aren't circles, but as there's no current circle | 154 | --set_foreground(self.color) |
88 | implementation in Rockbox, rectangles will just do fine (drawing | 155 | --rb.lcd_fillrect(self.x, self.y, self.size, self.size) |
89 | circles from within Lua is far too slow). | 156 | ]] |
90 | ]]-- | 157 | |
91 | set_foreground(self.color) | 158 | _ellipse(_LCD, self.x, self.y, |
92 | rb.lcd_fillrect(self.x, self.y, self.size, self.size) | 159 | self.x + self.size, self.y + self.size , self.color, self.color, true) |
93 | end | 160 | end |
94 | 161 | ||
95 | function Ball:step() | 162 | function Ball:step_exploded() |
96 | if self.exploded then | 163 | if self.implosion and self.size > 0 then |
97 | if self.implosion and self.size > 0 then | 164 | self.size = self.size - 2 |
98 | self.size = self.size - 2 | 165 | self.x = self.x + 1 -- We do this because we want to stay centered |
99 | self.x = self.x + 1 -- We do this because we want to stay centered | 166 | self.y = self.y + 1 |
100 | self.y = self.y + 1 | 167 | elseif self.size < self.explosion_size then |
101 | elseif self.size < self.explosion_size then | 168 | self.size = self.size + 2 |
102 | self.size = self.size + 2 | 169 | self.x = self.x - 1 -- We do this for the same reasons as above |
103 | self.x = self.x - 1 -- We do this for the same reasons as above | 170 | self.y = self.y - 1 |
104 | self.y = self.y - 1 | ||
105 | end | ||
106 | return | ||
107 | end | 171 | end |
172 | end | ||
108 | 173 | ||
174 | function Ball:step() | ||
109 | self.x = self.x + self.right_speed | 175 | self.x = self.x + self.right_speed |
110 | self.y = self.y + self.up_speed | 176 | self.y = self.y + self.up_speed |
111 | if (self.right_speed > 0 and self.x + self.size >= rb.LCD_WIDTH) or | 177 | if (self.x <= 0 or self.x >= rb.LCD_WIDTH - self.size) then |
112 | (self.right_speed < 0 and self.x <= 0) then | ||
113 | self.right_speed = -self.right_speed | 178 | self.right_speed = -self.right_speed |
179 | self.x = self.x + self.right_speed | ||
114 | end | 180 | end |
115 | if (self.up_speed > 0 and self.y + self.size >= rb.LCD_HEIGHT) or | 181 | if (self.y <= 0 or self.y >= rb.LCD_HEIGHT - self.size ) then |
116 | (self.up_speed < 0 and self.y <= 0) then | ||
117 | self.up_speed = -self.up_speed | 182 | self.up_speed = -self.up_speed |
183 | self.y = self.y + self.up_speed | ||
118 | end | 184 | end |
119 | end | 185 | end |
120 | 186 | ||
@@ -137,7 +203,8 @@ end | |||
137 | local Cursor = { | 203 | local Cursor = { |
138 | size = DEFAULT_BALL_SIZE*2, | 204 | size = DEFAULT_BALL_SIZE*2, |
139 | x = rb.LCD_WIDTH/2, | 205 | x = rb.LCD_WIDTH/2, |
140 | y = rb.LCD_HEIGHT/2 | 206 | y = rb.LCD_HEIGHT/2, |
207 | image = create_cursor(DEFAULT_BALL_SIZE*2) | ||
141 | } | 208 | } |
142 | 209 | ||
143 | function Cursor:new() | 210 | function Cursor:new() |
@@ -145,18 +212,18 @@ function Cursor:new() | |||
145 | end | 212 | end |
146 | 213 | ||
147 | function Cursor:do_action(action) | 214 | function Cursor:do_action(action) |
148 | if action == rb.actions.ACTION_TOUCHSCREEN and HAS_TOUCHSCREEN then | 215 | if action == actions_pla.ACTION_TOUCHSCREEN and HAS_TOUCHSCREEN then |
149 | _, self.x, self.y = rb.action_get_touchscreen_press() | 216 | _, self.x, self.y = rb.action_get_touchscreen_press() |
150 | return true | 217 | return true |
151 | elseif action == rb.actions.PLA_SELECT then | 218 | elseif action == actions_pla.PLA_SELECT then |
152 | return true | 219 | return true |
153 | elseif (action == rb.actions.PLA_RIGHT) then | 220 | elseif (action == actions_pla.PLA_RIGHT or action == actions_pla.PLA_RIGHT_REPEAT) then |
154 | self.x = self.x + self.size | 221 | self.x = self.x + self.size |
155 | elseif (action == rb.actions.PLA_LEFT) then | 222 | elseif (action == actions_pla.PLA_LEFT or action == actions_pla.PLA_LEFT_REPEAT) then |
156 | self.x = self.x - self.size | 223 | self.x = self.x - self.size |
157 | elseif (action == rb.actions.PLA_UP) then | 224 | elseif (action == actions_pla.PLA_UP or action == actions_pla.PLA_UP_REPEAT) then |
158 | self.y = self.y - self.size | 225 | self.y = self.y - self.size |
159 | elseif (action == rb.actions.PLA_DOWN) then | 226 | elseif (action == actions_pla.PLA_DOWN or action == actions_pla.PLA_DOWN_REPEAT) then |
160 | self.y = self.y + self.size | 227 | self.y = self.y + self.size |
161 | end | 228 | end |
162 | 229 | ||
@@ -176,25 +243,16 @@ function Cursor:do_action(action) | |||
176 | end | 243 | end |
177 | 244 | ||
178 | function Cursor:draw() | 245 | function Cursor:draw() |
179 | set_foreground(DEFAULT_FOREGROUND_COLOR) | ||
180 | 246 | ||
181 | rb.lcd_hline(self.x - self.size/2, self.x - self.size/4, self.y - self.size/2) | 247 | rocklib_image.copy(_LCD, self.image, self.x - self.size/2, self.y - self.size/2, |
182 | rb.lcd_hline(self.x + self.size/4, self.x + self.size/2, self.y - self.size/2) | 248 | _NIL, _NIL, _NIL, _NIL, true, BSAND, DEFAULT_FOREGROUND_COLOR) |
183 | rb.lcd_hline(self.x - self.size/2, self.x - self.size/4, self.y + self.size/2) | ||
184 | rb.lcd_hline(self.x + self.size/4, self.x + self.size/2, self.y + self.size/2) | ||
185 | rb.lcd_vline(self.x - self.size/2, self.y - self.size/2, self.y - self.size/4) | ||
186 | rb.lcd_vline(self.x - self.size/2, self.y + self.size/4, self.y + self.size/2) | ||
187 | rb.lcd_vline(self.x + self.size/2, self.y - self.size/2, self.y - self.size/4) | ||
188 | rb.lcd_vline(self.x + self.size/2, self.y + self.size/4, self.y + self.size/2) | ||
189 | |||
190 | rb.lcd_hline(self.x - self.size/4, self.x + self.size/4, self.y) | ||
191 | rb.lcd_vline(self.x, self.y - self.size/4, self.y + self.size/4) | ||
192 | end | 249 | end |
193 | 250 | ||
194 | function draw_positioned_string(bottom, right, str) | 251 | function draw_positioned_string(bottom, right, str) |
195 | local _, w, h = rb.font_getstringsize(str, rb.FONT_UI) | 252 | local _, w, h = rb.font_getstringsize(str, rb.FONT_UI) |
196 | 253 | local x = not right or (rb.LCD_WIDTH-w)*right - 1 | |
197 | rb.lcd_putsxy((rb.LCD_WIDTH-w)*right, (rb.LCD_HEIGHT-h)*bottom, str) | 254 | local y = not bottom or (rb.LCD_HEIGHT-h)*bottom - 1 |
255 | rb.lcd_putsxy(x, y, str) | ||
198 | end | 256 | end |
199 | 257 | ||
200 | function set_foreground(color) | 258 | function set_foreground(color) |
@@ -213,31 +271,43 @@ end | |||
213 | 271 | ||
214 | function start_round(level, goal, nrBalls, total) | 272 | function start_round(level, goal, nrBalls, total) |
215 | local player_added, score, exit, nrExpendedBalls = false, 0, false, 0 | 273 | local player_added, score, exit, nrExpendedBalls = false, 0, false, 0 |
216 | local balls, explodedBalls = {}, {} | 274 | local Balls, explodedBalls = {}, {} |
275 | local ball_ct, ball_el | ||
276 | local tick, endtick | ||
277 | local action = 0 | ||
278 | local hit_detected = false | ||
217 | local cursor = Cursor:new() | 279 | local cursor = Cursor:new() |
218 | 280 | ||
219 | -- Initialize the balls | 281 | -- Initialize the balls |
220 | for _=1,nrBalls do | 282 | for _=1,nrBalls do |
221 | table.insert(balls, Ball:new()) | 283 | table.insert(Balls, Ball:new(nil, level)) |
284 | end | ||
285 | |||
286 | local function draw_stats() | ||
287 | draw_positioned_string(0, 0, string.format("%d balls expended", nrExpendedBalls)) | ||
288 | draw_positioned_string(0, 1, string.format("Level %d", level)) | ||
289 | draw_positioned_string(1, 1, string.format("%d level points", score)) | ||
290 | draw_positioned_string(1, 0, string.format("%d total points", total + score)) | ||
222 | end | 291 | end |
223 | 292 | ||
224 | -- Make sure there are no unwanted touchscreen presses | 293 | -- Make sure there are no unwanted touchscreen presses |
225 | rb.button_clear_queue() | 294 | rb.button_clear_queue() |
226 | 295 | ||
296 | set_foreground(DEFAULT_FOREGROUND_COLOR) -- color for text | ||
297 | |||
227 | while true do | 298 | while true do |
228 | local endtick = rb.current_tick() + CYCLETIME | 299 | endtick = rb.current_tick() + CYCLETIME |
229 | 300 | ||
230 | -- Check if the round is over | 301 | -- Check if the round is over |
231 | if #explodedBalls == 0 and player_added then | 302 | if player_added and #explodedBalls == 0 then |
232 | break | 303 | break |
233 | end | 304 | end |
234 | 305 | ||
235 | -- Check for actions | 306 | if action == actions_pla.PLA_EXIT or action == actions_pla.PLA_CANCEL then |
236 | local action = rb.get_plugin_action(0) | ||
237 | if action == rb.actions.PLA_EXIT or action == rb.actions.PLA_CANCEL then | ||
238 | exit = true | 307 | exit = true |
239 | break | 308 | break |
240 | end | 309 | end |
310 | |||
241 | if not player_added and cursor:do_action(action) then | 311 | if not player_added and cursor:do_action(action) then |
242 | local player = Ball:new({ | 312 | local player = Ball:new({ |
243 | x = cursor.x, | 313 | x = cursor.x, |
@@ -248,26 +318,28 @@ function start_round(level, goal, nrBalls, total) | |||
248 | exploded = true, | 318 | exploded = true, |
249 | death_time = rb.current_tick() + rb.HZ * 3 | 319 | death_time = rb.current_tick() + rb.HZ * 3 |
250 | }) | 320 | }) |
251 | table.insert(explodedBalls, player) | 321 | explodedBalls[1] = player |
252 | player_added = true | 322 | player_added = true |
323 | cursor = nil | ||
253 | end | 324 | end |
254 | 325 | ||
255 | -- Check for hits | 326 | -- Check for hits |
256 | for i, ball in ipairs(balls) do | 327 | for i, Ball in ipairs(Balls) do |
257 | for _, explodedBall in ipairs(explodedBalls) do | 328 | for _, explodedBall in ipairs(explodedBalls) do |
258 | if ball:checkHit(explodedBall) then | 329 | if Ball:checkHit(explodedBall) then |
259 | score = score + 100*level | 330 | explodedBalls[#explodedBalls + 1] = Ball |
260 | nrExpendedBalls = nrExpendedBalls + 1 | 331 | --table.remove(Balls, i) |
261 | table.insert(explodedBalls, ball) | 332 | Balls[i] = false |
262 | table.remove(balls, i) | 333 | hit_detected = true |
263 | break | 334 | break |
264 | end | 335 | end |
265 | end | 336 | end |
266 | end | 337 | end |
267 | 338 | ||
268 | -- Check if we're dead yet | 339 | -- Check if we're dead yet |
340 | tick = rb.current_tick() | ||
269 | for i, explodedBall in ipairs(explodedBalls) do | 341 | for i, explodedBall in ipairs(explodedBalls) do |
270 | if rb.current_tick() >= explodedBall.death_time then | 342 | if explodedBall.death_time < tick then |
271 | if explodedBall.size > 0 then | 343 | if explodedBall.size > 0 then |
272 | explodedBall.implosion = true -- We should be dying | 344 | explodedBall.implosion = true -- We should be dying |
273 | else | 345 | else |
@@ -277,38 +349,64 @@ function start_round(level, goal, nrBalls, total) | |||
277 | end | 349 | end |
278 | 350 | ||
279 | -- Drawing phase | 351 | -- Drawing phase |
280 | rb.lcd_clear_display() | 352 | if hit_detected then |
353 | hit_detected = false | ||
354 | -- same as table.remove(Balls, i) but more efficient | ||
355 | ball_el = 1 | ||
356 | ball_ct = #Balls | ||
357 | for i = 1, ball_ct do | ||
358 | if Balls[i] then | ||
359 | Balls[ball_el] = Balls[i] | ||
360 | ball_el = ball_el + 1 | ||
361 | end | ||
362 | end | ||
363 | -- remove any remaining exploded balls | ||
364 | for i = ball_el, ball_ct do | ||
365 | Balls[i] = nil | ||
366 | end | ||
367 | -- Calculate score | ||
368 | nrExpendedBalls = nrBalls - ball_el + 1 | ||
369 | score = nrExpendedBalls * level * 100 | ||
370 | end | ||
281 | 371 | ||
282 | set_foreground(DEFAULT_FOREGROUND_COLOR) | 372 | rb.lcd_clear_display() |
283 | draw_positioned_string(0, 0, string.format("%d balls expended", nrExpendedBalls)) | 373 | draw_stats() |
284 | draw_positioned_string(0, 1, string.format("Level %d", level)) | ||
285 | draw_positioned_string(1, 1, string.format("%d level points", score)) | ||
286 | draw_positioned_string(1, 0, string.format("%d total points", total+score)) | ||
287 | 374 | ||
288 | for _, ball in ipairs(balls) do | 375 | if not (player_added or HAS_TOUCHSCREEN) then |
289 | ball:step() | 376 | cursor:draw() |
290 | ball:draw() | ||
291 | end | 377 | end |
292 | 378 | ||
293 | for _, explodedBall in ipairs(explodedBalls) do | 379 | for _, Ball in ipairs(Balls) do |
294 | explodedBall:step() | 380 | Ball:step() |
295 | explodedBall:draw() | 381 | Ball:draw() |
296 | end | 382 | end |
297 | 383 | ||
298 | if not HAS_TOUCHSCREEN and not player_added then | 384 | for _, explodedBall in ipairs(explodedBalls) do |
299 | cursor:draw() | 385 | explodedBall:step_exploded() |
386 | explodedBall:draw_exploded() | ||
300 | end | 387 | end |
301 | 388 | ||
302 | -- Push framebuffer to the LCD | 389 | -- Push framebuffer to the LCD |
303 | rb.lcd_update() | 390 | rb.lcd_update() |
304 | 391 | ||
392 | -- Check for actions | ||
305 | if rb.current_tick() < endtick then | 393 | if rb.current_tick() < endtick then |
306 | rb.sleep(endtick - rb.current_tick()) | 394 | action = rb.get_plugin_action(endtick - rb.current_tick()) |
307 | else | 395 | else |
308 | rb.yield() | 396 | rb.yield() |
397 | action = rb.get_plugin_action(0) | ||
309 | end | 398 | end |
399 | |||
310 | end | 400 | end |
311 | 401 | ||
402 | --splash the final stats for a moment at end | ||
403 | rb.lcd_clear_display() | ||
404 | for _, Ball in ipairs(Balls) do Ball:draw() end | ||
405 | _LCD:clear(nil, nil, nil, nil, nil, nil, 2, 2) | ||
406 | draw_stats() | ||
407 | rb.lcd_update() | ||
408 | rb.sleep(rb.HZ * 2) | ||
409 | |||
312 | return exit, score, nrExpendedBalls | 410 | return exit, score, nrExpendedBalls |
313 | end | 411 | end |
314 | 412 | ||
@@ -320,6 +418,7 @@ function display_message(to, ...) | |||
320 | 418 | ||
321 | rb.lcd_clear_display() | 419 | rb.lcd_clear_display() |
322 | set_foreground(DEFAULT_FOREGROUND_COLOR) | 420 | set_foreground(DEFAULT_FOREGROUND_COLOR) |
421 | |||
323 | if w > rb.LCD_WIDTH then | 422 | if w > rb.LCD_WIDTH then |
324 | rb.lcd_puts_scroll(0, y/h, message) | 423 | rb.lcd_puts_scroll(0, y/h, message) |
325 | else | 424 | else |
@@ -340,7 +439,7 @@ function display_message(to, ...) | |||
340 | if to == -1 then | 439 | if to == -1 then |
341 | rb.sleep(rb.HZ/2) | 440 | rb.sleep(rb.HZ/2) |
342 | rb.button_clear_queue() | 441 | rb.button_clear_queue() |
343 | rb.button_get(1) | 442 | rb.button_get(rb.HZ * 60) |
344 | else | 443 | else |
345 | rb.sleep(to) | 444 | rb.sleep(to) |
346 | end | 445 | end |
@@ -351,6 +450,8 @@ end | |||
351 | if HAS_TOUCHSCREEN then | 450 | if HAS_TOUCHSCREEN then |
352 | rb.touchscreen_set_mode(rb.TOUCHSCREEN_POINT) | 451 | rb.touchscreen_set_mode(rb.TOUCHSCREEN_POINT) |
353 | end | 452 | end |
453 | |||
454 | --[[MAIN PROGRAM]] | ||
354 | rb.backlight_force_on() | 455 | rb.backlight_force_on() |
355 | 456 | ||
356 | math.randomseed(os.time()) | 457 | math.randomseed(os.time()) |
@@ -359,9 +460,12 @@ local idx, highscore = 1, 0 | |||
359 | while levels[idx] ~= nil do | 460 | while levels[idx] ~= nil do |
360 | local goal, nrBalls = levels[idx][1], levels[idx][2] | 461 | local goal, nrBalls = levels[idx][1], levels[idx][2] |
361 | 462 | ||
463 | collectgarbage("collect") --run gc now to hopefully prevent interruption later | ||
464 | |||
362 | display_message(rb.HZ*2, "Level %d: get %d out of %d balls", idx, goal, nrBalls) | 465 | display_message(rb.HZ*2, "Level %d: get %d out of %d balls", idx, goal, nrBalls) |
363 | 466 | ||
364 | local exit, score, nrExpendedBalls = start_round(idx, goal, nrBalls, highscore) | 467 | local exit, score, nrExpendedBalls = start_round(idx, goal, nrBalls, highscore) |
468 | |||
365 | if exit then | 469 | if exit then |
366 | break -- Exiting.. | 470 | break -- Exiting.. |
367 | else | 471 | else |
@@ -371,11 +475,14 @@ while levels[idx] ~= nil do | |||
371 | highscore = highscore + score | 475 | highscore = highscore + score |
372 | else | 476 | else |
373 | display_message(rb.HZ*2, "You lost!") | 477 | display_message(rb.HZ*2, "You lost!") |
478 | highscore = highscore - score - idx * 100 | ||
479 | if highscore < 0 then break end | ||
374 | end | 480 | end |
375 | end | 481 | end |
376 | end | 482 | end |
377 | 483 | if highscore <= 0 then | |
378 | if idx > #levels then | 484 | display_message(-1, "You lost at level %d", idx) |
485 | elseif idx > #levels then | ||
379 | display_message(-1, "You finished the game with %d points!", highscore) | 486 | display_message(-1, "You finished the game with %d points!", highscore) |
380 | else | 487 | else |
381 | display_message(-1, "You made it till level %d with %d points!", idx, highscore) | 488 | display_message(-1, "You made it till level %d with %d points!", idx, highscore) |
@@ -383,3 +490,4 @@ end | |||
383 | 490 | ||
384 | -- Restore user backlight settings | 491 | -- Restore user backlight settings |
385 | rb.backlight_use_settings() | 492 | rb.backlight_use_settings() |
493 | |||