目次へもどる

終止符を打とう

さて,今のままでは延々とブロックが降ってきて無限の恐怖を感じるので そろそろゲームオーバーを作ろう.

ゲームオーバーのチェック

ゲームオーバーのために必要な情報は

  • ブロックがあったらだめな位置
    これである.ここではこの位置のことをダメポイントと呼ぶ. また,フィーバーではこのダメポイントは2カ所存在する. そこで,フィールドコントローラーがフィールドを作る際, ゲームオーバーになるフィールドの位置の配列drown_areaを引数として渡すことにする. これでダメポイントを任意の位置に任意の数設定することができる. このフィールド上のダメポイントすべてをダメエリアと呼ぶことにしよう.
class FieldController
  def initialize(x,y,row_s, line_s, block_s)
    @x = x; @y = y
    @colors = [:r, :g, :b, :y]
    @row_s = row_s; @line_s = line_s; @block_s = block_s
    @drown_area = [[2,11]]
    init_control_block_manager
    init_score_manager
    init_field
    init_phase
  end
  def init_field
    @field = Field.new(@row_s, @line_s, @block_s, @drown_area, @cbm, @sm)
  end
end

そしてフィールドは受け取ったダメポイントの配列を描画などの拡張を考えたDrownPos?のインスタンスの配列に変換する. これが実際に使用するダメエリアの情報である.
check_gameoverメソッドではダメエリアにブロックがあればtrueを返す.

class Field
  def initialize(row_s, line_s, block_s, drown_area, cbm, sm)
    @row_s = row_s
    @line_s = line_s
    @block_s = block_s
    @drown_area = drown_area.map{|pos| DrownPos.new(*pos,@block_s)}
    @fallen = false
    @eliminated = false
    @cbm = cbm
    @sm = sm
    @chain = 0
    @jammer_rate = 70
    init_table
    init_jammer_manager
    init_blocklist
    init_connect_table
  end
  def draw_field(x,y)
    y = @line_s * @block_s + y
    # draw drown area
    @drown_area.each do |drown_pos|
      drown_pos.draw(x,y)
    end

    # draw blocks
    all_blocks.each do |block|
      block.draw(x,y)
    end
  end
  def check_gameover
    (@active_blocks + @jamming_blocks).any? do |block|
      m = block.row; n = block.line
      @drown_area.map{|pos| pos.to_a }.include? [m,n]
    end
  end
end

DrownPos?クラスはダメポイントの位置と描画のためにブロックサイズを保持するだけの シンプルなクラスである.

class DrownPos
  def initialize(m, n, block_s)
    @row = m; @line = n
    @block_s = block_s
  end

  def draw(ox,oy)
    x = ox + @row * @block_s
    y = oy - @line * @block_s
    screen = GameMain.screen
    screen.render_rect(x, y, @block_s, @block_s, StarRuby::Color.new(255,0,0,180))
  end

  def to_a
    [@row, @line]
  end
end

ゲームオーバーフェーズ

ゲームオーバーかどうかのチェックはできるようになったので, あとは実際にゲームオーバーにする処理を加えよう.

class FieldController
  def init_phase
    @phase = Phase.new
    (略)
    # added :gameover handler
    @phase.add_condition_handler(:gameover, method(:gameover_cond))

    @phase.change :control_block
  end
  def update
    update_blocks
    draw_field
    return if @phase.dead?
    return if @phase.waiting
    case @phase.phase
    when :phase_trans
      @phase.trans_condition_check
    when :control_block
      update_control_block
    when :falldown
      update_falldown
    when :eliminate
      update_eliminate
    when :fall_jammer
      update_fall_jammer
    when :gameover
      update_gameover
    end
  end
  def update_gameover
    @phase.wait(60)
    @phase.change :term
  end
  def gameover_cond
    @phase.kill
  end
  def dead?
    @phase.dead?
  end
end

いつものようにフェーズを追加する. いつもとことなるのはゲームオーバーフェーズのupdate_gameoverとgameover_condにある @phase.change :termと@phase.killだろう.
前者はなんのことはなく,ここでフェーズの処理が終了するので遷移先に ダミーのフェーズを与えているだけである.
後者はフェーズを殺すメソッドである. これが呼ばれるとupdateメソッドにある@phase.dead?がtrueを返すようになり, 以後フェーズの処理は行われなくなる.

class Phase
  def initialize
    (略)
    @death = false                # phase termination flag
  end
  def kill
    @death = true
  end
  def dead?
    @death
  end
end

あとはフェイスが死んだら(フィールドコントローラーが死んだら)シーンを終了すれば良い. 今はとりあえず再び同じシーンを呼び出しているが・・・.

class ScenePuyoPuyo < SceneBase
  def update
    super
    @players.each do |controller|
      controller.update
      GameMain.scene_change ScenePuyoPuyo if controller.dead?
    end

    @playtime += 1
  end
end

実行

ダメポイントにブロックが乗るとしばしの沈黙ののち淡々と次のゲームが始まる・・・.

Loading the player ...

添付ファイル: filePuyoPuyoChap29.flv 302件 [詳細]

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