ControlBlock?(落下編) †よし,一通りアニメーションして満足したのでいよいよブロックを操作して連鎖がくめるようにしよう. 操作できるブロックという意味でControlBlock?と名付けた. class ControlBlock def initialize init_blocks end def init_blocks @pivot = nil @belongs = [] end def set(pivot, *belongs) @pivot = pivot @belongs = belongs end def blocks return [@pivot, *@belongs].compact end end コントロールブロックは回転させる際,軸となるブロックが存在するのでその軸のブロックを@pivotに,それ以外のブロックを@belongsに配列として持つ. フィールドにコントロールブロックを与える. class Field def initialize(row_s, line_s, block_s) @row_s = row_s @line_s = line_s @block_s = block_s @fallen = false @eliminated = false @ctrl_block = ControlBlock.new init_table init_blocklist init_connect_table end def start_control_block(colors) pivot = Block.new(colors.sample) belong = Block.new(colors.sample) @ctrl_block.set(pivot, belong) @ctrl_block.start end end そしてフィールドコントローラーのフェイズに:control_blockを追加する. class FieldController def initialize(x,y,row_s = 6, line_s = 12, block_s = 16) @x = x; @y = y @wait = 0 @colors = [:r, :g, :b, :y] @row_s = row_s; @line_s = line_s; @block_s = block_s init_field init_phase end def init_phase @phase = Phase.new # added :control_block handler @phase.add_start_handler(:control_block, method(:start_control_block)) # added :falldown handler @phase.add_condition_handler(:falldown, :eliminate, method(:falldown_eliminate_cond)) # added :elimiate handler @phase.add_condition_handler(:eliminate, :falldown, method(:eliminate_falldown_cond)) @phase.add_condition_handler(:eliminate, :control_block, method(:eliminate_control_block_cond)) @phase.change :control_block end def start_control_block @field.start_control_block(@colors) end def update_control_block @field.update_control_block end end (注意)今までフィールドのサイズはクラス変数で持っていたが,例えばプレイヤーごとにでかぷよorちびぷよでプレイなどの状況も考え得るのでインスタンス変数として持つことにした. また,@colorsも追加されている.これもプレイヤーごとの難易度に対応して色数が変化できるようにインスタンス変数で保持している. コントロールブロックを落下させる †まずは出現したコントロールブロックを自然落下させてみよう. 動きは単純で一定の速度で落ちていくだけである. ひとまず落下についてはすでに定義したアニメーションmove_yを使って1マスずつ落としていくことにする. class ControlBlock def falldown(speed, block_s) blocks.each do |block| y = block.line * block_s block.set_move_y(y, y - block_s, speed) block.line -= 1 end end end 一マス分のfalldownアニメーションをセットする.セットしたアニメーションが終了したらまたこのメソッドを呼べば良い. これでコントロールブロックは落ちてくるが,ただ落下させるのではなくすでに配置されているブロックが下にあれば止まらなければならない. そこで落下可能かチェックするメソッドcan_falldown?を定義した. このメソッドは現在のフィールドのテーブルを参照してチェックを行う. class ControlBlock def can_falldown?(table) blocks.group_by{|block| block.row}.each do |row, blks| min_line = blks.min_by{|blk| blk.line}.line return false if table[row].size >= min_line end return true end end さてこれは何をやっているか. まずコントロールブロックを列でグループ分けしている. そしてそれぞれのグループに対してその中で最も下にあるブロックの列を取得する. その列がテーブルの同じ列にいるブロックの高さより一つ大きいだけかそれよりも小さければ落下することができないという事になる. 実行 †じゃあとりあえず動作確認してみよう. Loading the player ...
空中にブロックがあるのは初期テーブルのセットをわざとおかしくして落下のあたり判定がちゃんとできてるか確認するため. たしかに途中で落下が止まることが確認できる. |