[[目次へもどる>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色のペアになる.