目次へもどる

フェーズ管理を便利にしよう

アニメーションもできてなかなか良くなってきた. が,ここで現状のフェーズ管理について考えてみる.

まず現在フェーズは:falldownと:eliminateの二つがあり, それぞれ次のフェーズに移るには

  1. すべてのブロックの落下アニメーションが終わっているか
  2. すべてのブロックのコラプスが終わっているか

この条件を満たさなければならない. また,次のチャクターでは操作ブロックを導入するが,これのフェーズ:control_blockに遷移した際,まずは操作ブロックを作らなければならない.

これらをまとめると,フェーズの遷移には次の項目が予想される.

  1. フェーズが遷移した時の開始処理
  2. フェーズが遷移するための条件(満たさない場合は満たすまでウェイト)
  3. フェーズが遷移する時の終了処理

これらの処理を,フェーズ遷移メソッドを呼ぶだけで全部やってくれる人が居たらすごい親切でうれしい. そんな人いるのかと思ったら作ればよい.

class Phase
  def initialize
    @start_handler = {}           # call method when phase starting
    @end_handler = {}             # call method before phase changing
    @trans_condition_handler = {} # call method of phase change condition
    @phase = nil                  # present phase
    @next_phase = nil             # next phase
  end

  def add_start_handler(phase, method)
    @start_handler[phase] = method
  end
  def add_end_handler(phase, method)
    @end_handler[phase] = method
  end
  def add_condition_handler(prephase, nextphase, cond)
    @trans_condition_handler[[prephase,nextphase]] = cond
  end

  def phase
    @next_phase ? :phase_trans : @phase
  end

  def trans_condition_check
    cond = @trans_condition_handler[[@phase,@next_phase]]
    return if cond && !cond.call
    @phase = @next_phase
    @next_phase = nil
    # start handler
    method = @start_handler[@phase]
    method.call if method
  end

  def change(phase)
    # end handler
    method = @end_handler[@phase]
    method.call if method
    # set next_phase
    @next_phase = phase
    # trans condition check
    trans_condition_check
  end
end

Phaseクラスはフェーズとその遷移を管理するクラスである. @start_handlerはフェーズ名から開始処理メソッドへのハッシュであり,そのフェーズに遷移したときに開始処理メソッドを実行する.

@end_handlerはフェーズ名から終了処理メソッドへのハッシュであり,そのフェーズから異なるフェーズに遷移する際,終了処理メソッドを実行する.

@trans_condition_handlerは遷移元フェーズ名と遷移先フェーズ名のペアから遷移条件メソッドへのハッシュであり,該当するフェーズ間遷移が呼ばれたときに条件メソッドを呼び出し,その戻り値によって遷移するかどうか判断する.

もし,条件メソッドがfalseを返した場合はひとまずフェーズを:pahse_transに設定し,引き続き条件メソッドを呼び続け,trueになった時点で遷移先フェーズに移行する.

class FieldController
  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.change :falldown
  end
  def update
    update_blocks
    draw_field
    return if update_wait
    case @phase.phase
    when :phase_trans
      @phase.trans_condition_check
    when :control_block
      update_control_block
    when :falldown
      update_falldown
    when :eliminate
      update_eliminate
    end
  end
  def update_falldown
    fallen = @field.falldown
    @phase.change :eliminate
  end
  def update_eliminate
    eliminated = @field.eliminate
    @phase.change eliminated ? :falldown : :control_block
  end
  def falldown_eliminate_cond
    # wait fall animation
    !@field.blocks_move?
  end
  def eliminate_falldown_cond
    # wait collapse animation
    !@field.blocks_reasonable_collapse?
  end
end

これでフェーズの管理が容易になった. 必然的に開始処理や終了処理が分割され,かつフェーズの遷移部分も遷移するフェーズのみが記述されるのですっきりしたコードになる.


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-08-30 (金) 22:00:58 (3889d)