diff --git a/src/info.opa b/src/info.opa index 7710d93..5aa6157 100644 --- a/src/info.opa +++ b/src/info.opa @@ -37,6 +37,15 @@ do Canvas.restore(ctx) + do Canvas.save(ctx) + do Canvas.set_font(ctx, "bold 20px Arial") + do Canvas.translate(ctx, 12+base_size*grid_width, 250) + do cft("HIGH SCORES:", 30) + do List.iter( + (score, name) -> cft(" - {name} {score}", 30), + g.scores) + do Canvas.restore(ctx) + do Canvas.save(ctx) do Canvas.set_font(ctx, "bold 20px Arial") do Canvas.translate(ctx, 2+base_size*grid_width, 0) @@ -58,7 +67,6 @@ w=2+base_size*grid_width h=2+base_size*grid_heigth do Canvas.save(ctx) - do Canvas.set_text_align(ctx, {align_center}) do Canvas.set_font(ctx, "bold {f}px Arial") do Canvas.fill_text(ctx, text, w/2, (h-f)/2) @@ -79,6 +87,31 @@ draw_game_over(ctx) = draw_in_center(ctx, "GAME OVER", some("'r' to restart")) + @private scorify(name) = + ll = String.length(name) + c1 = if ll < 1 then "_" else String.get(0, name) + c2 = if ll < 2 then "_" else String.get(1, name) + c3 = if ll < 3 then "_" else String.get(2, name) + "{c1} {c2} {c3}" + + draw_score_entry(ctx, name) = + f = 70 + w=2+base_size*grid_width + h=2+base_size*grid_heigth + do Canvas.save(ctx) + + do Canvas.set_text_align(ctx, {align_center}) + do Canvas.set_font(ctx, "bold {f}px Arial") + do Canvas.fill_text(ctx, "HIGH SCORE", w/2, (h-f)/2) + + do Canvas.set_font(ctx, "bold {f/2}px Arial") + do Canvas.fill_text(ctx, "Type your initials, submit with 'enter'", w/2, h/2) + + do Canvas.set_font(ctx, "bold 50px Arial") + do Canvas.fill_text(ctx, scorify(name), w/2, h/2+60) + do Canvas.restore(ctx) + void + draw_pause(ctx) = draw_in_center(ctx, "PAUSE", some("'space' or any direction to resume")) diff --git a/src/opacman.opa b/src/opacman.opa index 32c5542..8731755 100644 --- a/src/opacman.opa +++ b/src/opacman.opa @@ -28,6 +28,7 @@ default_game = { score = 0 lives = 3 on_steroids = none + scores = [] } : Game.status /* Game */ @@ -92,15 +93,22 @@ check_collision(g:Game.status):Game.status = lives = g.lives + (score/life_points - g.score/life_points) {g with ~ghosts ~score ~lives ~on_steroids} | {none} -> - if g.lives == 1 then - {g with - state = {game_over} + if g.lives < 2 then + scores = Scores.get() + cur_min = + if scores == [] then 0 + else List.rev(scores) |> List.head |> _.f1 + state = + if g.score > cur_min then {score=""} + else {game_over} + {g with ~scores ~state lives = 0} else {default_game with food = g.food score = g.score - lives = g.lives-1} + lives = g.lives-1 + scores = Scores.get()} @client clean_frame(ctx:Canvas.context) = Canvas.clear_rect( @@ -112,7 +120,7 @@ check_collision(g:Game.status):Game.status = t = Date.now() |> Date.in_milliseconds t = t / 100 t = t - (t/10)*10 - if t > 5 then f() + if t > 3 then f() @client next_frame(ctx:Canvas.context)() = draw_board(g) = @@ -128,6 +136,9 @@ check_collision(g:Game.status):Game.status = | {game_over} -> do blink(->Info.draw_game_over(ctx)) g + | {score=name} -> + do blink(->Info.draw_score_entry(ctx, name)) + g | {pause} -> do blink(->Info.draw_pause(ctx)) g @@ -151,7 +162,7 @@ check_collision(g:Game.status):Game.status = @client keyfun(e) = g = game.get() p = g.pacman - do Dom.transform([#debug <- "{e.key_code}"]) + // do Dom.transform([#debug <- "{e.key_code}"]) dir_key = key_to_dir(e.key_code ? -1) p = match (p.base.dir, dir_key) with | ({down}, {some={dir_up}}) -> @@ -181,7 +192,28 @@ check_collision(g:Game.status):Game.status = | _ -> p g = match (g.state, e.key_code) with // r (reset if game over) - | ({game_over}, {some=114}) -> default_game + | ({game_over}, {some=82}) -> + { default_game with scores=Scores.get() } + + // any letter for high score + | ({score=name}, {some=key}) -> + if key == 13 then + scores = Scores.add(name, g.score) + {g with ~scores state={game_over}} + else + char_idx = key - 65 + new_char = + if char_idx >= 0 && char_idx < 26 then + String.get(char_idx, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") + else "" + ll = String.length(name) + score = + if key == 8 && ll != 0 then + String.substring_unsafe(0, ll-1, name) + else if new_char == "" then name + else if ll < 3 then "{name}{new_char}" + else name + {g with state={~score}} // space (pause start) | ({running}, {some=32}) -> {g with state={pause}} @@ -201,7 +233,8 @@ check_collision(g:Game.status):Game.status = | _ -> {g with pacman=p} game.set(g) -@client init() = +@client init(scores) = + do game.set({game.get() with ~scores}) do match Canvas.get(#bg_holder) with | {none} -> void | {some=canvas} -> @@ -212,12 +245,13 @@ check_collision(g:Game.status):Game.status = | {some=canvas} -> ctx = Canvas.get_context_2d(canvas) |> Option.get t = Scheduler.make_timer(1000/fps, next_frame(ctx)) - _ = Dom.bind(Dom.select_document(), {keydown}, keyfun) + _ = Dom.bind_with_options(Dom.select_document(), {keydown}, keyfun, [{prevent_default}]) t.start() body() = width = 2+base_size*grid_width+info_width height = 2+base_size*grid_heigth + scores = Scores.get() <>