diff options
author | William Wilgus <me.theuser@yahoo.com> | 2020-06-22 11:38:30 -0400 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2020-06-25 13:50:57 +0000 |
commit | ce61be4d59607c579594a66e59db1569c775f3da (patch) | |
tree | 7f629703cf9960e7dde0faef6b31b991841c09ff /apps/plugins | |
parent | 4bb467242a18355295a19e61217576712edcf422 (diff) | |
download | rockbox-ce61be4d59607c579594a66e59db1569c775f3da.tar.gz rockbox-ce61be4d59607c579594a66e59db1569c775f3da.zip |
lua boomshine update to use rockevents library
using rockev for button presses
misc code refactoring, comments
drawing code is now split from game logic
cpu boost for targets that support it
removed quite a few if then statements by using dynamic functions
for ball draw, step, hit_check
shows two ways to do OO functions (closure and reference)
Change-Id: I63e795bbe90b033eabadc1f519cf3b635cf5e1a7
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/boomshine.lua | 698 |
1 files changed, 435 insertions, 263 deletions
diff --git a/apps/plugins/boomshine.lua b/apps/plugins/boomshine.lua index c7ed6dfdf1..fcdf7c9a1c 100644 --- a/apps/plugins/boomshine.lua +++ b/apps/plugins/boomshine.lua | |||
@@ -11,7 +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, logic rewrite, hard levels | 14 | Copyright (C) 2020 William Wilgus -- Added circles, logic rewrite, hard levels |
15 | 15 | ||
16 | This program is free software; you can redistribute it and/or | 16 | This program is free software; you can redistribute it and/or |
17 | modify it under the terms of the GNU General Public License | 17 | modify it under the terms of the GNU General Public License |
@@ -23,7 +23,9 @@ | |||
23 | 23 | ||
24 | ]]-- | 24 | ]]-- |
25 | require "actions" | 25 | require "actions" |
26 | --[[only save the actions we are using]] | 26 | local DEBUG = false |
27 | |||
28 | --[[only save the actions we are using]]---------------------------------------- | ||
27 | pla = {} | 29 | pla = {} |
28 | for key, val in pairs(rb.actions) do | 30 | for key, val in pairs(rb.actions) do |
29 | for _, v in ipairs({"PLA_", "TOUCHSCREEN", "_NONE"}) do | 31 | for _, v in ipairs({"PLA_", "TOUCHSCREEN", "_NONE"}) do |
@@ -33,15 +35,32 @@ for key, val in pairs(rb.actions) do | |||
33 | end | 35 | end |
34 | end | 36 | end |
35 | rb.actions, rb.contexts = nil, nil | 37 | rb.actions, rb.contexts = nil, nil |
36 | -------------------------------------- | 38 | -------------------------------------------------------------------------------- |
39 | |||
40 | |||
41 | --[[ Profiling ]]--------------------------------------------------------------- | ||
42 | local screen_redraw_count = 0 | ||
43 | local screen_redraw_duration = 0 | ||
44 | -------------------------------------------------------------------------------- | ||
45 | |||
37 | 46 | ||
47 | --[[ References ]]-------------------------------------------------------------- | ||
38 | local _LCD = rb.lcd_framebuffer() | 48 | local _LCD = rb.lcd_framebuffer() |
39 | local rocklib_image = getmetatable(_LCD) | 49 | local rocklib_image = getmetatable(_LCD) |
40 | local _ellipse = rocklib_image.ellipse | 50 | local _ellipse = rocklib_image.ellipse-- |
41 | local BSAND = 0x8 | 51 | local irand = math.random-- |
42 | local irand = math.random | 52 | local lcd_putsxy = rb.lcd_putsxy-- |
43 | 53 | local strfmt = string.format-- | |
54 | local Cursor_Ref = nil | ||
55 | local Ball_Ref = {} | ||
56 | -------------------------------------------------------------------------------- | ||
57 | |||
58 | |||
59 | --[[ 'Constants' ]]------------------------------------------------------------- | ||
60 | local SCORE_MULTIPLY = 10 | ||
61 | local BSAND = 0x8-- | ||
44 | local HAS_TOUCHSCREEN = rb.action_get_touchscreen_press ~= nil | 62 | local HAS_TOUCHSCREEN = rb.action_get_touchscreen_press ~= nil |
63 | local Empty_fn = function() end | ||
45 | local LCD_H, LCD_W = rb.LCD_HEIGHT, rb.LCD_WIDTH | 64 | local LCD_H, LCD_W = rb.LCD_HEIGHT, rb.LCD_WIDTH |
46 | local DEFAULT_BALL_SZ = LCD_H > LCD_W and LCD_W / 30 or LCD_H / 30 | 65 | local DEFAULT_BALL_SZ = LCD_H > LCD_W and LCD_W / 30 or LCD_H / 30 |
47 | DEFAULT_BALL_SZ = DEFAULT_BALL_SZ - bit.band(DEFAULT_BALL_SZ, 1) | 66 | DEFAULT_BALL_SZ = DEFAULT_BALL_SZ - bit.band(DEFAULT_BALL_SZ, 1) |
@@ -61,10 +80,16 @@ end | |||
61 | 80 | ||
62 | local FMT_EXPEND, FMT_LEVEL = "%d balls expended", "Level %d" | 81 | local FMT_EXPEND, FMT_LEVEL = "%d balls expended", "Level %d" |
63 | local FMT_TOTPTS, FMT_LVPTS = "%d total points", "%d level points" | 82 | local FMT_TOTPTS, FMT_LVPTS = "%d total points", "%d level points" |
83 | -------------------------------------------------------------------------------- | ||
84 | |||
85 | |||
86 | --[[ Other ]]------------------------------------------------------------------- | ||
87 | local Player_Added | ||
88 | local Action_Evt = pla.ACTION_NONE | ||
64 | 89 | ||
65 | local levels = { | 90 | local levels = { |
66 | -- {GOAL, TOTAL_BALLS}, | 91 | -- {GOAL, TOTAL_BALLS}, |
67 | {1, 5}, | 92 | {1, 5}, |
68 | {2, 10}, | 93 | {2, 10}, |
69 | {4, 15}, | 94 | {4, 15}, |
70 | {6, 20}, | 95 | {6, 20}, |
@@ -85,7 +110,21 @@ local levels = { | |||
85 | {4, 5}, | 110 | {4, 5}, |
86 | {5, 5} | 111 | {5, 5} |
87 | } | 112 | } |
113 | -------------------------------------------------------------------------------- | ||
88 | 114 | ||
115 | |||
116 | --[[ Event Callback ]]---------------------------------------------------------- | ||
117 | function action_event(action) | ||
118 | if action == pla.PLA_CANCEL then | ||
119 | Action_Evt = pla.PLA_EXIT | ||
120 | else | ||
121 | Action_Evt = action | ||
122 | end | ||
123 | end | ||
124 | -------------------------------------------------------------------------------- | ||
125 | |||
126 | |||
127 | --[[ Helper functions ]]-------------------------------------------------------- | ||
89 | local function getstringsize(str) | 128 | local function getstringsize(str) |
90 | local _, w, h = rb.font_getstringsize(str, rb.FONT_UI) | 129 | local _, w, h = rb.font_getstringsize(str, rb.FONT_UI) |
91 | return w, h | 130 | return w, h |
@@ -97,90 +136,180 @@ local function set_foreground(color) | |||
97 | end | 136 | end |
98 | end | 137 | end |
99 | 138 | ||
100 | local function random_color() | 139 | local function calc_score(total, level, goal, expended) |
101 | if rb.lcd_rgbpack ~= nil then -- color target | 140 | local bonus = 0 |
102 | return rb.lcd_rgbpack(irand(1,255), irand(1,255), irand(1,255)) | 141 | local score = (expended * level) * SCORE_MULTIPLY |
142 | if expended < goal then | ||
143 | score = -(score + (level * SCORE_MULTIPLY)) | ||
144 | elseif expended > goal then | ||
145 | bonus = (expended - goal) * (level * SCORE_MULTIPLY) | ||
146 | end | ||
147 | total = total + score + bonus | ||
148 | return total, score, bonus | ||
149 | end | ||
150 | |||
151 | local function wait_anykey(to_secs) | ||
152 | rb.sleep(rb.HZ / 2) | ||
153 | rb.button_clear_queue() | ||
154 | rb.button_get_w_tmo(rb.HZ * to_secs) | ||
155 | end | ||
156 | |||
157 | local function disp_msg(to, ...) | ||
158 | local message = strfmt(...) | ||
159 | local w, h = getstringsize(message) | ||
160 | local x, y = (LCD_W - w) / 2, (LCD_H - h) / 2 | ||
161 | |||
162 | rb.lcd_clear_display() | ||
163 | set_foreground(DEFAULT_FG_CLR) | ||
164 | |||
165 | if w > LCD_W then | ||
166 | rb.lcd_puts_scroll(0, (y / h), message) | ||
167 | else | ||
168 | lcd_putsxy(x, y, message) | ||
169 | end | ||
170 | |||
171 | if to == -1 then | ||
172 | local msg = "Press button to exit" | ||
173 | w, h = getstringsize(msg) | ||
174 | x = (LCD_W - w) / 2 | ||
175 | if x < 0 then | ||
176 | rb.lcd_puts_scroll(0, (y / h) + 1, msg) | ||
177 | else | ||
178 | lcd_putsxy(x, y + h, msg) | ||
179 | end | ||
180 | end | ||
181 | rb.lcd_update() | ||
182 | |||
183 | if to == -1 then | ||
184 | wait_anykey(60) | ||
185 | else | ||
186 | rb.sleep(to) | ||
103 | end | 187 | end |
104 | 188 | ||
105 | local color = irand(1, rb.LCD_DEPTH) | 189 | rb.lcd_scroll_stop() -- Stop our scrolling message |
106 | color = (rb.LCD_DEPTH == 2) and (3 - color) or color -- invert for 2-bit screens | 190 | end |
107 | 191 | ||
108 | return color | 192 | local function test_speed() |
193 | local test_spd, redraw, dur = start_round(0, 0, 0, 0) -- test speed of target | ||
194 | --Logic speed, screen redraw, duration | ||
195 | if DEBUG == true then | ||
196 | disp_msg(rb.HZ * 5, "Spd: %d, Redraw: %d Dur: %d Ms", test_spd, redraw, dur) | ||
197 | end | ||
198 | if test_spd < 25 or redraw < 10 then | ||
199 | rb.splash(rb.HZ, "Slow Target..") | ||
200 | |||
201 | if test_spd < 10 then | ||
202 | MAX_BALL_SPEED = MAX_BALL_SPEED + MAX_BALL_SPEED | ||
203 | elseif test_spd < 15 then | ||
204 | MAX_BALL_SPEED = MAX_BALL_SPEED + MAX_BALL_SPEED / 2 | ||
205 | elseif test_spd < 25 then | ||
206 | MAX_BALL_SPEED = MAX_BALL_SPEED + MAX_BALL_SPEED / 4 | ||
207 | end | ||
208 | end | ||
109 | end | 209 | end |
210 | -------------------------------------------------------------------------------- | ||
110 | 211 | ||
212 | |||
213 | --[[ Ball Functions ]]---------------------------------------------------------- | ||
111 | local Ball = { | 214 | local Ball = { |
112 | -- Ball defaults | 215 | -- Ball defaults |
113 | sz = DEFAULT_BALL_SZ, | 216 | sz = DEFAULT_BALL_SZ, |
114 | next_tick = 0, | 217 | next_tick = 0, |
115 | state = B_MOVE | 218 | state = B_MOVE, |
116 | } | 219 | } |
117 | 220 | ||
118 | function Ball:new(o, level) | 221 | function Ball:new(o, level, color) |
222 | local function random_color() | ||
223 | if color == nil then | ||
224 | if rb.lcd_rgbpack ~= nil then -- color target | ||
225 | return rb.lcd_rgbpack(irand(1,255), irand(1,255), irand(1,255)) | ||
226 | end | ||
227 | color = irand(1, rb.LCD_DEPTH) | ||
228 | color = (rb.LCD_DEPTH == 2) and (3 - color) or color -- invert for 2-bit screens | ||
229 | end | ||
230 | return color | ||
231 | end | ||
232 | |||
119 | if o == nil then | 233 | if o == nil then |
120 | level = level or 1 | 234 | level = level or 1 |
121 | local maxdelay = (level <= 5) and 10 or level | 235 | local maxdelay = (level <= 5) and 15 or level * 2 |
122 | o = { | 236 | o = { |
123 | x = irand(1, LCD_W - self.sz), | 237 | x = irand(1, LCD_W - self.sz), |
124 | y = irand(1, LCD_H - self.sz), | 238 | y = irand(1, LCD_H - self.sz), |
125 | color = random_color(), | 239 | color = random_color(), |
126 | xi = Ball:genSpeed(), | 240 | xi = self.genSpeed(), -- x increment; x + sz after explode |
127 | yi = Ball:genSpeed(), | 241 | yi = self.genSpeed(), -- y increment; y + sz after explode |
128 | step_delay = irand(3, maxdelay / 2), | 242 | step_delay = irand(3, maxdelay / 2), |
129 | explosion_sz = irand(2 * self.sz, 4 * self.sz), | 243 | explosion_sz = irand(2 * self.sz, 4 * self.sz), |
130 | life_ticks = irand(rb.HZ / level, rb.HZ * (maxdelay / 5)) | 244 | life_ticks = irand(rb.HZ / level, rb.HZ * (maxdelay / 5)), |
245 | draw_fn = nil, | ||
246 | step_fn = self.step -- reference to current stepping function | ||
131 | } | 247 | } |
132 | end | 248 | end |
133 | o.life_ticks = o.life_ticks + DEFAULT_BALL_SZ -- extra time for larger screens | 249 | local Ball = o or {} -- so we can use Ball. instead of self |
250 | |||
251 | -- these functions end up in a closure; faster to call, use more RAM | ||
252 | function Ball.draw() | ||
253 | _ellipse(_LCD, o.x, o.y, o.x + o.sz, o.y + o.sz, o.color, o.color, true) | ||
254 | end | ||
255 | |||
256 | function Ball.draw_exploded() | ||
257 | _ellipse(_LCD, o.x, o.y, o.xi, o.yi, o.color, nil, true) | ||
258 | end | ||
259 | |||
260 | if Ball.draw_fn == nil then | ||
261 | Ball.draw_fn = Ball.draw -- reference to current drawing function | ||
262 | end | ||
263 | |||
134 | setmetatable(o, self) | 264 | setmetatable(o, self) |
135 | self.__index = self | 265 | self.__index = self |
136 | return o | 266 | return o |
137 | end | 267 | end |
138 | 268 | ||
269 | -- these functions are shared by reference, slower to call, use less RAM | ||
139 | function Ball:genSpeed() | 270 | function Ball:genSpeed() |
140 | local speed = irand(-MAX_BALL_SPEED, MAX_BALL_SPEED) | 271 | local speed = irand(-MAX_BALL_SPEED, MAX_BALL_SPEED) |
141 | return speed ~= 0 and speed or MAX_BALL_SPEED -- Make sure all balls move | 272 | return speed ~= 0 and speed or MAX_BALL_SPEED -- Make sure all balls move |
142 | end | 273 | end |
143 | 274 | ||
144 | function Ball:draw() | ||
145 | _ellipse(_LCD, self.x, self.y, | ||
146 | self.x + self.sz, self.y + self.sz , self.color, self.color, true) | ||
147 | end | ||
148 | |||
149 | function Ball:step(tick) | 275 | function Ball:step(tick) |
276 | local function rndspeed(cur) | ||
277 | local speed = cur + irand(-2, 2) | ||
278 | if speed < -MAX_BALL_SPEED then | ||
279 | speed = -MAX_BALL_SPEED | ||
280 | elseif speed > MAX_BALL_SPEED then | ||
281 | speed = MAX_BALL_SPEED | ||
282 | elseif speed == 0 then | ||
283 | speed = cur | ||
284 | end | ||
285 | return speed | ||
286 | end | ||
287 | |||
150 | self.next_tick = tick + self.step_delay | 288 | self.next_tick = tick + self.step_delay |
151 | self.x = self.x + self.xi | 289 | self.x = self.x + self.xi |
152 | self.y = self.y + self.yi | 290 | self.y = self.y + self.yi |
291 | local max_x = LCD_W - self.sz | ||
292 | local max_y = LCD_H - self.sz | ||
153 | 293 | ||
154 | if (self.x <= 0 or self.x >= (LCD_W - self.sz)) then | 294 | if self.x <= 0 then |
155 | self.xi = -self.xi | 295 | self.xi = -self.xi |
156 | self.x = self.x + self.xi | 296 | self.x = 1 |
297 | self.yi = rndspeed(self.yi) | ||
298 | elseif self.x >= max_x then | ||
299 | self.xi = -self.xi | ||
300 | self.x = max_x | ||
301 | self.yi = rndspeed(self.yi) | ||
157 | end | 302 | end |
158 | 303 | ||
159 | if (self.y <= 0 or self.y >= (LCD_H - self.sz)) then | 304 | if self.y <= 0 then |
160 | self.yi = -self.yi | 305 | self.yi = -self.yi |
161 | self.y = self.y + self.yi | 306 | self.y = 1 |
162 | end | 307 | self.xi = rndspeed(self.xi) |
163 | end | 308 | elseif self.y >= max_y then |
164 | 309 | self.yi = -self.yi | |
165 | function Ball:checkHit(other) | 310 | self.y = max_y |
166 | if (other.xi >= self.x) and (other.yi >= self.y) and | 311 | self.xi = rndspeed(self.xi) |
167 | (self.x + self.sz >= other.x) and (self.y + self.sz >= other.y) then | ||
168 | self.state = B_EXPLODE | ||
169 | -- x/y increment no longer needed it is now impact region | ||
170 | self.xi = self.x + self.sz | ||
171 | self.yi = self.y + self.sz | ||
172 | |||
173 | if other.state < B_EXPLODE then -- add duration to the ball that got hit | ||
174 | other.next_tick = other.next_tick + self.life_ticks | ||
175 | end | ||
176 | return true | ||
177 | end | 312 | end |
178 | |||
179 | return false | ||
180 | end | ||
181 | |||
182 | function Ball:draw_exploded() | ||
183 | _ellipse(_LCD, self.x, self.y, self.xi, self.yi, self.color, nil, true) | ||
184 | end | 313 | end |
185 | 314 | ||
186 | function Ball:step_exploded(tick) | 315 | function Ball:step_exploded(tick) |
@@ -188,20 +317,24 @@ function Ball:step_exploded(tick) | |||
188 | -- B_EXPLODE >> B_DIE >> BWAIT >> B_IMPLODE >> B_DEAD | 317 | -- B_EXPLODE >> B_DIE >> BWAIT >> B_IMPLODE >> B_DEAD |
189 | if self.state == B_EXPLODE and self.sz < self.explosion_sz then | 318 | if self.state == B_EXPLODE and self.sz < self.explosion_sz then |
190 | self.sz = self.sz + 2 | 319 | self.sz = self.sz + 2 |
191 | self.x = self.x - 1 -- We do this because we want to stay centered | 320 | self.x = self.x - 1 -- stay centered |
192 | self.y = self.y - 1 | 321 | self.y = self.y - 1 |
193 | elseif self.state == B_DIE then | 322 | elseif self.state == B_DIE then |
194 | self.state = B_WAIT | 323 | self.state = B_WAIT |
195 | self.next_tick = tick + self.life_ticks | 324 | self.next_tick = tick + self.life_ticks |
196 | return | 325 | return |
197 | elseif self.state == B_IMPLODE and self.sz > 0 then | 326 | elseif self.state == B_IMPLODE then |
198 | self.sz = self.sz - 2 | 327 | if self.sz > 0 then |
199 | self.x = self.x + 1 -- We do this because we want to stay centered | 328 | self.sz = self.sz - 2 |
200 | self.y = self.y + 1 | 329 | self.x = self.x + 1 -- stay centered |
201 | elseif self.state <= B_IMPLODE then | 330 | self.y = self.y + 1 |
202 | self.state = B_DEAD | 331 | else |
203 | return | 332 | self.state = B_DEAD |
204 | elseif self.next_tick < tick then | 333 | self.draw_fn = Empty_fn |
334 | self.step_fn = Empty_fn | ||
335 | return B_DEAD | ||
336 | end | ||
337 | elseif self.next_tick < tick then -- decay to next lower state | ||
205 | self.state = self.state - 1 | 338 | self.state = self.state - 1 |
206 | return | 339 | return |
207 | end | 340 | end |
@@ -211,59 +344,90 @@ function Ball:step_exploded(tick) | |||
211 | self.yi = self.y + self.sz | 344 | self.yi = self.y + self.sz |
212 | end | 345 | end |
213 | 346 | ||
347 | function Ball:checkHit(other) | ||
348 | local x, y = self.x, self.y | ||
349 | if (other.xi >= x) and (other.yi >= y) then | ||
350 | local sz = self.sz | ||
351 | local xi, yi = x + sz, y + sz | ||
352 | if (xi >= other.x) and (yi >= other.y) then | ||
353 | -- update impact region | ||
354 | self.xi = xi | ||
355 | self.yi = yi | ||
356 | -- change to exploded state | ||
357 | self.state = B_EXPLODE | ||
358 | self.draw_fn = self.draw_exploded | ||
359 | self.step_fn = self.step_exploded | ||
360 | |||
361 | if other.state < B_EXPLODE then -- add duration to the ball that got hit | ||
362 | other.next_tick = other.next_tick + self.life_ticks | ||
363 | end | ||
364 | return true | ||
365 | end | ||
366 | end | ||
367 | |||
368 | return false | ||
369 | end | ||
370 | -------------------------------------------------------------------------------- | ||
371 | |||
372 | |||
373 | --[[ Cursor Functions ]]-------------------------------------------------------- | ||
214 | local Cursor = { | 374 | local Cursor = { |
215 | sz = (DEFAULT_BALL_SZ * 2), | 375 | sz = (DEFAULT_BALL_SZ * 2), |
216 | x = (LCD_W / 2), | 376 | x = (LCD_W / 2), |
217 | y = (LCD_H / 2), | 377 | y = (LCD_H / 2), |
218 | color = DEFAULT_FG_CLR | 378 | color = DEFAULT_FG_CLR |
379 | --image = nil | ||
219 | } | 380 | } |
220 | 381 | ||
221 | function Cursor:new() | 382 | function Cursor:new() |
222 | if rb.LCD_DEPTH == 2 then -- invert for 2 - bit screens | 383 | if rb.LCD_DEPTH == 2 then -- invert for 2 - bit screens |
223 | self.color = 3 - DEFAULT_FG_CLR | 384 | self.color = 3 - DEFAULT_FG_CLR |
224 | end | 385 | end |
225 | self:create_image(DEFAULT_BALL_SZ * 2) | 386 | if not HAS_TOUCHSCREEN and not self.image then |
226 | return self | 387 | local function create_image(sz) |
227 | end | 388 | sz = sz + 1 |
228 | 389 | local img = rb.new_image(sz, sz) | |
229 | function Cursor:create_image(sz) | 390 | local sz2 = (sz / 2) + 1 |
230 | if not HAS_TOUCHSCREEN then | 391 | local sz4 = (sz / 4) |
231 | sz = sz + 1 | 392 | |
232 | local img = rb.new_image(sz, sz) | 393 | img:clear(0) |
233 | local sz2 = (sz / 2) + 1 | 394 | img:line(1, 1, sz4 + 1, 1, 1) |
234 | local sz4 = (sz / 4) | 395 | img:line(1, 1, 1, sz4 + 1, 1) |
235 | 396 | ||
236 | img:clear(0) | 397 | img:line(1, sz, sz4 + 1, sz, 1) |
237 | img:line(1, 1, sz4 + 1, 1, 1) | 398 | img:line(1, sz, 1, sz - sz4, 1) |
238 | img:line(1, 1, 1, sz4 + 1, 1) | 399 | |
239 | 400 | img:line(sz, sz, sz - sz4, sz, 1) | |
240 | img:line(1, sz, sz4 + 1, sz, 1) | 401 | img:line(sz, sz, sz, sz - sz4, 1) |
241 | img:line(1, sz, 1, sz - sz4, 1) | 402 | |
242 | 403 | img:line(sz, 1, sz - sz4, 1, 1) | |
243 | img:line(sz, sz, sz - sz4, sz, 1) | 404 | img:line(sz, 1, sz, sz4 + 1, 1) |
244 | img:line(sz, sz, sz, sz - sz4, 1) | 405 | |
245 | 406 | -- crosshairs | |
246 | img:line(sz, 1, sz - sz4, 1, 1) | 407 | img:line(sz2 - sz4, sz2, sz2 + sz4, sz2, 1) |
247 | img:line(sz, 1, sz, sz4 + 1, 1) | 408 | img:line(sz2, sz2 - sz4, sz2, sz2 + sz4, 1) |
248 | 409 | return img | |
249 | -- crosshairs | 410 | end |
250 | img:line(sz2 - sz4, sz2, sz2 + sz4, sz2, 1) | 411 | self.image = create_image(DEFAULT_BALL_SZ * 2) |
251 | img:line(sz2, sz2 - sz4, sz2, sz2 + sz4, 1) | ||
252 | self.image = img | ||
253 | end | 412 | end |
254 | end | ||
255 | 413 | ||
256 | local function clamp_roll(iVal, iMin, iMax) | 414 | function Cursor.draw() |
257 | if iVal < iMin then | 415 | rocklib_image.copy(_LCD, self.image, self.x, self.y, _NIL, _NIL, |
258 | iVal = iMax | 416 | _NIL, _NIL, true, BSAND, self.color) |
259 | elseif iVal > iMax then | ||
260 | iVal = iMin | ||
261 | end | 417 | end |
262 | 418 | ||
263 | return iVal | 419 | return self |
264 | end | 420 | end |
265 | 421 | ||
266 | function Cursor:do_action(action) | 422 | function Cursor:do_action(action) |
423 | local function clamp_roll(iVal, iMin, iMax) | ||
424 | if iVal < iMin then | ||
425 | iVal = iMax | ||
426 | elseif iVal > iMax then | ||
427 | iVal = iMin | ||
428 | end | ||
429 | return iVal | ||
430 | end | ||
267 | local xi, yi = 0, 0 | 431 | local xi, yi = 0, 0 |
268 | 432 | ||
269 | if HAS_TOUCHSCREEN and action == pla.ACTION_TOUCHSCREEN then | 433 | if HAS_TOUCHSCREEN and action == pla.ACTION_TOUCHSCREEN then |
@@ -279,188 +443,225 @@ function Cursor:do_action(action) | |||
279 | yi = -self.sz | 443 | yi = -self.sz |
280 | elseif (action == pla.PLA_DOWN or action == pla.PLA_DOWN_REPEAT) then | 444 | elseif (action == pla.PLA_DOWN or action == pla.PLA_DOWN_REPEAT) then |
281 | yi = self.sz | 445 | yi = self.sz |
446 | else | ||
447 | Action_Evt = pla.ACTION_NONE | ||
448 | return false | ||
282 | end | 449 | end |
283 | 450 | ||
284 | self.x = clamp_roll(self.x + xi, 1, LCD_W - self.sz) | 451 | self.x = clamp_roll(self.x + xi, 1, LCD_W - self.sz) |
285 | self.y = clamp_roll(self.y + yi, 1, LCD_H - self.sz) | 452 | self.y = clamp_roll(self.y + yi, 1, LCD_H - self.sz) |
286 | 453 | Action_Evt = pla.ACTION_NONE | |
287 | return false | 454 | return false |
288 | end | 455 | end |
456 | -------------------------------------------------------------------------------- | ||
289 | 457 | ||
290 | function Cursor:draw() | ||
291 | rocklib_image.copy(_LCD, self.image, self.x, self.y, _NIL, _NIL, | ||
292 | _NIL, _NIL, true, BSAND, self.color) | ||
293 | end | ||
294 | 458 | ||
295 | local function calc_score(total, level, goal, expended) | 459 | --[[ Game function ]]----------------------------------------------------------- |
296 | local score = (expended * level) * 100 | 460 | function start_round(level, goal, nrBalls, total) |
297 | if expended < goal then | 461 | Player_Added = false |
298 | score = -(score + (level * 100)) | 462 | --[[ References ]]-- |
299 | end | 463 | local current_tick = rb.current_tick |
300 | total = total + score | 464 | local lcd_update = rb.lcd_update |
301 | return total | 465 | local lcd_clear_display = rb.lcd_clear_display |
302 | end | ||
303 | |||
304 | local function draw_pos_str(bottom, right, str) | ||
305 | local w, h = getstringsize(str) | ||
306 | local x = (right > 0) and ((LCD_W - w) * right - 1) or 1 | ||
307 | local y = (bottom > 0) and ((LCD_H - h) * bottom - 1) or 1 | ||
308 | rb.lcd_putsxy(x, y, str) | ||
309 | end | ||
310 | |||
311 | local function wait_anykey(to_secs) | ||
312 | rb.sleep(rb.HZ / 2) | ||
313 | rb.button_clear_queue() | ||
314 | rb.button_get_w_tmo(rb.HZ * to_secs) | ||
315 | end | ||
316 | 466 | ||
317 | local function start_round(level, goal, nrBalls, total) | 467 | local test_spd = false |
318 | local player_added, score = false, 0 | 468 | local is_exit = false; |
469 | local score = 0 | ||
319 | local last_expend, nrBalls_expend = 0, 0 | 470 | local last_expend, nrBalls_expend = 0, 0 |
320 | local balls_exploded = 1 -- keep looping when player_added == false | ||
321 | local action = 0 | ||
322 | local Balls = {} | 471 | local Balls = {} |
323 | local str_level = string.format(FMT_LEVEL, level) -- static | 472 | local balls_exploded = 1 -- to keep looping when player_added == false |
324 | local str_totpts = string.format(FMT_TOTPTS, total) -- static | 473 | |
474 | local tick_next = 0 | ||
475 | local cursor = nil | ||
476 | local draw_cursor = Empty_fn | ||
477 | local refresh = rb.HZ/20 | ||
478 | |||
479 | local function level_stats(level, total) | ||
480 | return strfmt(FMT_LEVEL, level), strfmt(FMT_TOTPTS, total) | ||
481 | end | ||
482 | |||
483 | local str_level, str_totpts = level_stats(level, total) -- static for lvl | ||
325 | local str_expend, str_lvlpts | 484 | local str_expend, str_lvlpts |
326 | local tick, cursor | ||
327 | local test_spd = false | ||
328 | 485 | ||
329 | local function update_stats() | 486 | local function update_stats() |
330 | -- we only create a new string when a hit is detected | 487 | -- we only create a new string when a hit is detected |
331 | str_expend = string.format(FMT_EXPEND, nrBalls_expend) | 488 | str_expend = strfmt(FMT_EXPEND, nrBalls_expend) |
332 | str_lvlpts = string.format(FMT_LVPTS, score) | 489 | str_lvlpts = strfmt(FMT_LVPTS, score) |
333 | end | 490 | end |
334 | 491 | ||
335 | local function draw_stats() | 492 | function draw_stats() |
493 | local function draw_pos_str(bottom, right, str) | ||
494 | local w, h = getstringsize(str) | ||
495 | local x = (right > 0) and ((LCD_W - w) * right - 1) or 1 | ||
496 | local y = (bottom > 0) and ((LCD_H - h) * bottom - 1) or 1 | ||
497 | lcd_putsxy(x, y, str) | ||
498 | end | ||
499 | -- pos(B, R) [B/R]=0 => [y/x]=1, [B/R]=1 => [y/x]=lcd[H/W]-string[H/W] | ||
336 | draw_pos_str(0, 0, str_expend) | 500 | draw_pos_str(0, 0, str_expend) |
337 | draw_pos_str(0, 1, str_level) | 501 | draw_pos_str(0, 1, str_level) |
338 | draw_pos_str(1, 1, str_lvlpts) | 502 | draw_pos_str(1, 1, str_lvlpts) |
339 | draw_pos_str(1, 0, str_totpts) | 503 | draw_pos_str(1, 0, str_totpts) |
340 | end | 504 | end |
341 | 505 | ||
506 | -- all Balls share same function, will by changed by player_add() | ||
507 | local checkhit_fn = Empty_fn | ||
508 | |||
509 | local function checkhit(Ball) | ||
510 | if Ball.state == B_MOVE then | ||
511 | for i = #Balls, 1, -1 do | ||
512 | if Balls[i].state < B_MOVE and | ||
513 | Ball:checkHit(Balls[i]) then -- exploded? | ||
514 | balls_exploded = balls_exploded + 1 | ||
515 | nrBalls_expend = nrBalls_expend + 1 | ||
516 | break | ||
517 | end | ||
518 | end | ||
519 | end | ||
520 | end | ||
521 | |||
342 | local function add_player() | 522 | local function add_player() |
343 | -- cursor becomes exploded ball | 523 | -- cursor becomes exploded ball |
344 | local player = Ball:new({ | 524 | local player = Ball:new({ |
345 | x = cursor.x, | 525 | x = cursor.x - cursor.sz, |
346 | y = cursor.y, | 526 | y = cursor.y - cursor.sz, |
347 | color = cursor.color, | 527 | color = cursor.color, |
348 | step_delay = 3, | 528 | step_delay = 3, |
349 | explosion_sz = (3 * DEFAULT_BALL_SZ), | 529 | explosion_sz = (3 * DEFAULT_BALL_SZ), |
350 | life_ticks = (test_time == true) and (100) or | 530 | life_ticks = (test_spd) and (rb.HZ) or |
351 | irand(rb.HZ * 2, rb.HZ * DEFAULT_BALL_SZ), | 531 | irand(rb.HZ * 2, rb.HZ * DEFAULT_BALL_SZ), |
352 | sz = 10, | 532 | sz = 10, |
353 | state = B_EXPLODE | 533 | state = B_EXPLODE |
354 | }) | 534 | }) |
355 | -- set x/y impact region | 535 | -- set x/y impact region -->[] |
356 | player.xi = player.x + player.sz | 536 | player.xi = player.x + player.sz |
357 | player.yi = player.y + player.sz | 537 | player.yi = player.y + player.sz |
538 | player.draw_fn = player.draw_exploded | ||
539 | player.step_fn = player.step_exploded | ||
358 | 540 | ||
359 | table.insert(Balls, player) | 541 | table.insert(Balls, player) |
360 | balls_exploded = 1 | 542 | balls_exploded = 1 |
361 | player_added = true | 543 | Player_Added = true |
362 | cursor = nil | 544 | cursor = nil |
545 | draw_cursor = Empty_fn | ||
546 | -- only need collision detection after player add | ||
547 | checkhit_fn = checkhit | ||
363 | end | 548 | end |
364 | 549 | ||
365 | if level < 1 then | 550 | local function speedtest() |
366 | -- check speed of target | 551 | -- check speed of target |
367 | set_foreground(DEFAULT_BG_CLR) --hide text during test | 552 | set_foreground(DEFAULT_BG_CLR) --hide text during test |
368 | local bkcolor = (rb.LCD_DEPTH == 2) and (3) or 0 | ||
369 | level = 1 | 553 | level = 1 |
370 | nrBalls = 20 | 554 | nrBalls = 100 |
371 | cursor = { x = LCD_W * 2, y = LCD_H * 2, color = bkcolor} | 555 | cursor = {x = LCD_W * 2, y = LCD_H * 2, color = 0, sz = 1} |
372 | table.insert(Balls, Ball:new({ | 556 | table.insert(Balls, Ball:new({ |
373 | x = 1, y = 1, xi = 1, yi = 1, | 557 | x = 1, y = 1, xi = 1, yi = 1, |
374 | color = bkcolor, step_delay = 1, | 558 | color = 0, step_delay = 0, |
375 | explosion_sz = 0, life_ticks = 0, | 559 | explosion_sz = 0, life_ticks = 0, |
376 | step = function() test_spd = test_spd + 1 end | 560 | draw_fn = Empty_fn, |
561 | step_fn = function() test_spd = test_spd + 1 end | ||
377 | }) | 562 | }) |
378 | ) | 563 | ) |
379 | add_player() | ||
380 | test_spd = 0 | 564 | test_spd = 0 |
565 | add_player() | ||
566 | end | ||
567 | |||
568 | local function screen_redraw() | ||
569 | -- (draw_fn changes dynamically at runtime) | ||
570 | for i = 1, #Balls do | ||
571 | Balls[i].draw_fn() | ||
572 | end | ||
573 | |||
574 | draw_stats() | ||
575 | draw_cursor() | ||
576 | |||
577 | lcd_update() | ||
578 | lcd_clear_display() | ||
579 | end | ||
580 | |||
581 | local function game_loop() | ||
582 | local tick = current_tick() | ||
583 | for _, Ball in ipairs(Balls) do | ||
584 | if tick > Ball.next_tick then | ||
585 | -- (step_fn changes dynamically at runtime) | ||
586 | if Ball:step_fn(tick) == B_DEAD then | ||
587 | balls_exploded = balls_exploded - 1 | ||
588 | else | ||
589 | checkhit_fn(Ball) | ||
590 | end | ||
591 | end | ||
592 | end | ||
593 | return tick | ||
594 | end | ||
595 | |||
596 | if level < 1 then | ||
597 | speedtest() | ||
598 | local bkcolor = (rb.LCD_DEPTH == 2) and (3) or 0 | ||
599 | -- Initialize the balls | ||
600 | if DEBUG then bkcolor = nil end | ||
601 | for i=1, nrBalls do | ||
602 | table.insert(Balls, Ball:new(nil, level, bkcolor)) | ||
603 | end | ||
381 | else | 604 | else |
605 | speedtest = nil | ||
382 | set_foreground(DEFAULT_FG_CLR) -- color for text | 606 | set_foreground(DEFAULT_FG_CLR) -- color for text |
383 | cursor = Cursor:new() | 607 | cursor = Cursor:new() |
384 | end | 608 | if not HAS_TOUCHSCREEN then |
385 | 609 | draw_cursor = cursor.draw | |
386 | -- Initialize the balls | 610 | end |
387 | for i=1, nrBalls do | 611 | -- Initialize the balls |
388 | table.insert(Balls, Ball:new(nil, level)) | 612 | for i=1, nrBalls do |
613 | table.insert(Balls, Ball:new(nil, level)) | ||
614 | end | ||
389 | end | 615 | end |
390 | 616 | ||
391 | -- Make sure there are no unwanted touchscreen presses | 617 | -- Make sure there are no unwanted touchscreen presses |
392 | rb.button_clear_queue() | 618 | rb.button_clear_queue() |
393 | 619 | ||
620 | Action_Evt = pla.ACTION_NONE | ||
621 | |||
394 | update_stats() -- load status strings | 622 | update_stats() -- load status strings |
395 | 623 | ||
396 | -- Check if the round is over | 624 | if rb.cpu_boost then rb.cpu_boost(true) end |
397 | while balls_exploded > 0 do | 625 | collectgarbage("collect") -- run gc now to hopefully prevent interruption later |
398 | tick = rb.current_tick() | ||
399 | 626 | ||
400 | if action ~= pla.ACTION_NONE and (action == pla.PLA_EXIT or | 627 | local duration = current_tick() |
401 | action == pla.PLA_CANCEL) then | 628 | -- Game loop >> Check if the round is over |
402 | action = pla.PLA_EXIT | 629 | while balls_exploded > 0 do |
630 | if Action_Evt == pla.PLA_EXIT then | ||
631 | is_exit = true | ||
403 | break | 632 | break |
404 | end | 633 | end |
405 | 634 | ||
406 | rb.lcd_clear_display() | 635 | if game_loop() > tick_next then |
407 | 636 | tick_next = current_tick() + refresh | |
408 | if not player_added then | 637 | if not Player_Added then |
409 | if action ~= pla.ACTION_NONE and cursor:do_action(action) then | 638 | if Action_Evt ~= pla.ACTION_NONE and cursor:do_action(Action_Evt) then |
410 | add_player() | 639 | add_player() |
411 | elseif not HAS_TOUCHSCREEN then | ||
412 | cursor:draw() | ||
413 | end | ||
414 | end | ||
415 | |||
416 | for _, Ball in ipairs(Balls) do | ||
417 | if Ball.state == B_MOVE then | ||
418 | if tick > Ball.next_tick then | ||
419 | Ball:step(tick) | ||
420 | for i = #Balls, 1, -1 do | ||
421 | if Balls[i].state < B_MOVE and | ||
422 | Ball:checkHit(Balls[i]) then -- exploded? | ||
423 | balls_exploded = balls_exploded + 1 | ||
424 | nrBalls_expend = nrBalls_expend + 1 | ||
425 | break | ||
426 | end | ||
427 | end | ||
428 | end | ||
429 | -- check if state changed draw ball if still moving | ||
430 | if Ball.state == B_MOVE then | ||
431 | Ball:draw() | ||
432 | end | ||
433 | elseif Ball.state ~= B_DEAD then | ||
434 | if tick > Ball.next_tick then | ||
435 | Ball:step_exploded(tick) | ||
436 | end | ||
437 | if Ball.state ~= B_DEAD then | ||
438 | Ball:draw_exploded() | ||
439 | else | ||
440 | balls_exploded = balls_exploded - 1 | ||
441 | end | 640 | end |
442 | end | 641 | end |
443 | end | ||
444 | 642 | ||
445 | draw_stats() -- stats redrawn every frame | 643 | if nrBalls_expend ~= last_expend then -- hit detected? |
446 | rb.lcd_update() -- Push framebuffer to the LCD | 644 | last_expend = nrBalls_expend |
645 | score = (nrBalls_expend * level) * SCORE_MULTIPLY | ||
646 | update_stats() -- only update stats when not current | ||
647 | if nrBalls_expend == nrBalls then break end -- round is over? | ||
648 | end | ||
447 | 649 | ||
448 | if nrBalls_expend ~= last_expend then -- hit detected? | 650 | screen_redraw_count = screen_redraw_count + 1 |
449 | last_expend = nrBalls_expend | 651 | screen_redraw() |
450 | score = (nrBalls_expend * level) * 100 | ||
451 | update_stats() -- only update stats when not current | ||
452 | if nrBalls_expend == nrBalls then break end -- round is over? | ||
453 | end | 652 | end |
454 | |||
455 | rb.yield() -- yield to other tasks | 653 | rb.yield() -- yield to other tasks |
456 | |||
457 | action = rb.get_plugin_action(0) -- Check for actions | ||
458 | end | 654 | end |
459 | 655 | ||
460 | if test_spd and test_spd > 0 then return test_spd end | 656 | screen_redraw_duration = screen_redraw_duration + (rb.current_tick() - duration) |
657 | if rb.cpu_boost then rb.cpu_boost(false) end | ||
658 | |||
659 | if test_spd and test_spd > 0 then | ||
660 | return test_spd, screen_redraw_count, screen_redraw_duration *10 --ms | ||
661 | end | ||
461 | 662 | ||
462 | -- splash the final stats for a moment at end | 663 | -- splash the final stats for a moment at end |
463 | rb.lcd_clear_display() | 664 | lcd_clear_display() |
464 | for _, Ball in ipairs(Balls) do | 665 | for _, Ball in ipairs(Balls) do |
465 | -- move balls back to their initial exploded positions | 666 | -- move balls back to their initial exploded positions |
466 | if Ball.state == B_DEAD then | 667 | if Ball.state == B_DEAD then |
@@ -471,56 +672,22 @@ local function start_round(level, goal, nrBalls, total) | |||
471 | Ball:draw() | 672 | Ball:draw() |
472 | end | 673 | end |
473 | 674 | ||
474 | if DEFAULT_BALL_SZ > 3 then | 675 | if DEFAULT_BALL_SZ > 3 then -- dither |
475 | _LCD:clear(nil, nil, nil, nil, nil, nil, 2, 2) | 676 | _LCD:clear(nil, nil, nil, nil, nil, nil, 2, 2) |
476 | end | 677 | end |
477 | 678 | ||
478 | total = calc_score(total, level, goal, nrBalls_expend) | 679 | total = calc_score(total, level, goal, nrBalls_expend) |
479 | str_totpts = string.format(FMT_TOTPTS, total) | 680 | str_level, str_totpts = level_stats(level, total) |
480 | draw_stats() | 681 | draw_stats() |
481 | rb.lcd_update() | 682 | lcd_update() |
482 | wait_anykey(2) | 683 | wait_anykey(2) |
483 | 684 | ||
484 | return action == pla.PLA_EXIT, score, nrBalls_expend | 685 | return is_exit, score, nrBalls_expend |
485 | end | 686 | end |
687 | -------------------------------------------------------------------------------- | ||
486 | 688 | ||
487 | -- Helper function to display a message | ||
488 | local function disp_msg(to, ...) | ||
489 | local message = string.format(...) | ||
490 | local w, h = getstringsize(message) | ||
491 | local x, y = (LCD_W - w) / 2, (LCD_H - h) / 2 | ||
492 | |||
493 | rb.lcd_clear_display() | ||
494 | set_foreground(DEFAULT_FG_CLR) | ||
495 | |||
496 | if w > LCD_W then | ||
497 | rb.lcd_puts_scroll(0, (y / h), message) | ||
498 | else | ||
499 | rb.lcd_putsxy(x, y, message) | ||
500 | end | ||
501 | 689 | ||
502 | if to == -1 then | 690 | --[[MAIN PROGRAM]]-------------------------------------------------------------- |
503 | local msg = "Press button to exit" | ||
504 | w, h = getstringsize(msg) | ||
505 | x = (LCD_W - w) / 2 | ||
506 | if x < 0 then | ||
507 | rb.lcd_puts_scroll(0, (y / h) + 1, msg) | ||
508 | else | ||
509 | rb.lcd_putsxy(x, y + h, msg) | ||
510 | end | ||
511 | end | ||
512 | rb.lcd_update() | ||
513 | |||
514 | if to == -1 then | ||
515 | wait_anykey(60) | ||
516 | else | ||
517 | rb.sleep(to) | ||
518 | end | ||
519 | |||
520 | rb.lcd_scroll_stop() -- Stop our scrolling message | ||
521 | end | ||
522 | |||
523 | --[[MAIN PROGRAM]] | ||
524 | do -- attempt to get stats to fit on screen | 691 | do -- attempt to get stats to fit on screen |
525 | local function getwidth(str) | 692 | local function getwidth(str) |
526 | local w, _ = getstringsize(str) | 693 | local w, _ = getstringsize(str) |
@@ -530,7 +697,7 @@ do -- attempt to get stats to fit on screen | |||
530 | if (w0 + w1) > LCD_W then | 697 | if (w0 + w1) > LCD_W then |
531 | FMT_EXPEND, FMT_LEVEL = "%d balls", "Lv %d" | 698 | FMT_EXPEND, FMT_LEVEL = "%d balls", "Lv %d" |
532 | end | 699 | end |
533 | w0, w1 = getwidth(FMT_TOTPTS), getwidth(FMT_LVPTS) | 700 | w0, w1 = getwidth(FMT_TOTPTS), getwidth(FMT_LVPTS) |
534 | if (w0 + w1 + getwidth("0000000")) > LCD_W then | 701 | if (w0 + w1 + getwidth("0000000")) > LCD_W then |
535 | FMT_TOTPTS, FMT_LVPTS = "%d total", "%d lv" | 702 | FMT_TOTPTS, FMT_LVPTS = "%d total", "%d lv" |
536 | end | 703 | end |
@@ -542,23 +709,16 @@ end | |||
542 | 709 | ||
543 | rb.backlight_force_on() | 710 | rb.backlight_force_on() |
544 | 711 | ||
545 | math.randomseed(os.time()) | 712 | local eva = rockev.register("action", action_event, rb.HZ / 10) |
546 | |||
547 | local idx, highscore = 1, 0 | ||
548 | 713 | ||
549 | local test_spd = start_round(0, 0, 0, 0) -- test speed of target | 714 | math.randomseed(os.time() or 1) |
550 | 715 | ||
551 | if test_spd < 100 then | 716 | local idx, highscore = 1, 0 |
552 | rb.splash(100, "Slow Target..") | ||
553 | 717 | ||
554 | if test_spd < 25 then | 718 | disp_msg(rb.HZ, "BoomShine") |
555 | MAX_BALL_SPEED = MAX_BALL_SPEED + MAX_BALL_SPEED | 719 | test_speed() |
556 | elseif test_spd < 50 then | 720 | rb.sleep(rb.HZ * 2) |
557 | MAX_BALL_SPEED = MAX_BALL_SPEED + MAX_BALL_SPEED / 2 | 721 | test_speed = nil |
558 | elseif test_spd < 100 then | ||
559 | MAX_BALL_SPEED = MAX_BALL_SPEED + MAX_BALL_SPEED / 4 | ||
560 | end | ||
561 | end | ||
562 | 722 | ||
563 | while levels[idx] ~= nil do | 723 | while levels[idx] ~= nil do |
564 | local goal, nrBalls = levels[idx][1], levels[idx][2] | 724 | local goal, nrBalls = levels[idx][1], levels[idx][2] |
@@ -567,18 +727,26 @@ while levels[idx] ~= nil do | |||
567 | 727 | ||
568 | disp_msg(rb.HZ * 2, "Level %d: get %d out of %d balls", idx, goal, nrBalls) | 728 | disp_msg(rb.HZ * 2, "Level %d: get %d out of %d balls", idx, goal, nrBalls) |
569 | 729 | ||
570 | local exit, score, nrBalls_expend = start_round(idx, goal, nrBalls, highscore) | 730 | local is_exit, score, nrBalls_expend = start_round(idx, goal, nrBalls, highscore) |
731 | if DEBUG == true then | ||
732 | local fps = screen_redraw_count * 100 / screen_redraw_duration | ||
733 | disp_msg(rb.HZ * 5, "Redraw: %d fps", fps) | ||
734 | end | ||
571 | 735 | ||
572 | if exit then | 736 | if is_exit then |
573 | break -- Exiting.. | 737 | break -- Exiting.. |
574 | else | 738 | else |
575 | highscore = calc_score(highscore, idx, goal, nrBalls_expend) | 739 | highscore, score, bonus = calc_score(highscore, idx, goal, nrBalls_expend) |
576 | if nrBalls_expend >= goal then | 740 | if nrBalls_expend >= goal then |
577 | disp_msg(rb.HZ * 2, "You won!") | 741 | if bonus == 0 then |
742 | disp_msg(rb.HZ * 2, "You won!") | ||
743 | else | ||
744 | disp_msg(rb.HZ * 2, "You won BONUS!") | ||
745 | end | ||
578 | levels[idx] = nil | 746 | levels[idx] = nil |
579 | idx = idx + 1 | 747 | idx = idx + 1 |
580 | else | 748 | else |
581 | disp_msg(rb.HZ * 2, "You lost %d points!", score + (idx * 100)) | 749 | disp_msg(rb.HZ * 2, "You lost %d points!", -score) |
582 | if highscore < 0 then break end | 750 | if highscore < 0 then break end |
583 | end | 751 | end |
584 | end | 752 | end |
@@ -594,3 +762,7 @@ end | |||
594 | 762 | ||
595 | -- Restore user backlight settings | 763 | -- Restore user backlight settings |
596 | rb.backlight_use_settings() | 764 | rb.backlight_use_settings() |
765 | if rb.cpu_boost then rb.cpu_boost(false) end | ||
766 | |||
767 | os.exit() | ||
768 | -------------------------------------------------------------------------------- | ||