Glimmer Tetris just got a High Score dialog (replacing the Game Over dialog) and got enhanced to save/load high scores to/from disk (tab delimited format). It uses the user directory (dumping a .glimmer-tetris/high_scores.txt file) to use the same security permissions as the current user. If writing fails for any reason, it fails gracefully, defaulting to memory storage of high scores.
Otherwise, Glimmer Tetris got more menus:
- View (to show/clear high scores)
- Options (to enable/disable beeping)
- Help (to show about dialog)
Seeing is believing!
Updated Model::Game logic for saving/loading high scores (relies on automatic observation support of arrays in Glimmer):
class Tetris | |
module Model | |
PastGame = Struct.new(:name, :score) | |
end | |
end | |
class Tetris | |
module Model | |
class Game | |
# more code precedes | |
def game_over! | |
add_high_score! | |
beep | |
self.game_over = true | |
end | |
def clear_high_scores! | |
high_scores.clear | |
end | |
def add_high_score! | |
self.added_high_score = true | |
high_scores.prepend(PastGame.new("Player #{high_scores.count + 1}", score)) | |
end | |
def save_high_scores! | |
high_score_file_content = @high_scores.map {|past_game| past_game.to_a.join("\t") }.join("\n") | |
FileUtils.mkdir_p(tetris_dir) | |
File.write(tetris_high_score_file, high_score_file_content) | |
rescue => e | |
# Fail safely by keeping high scores in memory if unable to access disk | |
Glimmer::Config.logger.error {"Failed to save high scores in: #{tetris_high_score_file}\n#{e.full_message}"} | |
end | |
def load_high_scores! | |
if File.exist?(tetris_high_score_file) | |
self.high_scores = File.read(tetris_high_score_file).split("\n").map {|line| PastGame.new(*line.split("\t")) } | |
end | |
rescue => e | |
# Fail safely by keeping high scores in memory if unable to access disk | |
Glimmer::Config.logger.error {"Failed to load high scores from: #{tetris_high_score_file}\n#{e.full_message}"} | |
end | |
def tetris_dir | |
@tetris_dir ||= File.join(Etc.getpwuid.dir, '.glimmer-tetris') | |
end | |
def tetris_high_score_file | |
File.join(tetris_dir, "high_scores.txt") | |
end | |
# more code succeeds | |
end | |
end | |
end | |
New high_score_dialog custom shell (replacing game_over_dialog):
# From: https://github.com/AndyObtiva/glimmer-dsl-swt/blob/v4.18.3.2/samples/elaborate/tetris/view/high_score_dialog.rb | |
require_relative 'tetris_menu_bar' | |
class Tetris | |
module View | |
class HighScoreDialog | |
include Glimmer::UI::CustomShell | |
options :parent_shell, :game | |
after_body { | |
@game_over_observer = observe(game, :game_over) do |game_over| | |
close if !game_over | |
end | |
} | |
body { | |
dialog(parent_shell) { | |
row_layout { | |
type :vertical | |
center true | |
} | |
text 'Tetris' | |
tetris_menu_bar(game: game) | |
label(:center) { | |
text bind(game, :game_over) {|game_over| game_over ? 'Game Over!' : 'High Scores'} | |
font name: FONT_NAME, height: FONT_TITLE_HEIGHT, style: FONT_TITLE_STYLE | |
} | |
@high_score_table = table { | |
layout_data { | |
height 100 | |
} | |
table_column { | |
text 'Name' | |
} | |
table_column { | |
text 'Score' | |
} | |
items bind(game, :high_scores), column_properties(:name, :score) | |
} | |
composite { | |
row_layout :horizontal | |
button { | |
text 'Clear' | |
on_widget_selected { | |
game.clear_high_scores! | |
} | |
} | |
@play_close_button = button { | |
text bind(game, :game_over) {|game_over| game_over ? 'Play Again?' : 'Close'} | |
focus true # initial focus | |
on_widget_selected { | |
close | |
game.restart! if game.game_over? | |
} | |
} | |
} | |
on_swt_show { | |
if game.game_over? && game.added_high_score? | |
game.added_high_score = false | |
@high_score_table.edit_table_item( | |
@high_score_table.items.first, # row item | |
0, # column | |
after_write: -> { | |
game.save_high_scores! | |
@play_close_button.set_focus | |
}, | |
after_cancel: -> { | |
@play_close_button.set_focus | |
}, | |
) | |
end | |
} | |
on_shell_closed { | |
@high_score_table.cancel_edit! | |
} | |
on_widget_disposed { | |
@game_over_observer.deregister | |
} | |
} | |
} | |
end | |
end | |
end |
Updated tetris_menu_bar custom widget:
All of this ships with Glimmer DSL for SWT v4.18.3.3 as part of the following changes:
- Tetris High Scores
- Tetris Modify High Score Player Name
- Tetris Show High Scores (Menu Item + Accelerator)
- Tetris add a menu item with beep enablement option
- Tetris Clear High Scores
- Tetris Add left and right alt (option) buttons as alternative to shift for rotation. Use left ctrl as rotate left. Use a, s, d as left, down, right.
- Fix issues relating to setting parenthood with custom widgets before building their body (instead of after)
- Fix issues relating to not respecting arity of passed in table editing callbacks: before_write, after_write, and after_cancel
Happy Glimmering!
Check out last: Glimmer Tetris Icon via Image Shape DSL + Instant Down
This article is part of the Tetris Saga
No comments:
Post a Comment