Class: GlimmerTetris::Model::Game
- Inherits:
-
Object
- Object
- GlimmerTetris::Model::Game
- Defined in:
- app/glimmer_tetris/model/game.rb
Constant Summary collapse
- PLAYFIELD_WIDTH =
10
- PLAYFIELD_HEIGHT =
20
- PREVIEW_PLAYFIELD_WIDTH =
4
- PREVIEW_PLAYFIELD_HEIGHT =
2
- SCORE_MULTIPLIER =
{1 => 40, 2 => 100, 3 => 300, 4 => 1200}
Instance Attribute Summary collapse
-
#added_high_score ⇒ Object
(also: #added_high_score?)
Returns the value of attribute added_high_score.
-
#beeping ⇒ Object
(also: #beeping?)
Returns the value of attribute beeping.
-
#game_over ⇒ Object
(also: #game_over?)
Returns the value of attribute game_over.
-
#high_scores ⇒ Object
Returns the value of attribute high_scores.
-
#level ⇒ Object
Returns the value of attribute level.
-
#lines ⇒ Object
Returns the value of attribute lines.
-
#paused ⇒ Object
(also: #paused?)
Returns the value of attribute paused.
-
#playfield_height ⇒ Object
readonly
Returns the value of attribute playfield_height.
-
#playfield_width ⇒ Object
readonly
Returns the value of attribute playfield_width.
-
#preview_tetromino ⇒ Object
Returns the value of attribute preview_tetromino.
-
#score ⇒ Object
Returns the value of attribute score.
-
#show_high_scores ⇒ Object
Returns the value of attribute show_high_scores.
-
#up_arrow_action ⇒ Object
Returns the value of attribute up_arrow_action.
Instance Method Summary collapse
- #add_high_score! ⇒ Object
- #beep ⇒ Object
- #calculate_score!(eliminated_lines) ⇒ Object
- #clear_high_scores! ⇒ Object
- #configure_beeper(&beeper) ⇒ Object
- #consider_adding_tetromino ⇒ Object
- #consider_eliminating_lines ⇒ Object
- #current_tetromino ⇒ Object
- #delay ⇒ Object
- #down!(instant: false) ⇒ Object
- #game_in_progress? ⇒ Boolean
- #game_over! ⇒ Object
-
#hypothetical(&block) ⇒ Object
Executes a hypothetical scenario without truly changing playfield permanently.
-
#hypothetical? ⇒ Boolean
Returns whether currently executing a hypothetical scenario.
- #hypothetical_playfield ⇒ Object
-
#initialize(playfield_width = PLAYFIELD_WIDTH, playfield_height = PLAYFIELD_HEIGHT) ⇒ Game
constructor
A new instance of Game.
- #instant_down_on_up ⇒ Object
- #instant_down_on_up=(value) ⇒ Object
- #left! ⇒ Object
- #level_up! ⇒ Object
- #load_high_scores! ⇒ Object
-
#playfield ⇒ Object
Returns blocks in the playfield.
- #playfield_remaining_heights(tetromino = nil) ⇒ Object
- #preview_next_tetromino! ⇒ Object
- #preview_playfield ⇒ Object
- #reset_playfield ⇒ Object
- #reset_preview_playfield ⇒ Object
- #reset_tetrominoes ⇒ Object
- #right! ⇒ Object
- #rotate!(direction) ⇒ Object
- #rotate_left_on_up ⇒ Object
- #rotate_left_on_up=(value) ⇒ Object
- #rotate_right_on_up ⇒ Object
- #rotate_right_on_up=(value) ⇒ Object
- #save_high_scores! ⇒ Object
- #start! ⇒ Object (also: #restart!)
- #tetris_dir ⇒ Object
- #tetris_high_score_file ⇒ Object
- #tetrominoes ⇒ Object
Constructor Details
#initialize(playfield_width = PLAYFIELD_WIDTH, playfield_height = PLAYFIELD_HEIGHT) ⇒ Game
Returns a new instance of Game.
47 48 49 50 51 52 53 54 55 |
# File 'app/glimmer_tetris/model/game.rb', line 47 def initialize(playfield_width = PLAYFIELD_WIDTH, playfield_height = PLAYFIELD_HEIGHT) @playfield_width = playfield_width @playfield_height = playfield_height @high_scores = [] @show_high_scores = false @beeping = true @up_arrow_action = :rotate_left load_high_scores! end |
Instance Attribute Details
#added_high_score ⇒ Object Also known as: added_high_score?
Returns the value of attribute added_high_score.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def added_high_score @added_high_score end |
#beeping ⇒ Object Also known as: beeping?
Returns the value of attribute beeping.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def beeping @beeping end |
#game_over ⇒ Object Also known as: game_over?
Returns the value of attribute game_over.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def game_over @game_over end |
#high_scores ⇒ Object
Returns the value of attribute high_scores.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def high_scores @high_scores end |
#level ⇒ Object
Returns the value of attribute level.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def level @level end |
#lines ⇒ Object
Returns the value of attribute lines.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def lines @lines end |
#paused ⇒ Object Also known as: paused?
Returns the value of attribute paused.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def paused @paused end |
#playfield_height ⇒ Object (readonly)
Returns the value of attribute playfield_height.
40 41 42 |
# File 'app/glimmer_tetris/model/game.rb', line 40 def playfield_height @playfield_height end |
#playfield_width ⇒ Object (readonly)
Returns the value of attribute playfield_width.
40 41 42 |
# File 'app/glimmer_tetris/model/game.rb', line 40 def playfield_width @playfield_width end |
#preview_tetromino ⇒ Object
Returns the value of attribute preview_tetromino.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def preview_tetromino @preview_tetromino end |
#score ⇒ Object
Returns the value of attribute score.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def score @score end |
#show_high_scores ⇒ Object
Returns the value of attribute show_high_scores.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def show_high_scores @show_high_scores end |
#up_arrow_action ⇒ Object
Returns the value of attribute up_arrow_action.
41 42 43 |
# File 'app/glimmer_tetris/model/game.rb', line 41 def up_arrow_action @up_arrow_action end |
Instance Method Details
#add_high_score! ⇒ Object
90 91 92 93 |
# File 'app/glimmer_tetris/model/game.rb', line 90 def add_high_score! self.added_high_score = true high_scores.prepend(PastGame.new("Player #{high_scores.count + 1}", score, lines, level)) end |
#beep ⇒ Object
204 205 206 |
# File 'app/glimmer_tetris/model/game.rb', line 204 def beep @beeper&.call if beeping end |
#calculate_score!(eliminated_lines) ⇒ Object
191 192 193 194 |
# File 'app/glimmer_tetris/model/game.rb', line 191 def calculate_score!(eliminated_lines) new_score = SCORE_MULTIPLIER[eliminated_lines] * (level + 1) self.score += new_score end |
#clear_high_scores! ⇒ Object
86 87 88 |
# File 'app/glimmer_tetris/model/game.rb', line 86 def clear_high_scores! high_scores.clear end |
#configure_beeper(&beeper) ⇒ Object
57 58 59 |
# File 'app/glimmer_tetris/model/game.rb', line 57 def configure_beeper(&beeper) @beeper = beeper end |
#consider_adding_tetromino ⇒ Object
252 253 254 255 256 257 |
# File 'app/glimmer_tetris/model/game.rb', line 252 def consider_adding_tetromino if tetrominoes.empty? || current_tetromino.stopped? preview_tetromino.launch! preview_next_tetromino! end end |
#consider_eliminating_lines ⇒ Object
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'app/glimmer_tetris/model/game.rb', line 259 def consider_eliminating_lines eliminated_lines = 0 playfield.each_with_index do |row, playfield_row| if row.all? {|block| !block.clear?} eliminated_lines += 1 shift_blocks_down_above_row(playfield_row) end end if eliminated_lines > 0 beep self.lines += eliminated_lines level_up! calculate_score!(eliminated_lines) end end |
#current_tetromino ⇒ Object
142 143 144 |
# File 'app/glimmer_tetris/model/game.rb', line 142 def current_tetromino tetrominoes.last end |
#delay ⇒ Object
200 201 202 |
# File 'app/glimmer_tetris/model/game.rb', line 200 def delay [1.1 - (level.to_i * 0.1), 0.001].max end |
#down!(instant: false) ⇒ Object
121 122 123 124 125 |
# File 'app/glimmer_tetris/model/game.rb', line 121 def down!(instant: false) return unless game_in_progress? current_tetromino.down!(instant: instant) game_over! if current_tetromino.row <= 0 && current_tetromino.stopped? end |
#game_in_progress? ⇒ Boolean
61 62 63 |
# File 'app/glimmer_tetris/model/game.rb', line 61 def game_in_progress? !game_over? && !paused? end |
#game_over! ⇒ Object
80 81 82 83 84 |
# File 'app/glimmer_tetris/model/game.rb', line 80 def game_over! add_high_score! beep self.game_over = true end |
#hypothetical(&block) ⇒ Object
Executes a hypothetical scenario without truly changing playfield permanently
160 161 162 163 164 |
# File 'app/glimmer_tetris/model/game.rb', line 160 def hypothetical(&block) @playfield = hypothetical_playfield block.call @playfield = @original_playfield end |
#hypothetical? ⇒ Boolean
Returns whether currently executing a hypothetical scenario
167 168 169 |
# File 'app/glimmer_tetris/model/game.rb', line 167 def hypothetical? @playfield != @original_playfield end |
#hypothetical_playfield ⇒ Object
171 172 173 174 175 176 177 |
# File 'app/glimmer_tetris/model/game.rb', line 171 def hypothetical_playfield @playfield_height.times.map { |row| @playfield_width.times.map { |column| playfield[row][column].clone } } end |
#instant_down_on_up ⇒ Object
212 213 214 |
# File 'app/glimmer_tetris/model/game.rb', line 212 def instant_down_on_up self.up_arrow_action == :instant_down end |
#instant_down_on_up=(value) ⇒ Object
208 209 210 |
# File 'app/glimmer_tetris/model/game.rb', line 208 def instant_down_on_up=(value) self.up_arrow_action = :instant_down if value end |
#left! ⇒ Object
132 133 134 135 |
# File 'app/glimmer_tetris/model/game.rb', line 132 def left! return unless game_in_progress? current_tetromino.left! end |
#level_up! ⇒ Object
196 197 198 |
# File 'app/glimmer_tetris/model/game.rb', line 196 def level_up! self.level += 1 if lines >= self.level*10 end |
#load_high_scores! ⇒ Object
104 105 106 107 108 109 110 111 |
# File 'app/glimmer_tetris/model/game.rb', line 104 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.}"} end |
#playfield ⇒ Object
Returns blocks in the playfield
151 152 153 154 155 156 157 |
# File 'app/glimmer_tetris/model/game.rb', line 151 def playfield @playfield ||= @original_playfield = @playfield_height.times.map { @playfield_width.times.map { Block.new } } end |
#playfield_remaining_heights(tetromino = nil) ⇒ Object
275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'app/glimmer_tetris/model/game.rb', line 275 def playfield_remaining_heights(tetromino = nil) @playfield_width.times.map do |playfield_column| bottom_most_block = tetromino.bottom_most_block_for_column(playfield_column) (playfield.each_with_index.detect do |row, playfield_row| !row[playfield_column].clear? && ( tetromino.nil? || bottom_most_block.nil? || (playfield_row > tetromino.row + bottom_most_block[:row_index]) ) end || [nil, @playfield_height])[1] end.to_a end |
#preview_next_tetromino! ⇒ Object
187 188 189 |
# File 'app/glimmer_tetris/model/game.rb', line 187 def preview_next_tetromino! self.preview_tetromino = Tetromino.new(self) end |
#preview_playfield ⇒ Object
179 180 181 182 183 184 185 |
# File 'app/glimmer_tetris/model/game.rb', line 179 def preview_playfield @preview_playfield ||= PREVIEW_PLAYFIELD_HEIGHT.times.map {|row| PREVIEW_PLAYFIELD_WIDTH.times.map {|column| Block.new } } end |
#reset_playfield ⇒ Object
236 237 238 239 240 241 242 |
# File 'app/glimmer_tetris/model/game.rb', line 236 def reset_playfield playfield.each do |row| row.each do |block| block.clear end end end |
#reset_preview_playfield ⇒ Object
244 245 246 247 248 249 250 |
# File 'app/glimmer_tetris/model/game.rb', line 244 def reset_preview_playfield preview_playfield.each do |row| row.each do |block| block.clear end end end |
#reset_tetrominoes ⇒ Object
232 233 234 |
# File 'app/glimmer_tetris/model/game.rb', line 232 def reset_tetrominoes @tetrominoes = [] end |
#right! ⇒ Object
127 128 129 130 |
# File 'app/glimmer_tetris/model/game.rb', line 127 def right! return unless game_in_progress? current_tetromino.right! end |
#rotate!(direction) ⇒ Object
137 138 139 140 |
# File 'app/glimmer_tetris/model/game.rb', line 137 def rotate!(direction) return unless game_in_progress? current_tetromino.rotate!(direction) end |
#rotate_left_on_up ⇒ Object
228 229 230 |
# File 'app/glimmer_tetris/model/game.rb', line 228 def rotate_left_on_up self.up_arrow_action == :rotate_left end |
#rotate_left_on_up=(value) ⇒ Object
224 225 226 |
# File 'app/glimmer_tetris/model/game.rb', line 224 def rotate_left_on_up=(value) self.up_arrow_action = :rotate_left if value end |
#rotate_right_on_up ⇒ Object
220 221 222 |
# File 'app/glimmer_tetris/model/game.rb', line 220 def rotate_right_on_up self.up_arrow_action == :rotate_right end |
#rotate_right_on_up=(value) ⇒ Object
216 217 218 |
# File 'app/glimmer_tetris/model/game.rb', line 216 def rotate_right_on_up=(value) self.up_arrow_action = :rotate_right if value end |
#save_high_scores! ⇒ Object
95 96 97 98 99 100 101 102 |
# File 'app/glimmer_tetris/model/game.rb', line 95 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.}"} end |
#start! ⇒ Object Also known as: restart!
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'app/glimmer_tetris/model/game.rb', line 65 def start! self.show_high_scores = false self.paused = false self.level = 1 self.score = 0 self.lines = 0 reset_playfield reset_preview_playfield reset_tetrominoes preview_next_tetromino! consider_adding_tetromino self.game_over = false end |
#tetris_dir ⇒ Object
113 114 115 |
# File 'app/glimmer_tetris/model/game.rb', line 113 def tetris_dir @tetris_dir ||= File.join(File.('~'), '.glimmer-tetris') end |
#tetris_high_score_file ⇒ Object
117 118 119 |
# File 'app/glimmer_tetris/model/game.rb', line 117 def tetris_high_score_file File.join(tetris_dir, "high_scores.txt") end |
#tetrominoes ⇒ Object
146 147 148 |
# File 'app/glimmer_tetris/model/game.rb', line 146 def tetrominoes @tetrominoes ||= reset_tetrominoes end |