class Tetris::Model::Game
Constants
- PLAYFIELD_HEIGHT
- PLAYFIELD_WIDTH
- PREVIEW_PLAYFIELD_HEIGHT
- PREVIEW_PLAYFIELD_WIDTH
- SCORE_MULTIPLIER
- SPEEDS
- SPEED_INITIAL_DELAYS
- UP_ARROW_ACTIONS
Attributes
added_high_score[RW]
added_high_score?[RW]
beeping[RW]
beeping?[RW]
game_over[RW]
game_over?[RW]
high_scores[RW]
initial_delay[RW]
level[RW]
lines[RW]
paused[RW]
paused?[RW]
playfield_height[R]
playfield_width[R]
preview_tetromino[RW]
score[RW]
show_high_scores[RW]
show_preview_tetromino[RW]
show_preview_tetromino?[RW]
up_arrow_action[RW]
Public Class Methods
new(playfield_width = PLAYFIELD_WIDTH, playfield_height = PLAYFIELD_HEIGHT)
click to toggle source
# File examples/tetris/model/game.rb, line 51 def initialize(playfield_width = PLAYFIELD_WIDTH, playfield_height = PLAYFIELD_HEIGHT) @initial_delay = SPEED_INITIAL_DELAYS[:snail] @playfield_width = playfield_width @playfield_height = playfield_height @high_scores = [] @show_high_scores = false @beeping = true @up_arrow_action = :rotate_left @show_preview_tetromino = true load_high_scores! end
Public Instance Methods
add_high_score!()
click to toggle source
# File examples/tetris/model/game.rb, line 97 def add_high_score! self.added_high_score = true high_scores.prepend(PastGame.new("Player #{high_scores.count + 1}", score, lines, level)) save_high_scores! end
beep()
click to toggle source
# File examples/tetris/model/game.rb, line 212 def beep @beeper&.call if beeping end
calculate_score!(eliminated_lines)
click to toggle source
# File examples/tetris/model/game.rb, line 199 def calculate_score!(eliminated_lines) new_score = SCORE_MULTIPLIER[eliminated_lines] * (level + 1) self.score += new_score end
clear_high_scores!()
click to toggle source
# File examples/tetris/model/game.rb, line 92 def clear_high_scores! high_scores.clear save_high_scores! end
configure_beeper(&beeper)
click to toggle source
# File examples/tetris/model/game.rb, line 63 def configure_beeper(&beeper) @beeper = beeper end
consider_adding_tetromino()
click to toggle source
# File examples/tetris/model/game.rb, line 256 def consider_adding_tetromino if tetrominoes.empty? || current_tetromino.stopped? preview_tetromino.launch! preview_next_tetromino! end end
consider_eliminating_lines()
click to toggle source
# File examples/tetris/model/game.rb, line 263 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()
click to toggle source
# File examples/tetris/model/game.rb, line 150 def current_tetromino tetrominoes.last end
delay()
click to toggle source
# File examples/tetris/model/game.rb, line 208 def delay [@initial_delay - (level.to_i * 0.1), 0.001].max end
down!(instant: false)
click to toggle source
# File examples/tetris/model/game.rb, line 129 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?()
click to toggle source
# File examples/tetris/model/game.rb, line 67 def game_in_progress? !game_over? && !paused? end
game_over!()
click to toggle source
# File examples/tetris/model/game.rb, line 86 def game_over! add_high_score! beep self.game_over = true end
hypothetical(&block)
click to toggle source
Executes a hypothetical scenario without truly changing playfield permanently
# File examples/tetris/model/game.rb, line 168 def hypothetical(&block) @playfield = hypothetical_playfield block.call @playfield = @original_playfield end
hypothetical?()
click to toggle source
Returns whether currently executing a hypothetical scenario
# File examples/tetris/model/game.rb, line 175 def hypothetical? @playfield != @original_playfield end
hypothetical_playfield()
click to toggle source
# File examples/tetris/model/game.rb, line 179 def hypothetical_playfield @playfield_height.times.map { |row| @playfield_width.times.map { |column| playfield[row][column].clone } } end
left!()
click to toggle source
# File examples/tetris/model/game.rb, line 140 def left! return unless game_in_progress? current_tetromino.left! end
level_up!()
click to toggle source
# File examples/tetris/model/game.rb, line 204 def level_up! self.level += 1 if lines >= self.level*10 end
load_high_scores!()
click to toggle source
# File examples/tetris/model/game.rb, line 112 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
playfield()
click to toggle source
Returns blocks in the playfield
# File examples/tetris/model/game.rb, line 159 def playfield @playfield ||= @original_playfield = @playfield_height.times.map do @playfield_width.times.map do Block.new end end end
playfield_remaining_heights(tetromino = nil)
click to toggle source
# File examples/tetris/model/game.rb, line 279 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!()
click to toggle source
# File examples/tetris/model/game.rb, line 195 def preview_next_tetromino! self.preview_tetromino = Tetromino.new(self) end
preview_playfield()
click to toggle source
# File examples/tetris/model/game.rb, line 187 def preview_playfield @preview_playfield ||= PREVIEW_PLAYFIELD_HEIGHT.times.map {|row| PREVIEW_PLAYFIELD_WIDTH.times.map {|column| Block.new } } end
reset_playfield()
click to toggle source
# File examples/tetris/model/game.rb, line 240 def reset_playfield playfield.each do |row| row.each do |block| block.clear end end end
reset_preview_playfield()
click to toggle source
# File examples/tetris/model/game.rb, line 248 def reset_preview_playfield preview_playfield.each do |row| row.each do |block| block.clear end end end
reset_tetrominoes()
click to toggle source
# File examples/tetris/model/game.rb, line 236 def reset_tetrominoes @tetrominoes = [] end
right!()
click to toggle source
# File examples/tetris/model/game.rb, line 135 def right! return unless game_in_progress? current_tetromino.right! end
rotate!(direction)
click to toggle source
# File examples/tetris/model/game.rb, line 145 def rotate!(direction) return unless game_in_progress? current_tetromino.rotate!(direction) end
save_high_scores!()
click to toggle source
# File examples/tetris/model/game.rb, line 103 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
start!()
click to toggle source
# File examples/tetris/model/game.rb, line 71 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
Also aliased as: restart!
tetris_dir()
click to toggle source
# File examples/tetris/model/game.rb, line 121 def tetris_dir @tetris_dir ||= File.join(Dir.home, '.glimmer-tetris') end
tetris_high_score_file()
click to toggle source
# File examples/tetris/model/game.rb, line 125 def tetris_high_score_file File.join(tetris_dir, "high_scores.txt") end
tetrominoes()
click to toggle source
# File examples/tetris/model/game.rb, line 154 def tetrominoes @tetrominoes ||= reset_tetrominoes end
Private Instance Methods
shift_blocks_down_above_row(row)
click to toggle source
# File examples/tetris/model/game.rb, line 295 def shift_blocks_down_above_row(row) row.downto(0) do |playfield_row| playfield[playfield_row].each_with_index do |block, playfield_column| previous_row = playfield[playfield_row - 1] previous_block = previous_row[playfield_column] block.color = previous_block.color unless block.color == previous_block.color end end playfield[0].each(&:clear) end