フェーズ管理を便利にしよう †アニメーションもできてなかなか良くなってきた. が,ここで現状のフェーズ管理について考えてみる. まず現在フェーズは:falldownと:eliminateの二つがあり, それぞれ次のフェーズに移るには
この条件を満たさなければならない. また,次のチャクターでは操作ブロックを導入するが,これのフェーズ:control_blockに遷移した際,まずは操作ブロックを作らなければならない. これらをまとめると,フェーズの遷移には次の項目が予想される.
これらの処理を,フェーズ遷移メソッドを呼ぶだけで全部やってくれる人が居たらすごい親切でうれしい. そんな人いるのかと思ったら作ればよい. 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 これでフェーズの管理が容易になった. 必然的に開始処理や終了処理が分割され,かつフェーズの遷移部分も遷移するフェーズのみが記述されるのですっきりしたコードになる. |