[[目次へもどる>PuyoPuyo]]
* ControlBlock(落下編) [#p7772257]
#contents

よし,一通りアニメーションして満足したのでいよいよブロックを操作して連鎖がくめるようにしよう.

操作できるブロックという意味でControlBlockと名付けた.

#sh(ruby){{
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に配列として持つ.

フィールドにコントロールブロックを与える.
#sh(ruby){{
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を追加する.
#sh(ruby){{
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も追加されている.これもプレイヤーごとの難易度に対応して色数が変化できるようにインスタンス変数で保持している.

** コントロールブロックを落下させる [#d6c54472]
まずは出現したコントロールブロックを自然落下させてみよう.
動きは単純で一定の速度で落ちていくだけである.

ひとまず落下についてはすでに定義したアニメーションmove_yを使って1マスずつ落としていくことにする.
#sh(ruby){{
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?を定義した.
このメソッドは現在のフィールドのテーブルを参照してチェックを行う.
#sh(ruby){{
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
}}
さてこれは何をやっているか.
まずコントロールブロックを列でグループ分けしている.
そしてそれぞれのグループに対してその中で最も下にあるブロックの列を取得する.
その列がテーブルの同じ列にいるブロックの高さより一つ大きいだけかそれよりも小さければ落下することができないという事になる.

** 実行 [#e7f3d8d1]
じゃあとりあえず動作確認してみよう.
#media(PuyoPuyoChap10/PuyoPuyoChap10.flv);
空中にブロックがあるのは初期テーブルのセットをわざとおかしくして落下のあたり判定がちゃんとできてるか確認するため.
たしかに途中で落下が止まることが確認できる.


トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS