[[目次へもどる>PuyoPuyo]]
* 回転させよう(Cycle編) [#l1ea176e]
#contents

うんじゃあまあ次はサイクルブロックの回転を考えよう.
とはいってもサイクルブロックの回転はほとんど考える事がない.
なぜなら四つ組みの中ですべて簡潔しているからである.
 b1 b2    b0 b1
 b0 b3 => b3 b2
テーブルの状況に一切影響を受けない.
もちろんこれは必ず4個のブロックが存在するという制約の下での事である.
ピボットブロックの制約と同様に今回もこの制約を満たすときのみを考える.

サイクルブロックの回転を一つ一つのブロックの移動でみたとき,回転ではなく単なる縦移動,もしくは横移動に過ぎないことがわかる.
であれば,ピボットブロックの回転で考えた回転アニメーションを使ってサイクルブロックの回転を表現するにはプッシュシフトの概念を使ってしまえば楽そうである.

よって今までx方向のみに用意したプッシュシフトをy方向にも追加する.
そしてプッシュシフトっていう名前もなんか違う感じになるので,xシフト,yシフトと呼ぶことにしよう.
#sh(ruby){{
class FreeBlock < Block
  def set_rotate_x(from, to, time, xshift)
    # x : rotate distance list based on to
    from_rad = from * Math::PI / 180
    to_rad = to * Math::PI / 180
    time_divide = (to_rad - from_rad) / time
    shift = Math.cos(to_rad) * @block_s
    xs_divide = (xshift * @block_s).quo time
    rotate = []
    rad = from_rad
    xs = xshift * @block_s
    time.times do
      rad += time_divide
      xs -= xs_divide
      rotate.push(Math.cos(rad) * @block_s - shift - xs)
    end
    return rotate
  end

  def set_rotate_y(from, to, time, yshift)
    # y : rotate speed list base on from
    from_rad = from * Math::PI / 180
    to_rad = to * Math::PI / 180
    time_divide = (to_rad - from_rad) / time
    ys_divide = (yshift * @block_s).quo time
    rotate = []
    rad = from_rad
    time.times do
      old = rad
      rad += time_divide
      rotate.push((Math.sin(rad) - Math.sin(old)) * @block_s + ys_divide)
    end
    return rotate
  end

  def set_rotate(from, to, time, xshift, yshift)
    @rotate_x = set_rotate_x(from, to, time, xshift)
    @rotate_y = set_rotate_y(from, to, time, yshift)
  end
end
}}
set_rotate_xについてはpush_shiftの名前が変わっただけで処理は全く同じである.

set_rotate_yはx方向とは違って毎フレームの移動量を配列としてセットするので,
全体のyシフト量をフレーム数で割ったys_divideを今までの移動量に付加すれば良い.

あとはサイクルブロックの回転処理を定義すれば終わりだ.
#sh(ruby){{
class CycleBlock < Block
  def can_rotate?(ir, table, row_s)
    return ir == 0 ? false : ir
  end

  def rotate(ir, time)
    @blocks.rotate!(-ir)
    @blocks.each.with_index do |block, i|
      next unless block
      case i
      when 0; shift = ir > 0 ? [-1, 0] : [ 0,-1]
      when 1; shift = ir > 0 ? [ 0, 1] : [-1, 0]
      when 2; shift = ir > 0 ? [ 1, 0] : [ 0, 1]
      when 3; shift = ir > 0 ? [ 0,-1] : [ 1, 0]
      end
      block.set_rotate(0, 0, time, *shift)
      block.row += shift[0]
    end
  end
end
}}
can_rotate?メソッドは入力があるかないかだけでチェック終了であり,回転方向を返す.
rotateメソッドは回転方向とアニメーション時間を受け取る.
ピボットブロックと同様に回転方向に基づいてまずは配列自体を回転させる.
その後は回転後の位置を元にブロック自体の位置を実際に更新する.
処理手順はピボットブロックと同じ.
ただし,移動はシフトのみでよく,回転は必要ないので,初期角度と終了角度はともに0を指定する.

** 実行 [#f206490f]
四つ組みだけこられると連鎖なんて組めないな.
#media(PuyoPuyoChap17/PuyoPuyoChap17.flv);
ちなみにフィーバーだと四つ組みの場合は必ず2色のペアになる.


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