[[目次へもどる>PuyoPuyo]] * ガタガタする [#l8af88a6] #contents ここで少し気になった部分があった. サイクルブロックだが,回転するときにガタガタするときがある. それは以下のような場合である. b1 b2 b0 b3 B0 ----- 上記の様な状態で右に回転させると, rowはすぐに反映され,lineはアニメーションに基づいて決定される. よって回転操作直後は一時的に以下のようなブロックの配置になる. [ ] b1/b2 b0/b3 [ ] B0 ----------- このため,コントロールブロックが1ブロック分だけ落下できる事になり,数フレーム下がる. その後,回転アニメーションが進み,回転後の配置になるためめり込み修正が入り, コントロールブロックが上昇する. この現象によって回転時にガタガタしてしまう. これを回避するために,サイクルブロックについて落下可能判定時にある種のバウンディングボックスを考える. すなわち,サイクルブロックは常にブロック4個分の正方形からなるコントロールブロックなので,ブロック1個単位のあたり判定で落下可能か判断するのではなく, 最も下にあるブロックのlineをコントロールブロック全体のあたり判定として判定する. そんじゃまあ実装しましょう. #sh(ruby){{ class CycleControlBlock < ControlBlock def can_falldown?(table, block_s) min_y = [@blocks[0], @blocks[3]].min_by{|block| block.draw_pos[1] }.draw_pos[1] row = @blocks[0].row fall_ys = [row, row + 1].map{|row| min_y >= 0 ? min_y - table[row].size * block_s : min_y } # fall_ys == 0 : can not fall # > 0 : fall y # < 0 : dent y return fall_ys.min end end }} サイクルブロックの下にあるのはb0とb3なのでそいつらだけを取り出し,小さい方のy座標を取得する((右回転ならb0,左回転ならb1が最小になるはず)). そしたらそれを基準にしてコントロールブロックの左側と右側両方のfall_ysを取得し,小さい方を返す((今思ったんだが,ysってなんだ?あ,複数のy座標って意味か.我ながら意味不明なネーミングしてるな)). あとは横移動に関しても同様にバウンディングボックスの概念をもちいて改造. #sh(ruby){{ class CycleControlBlock < ControlBlock def can_move_row?(imr, table, row_s) return false if imr == 0 # no move min_line = [@blocks[0], @blocks[3]].min_by{|block| block.draw_pos[1] }.line row_left = @blocks[0].row; row_right = @blocks[3].row [min_line, min_line + 1].each do |line| if imr > 0 # move right return false if row_right >= row_s - 1 return false if table[row_right + 1][line] else # move left return false if row_left <= 0 return false if table[row_left - 1][line] end end return true end end }} 一番下のlineを元にバウンディングボックスを作る. rowは特に問題ないので,左右で決め打ちできる. ** 実行 [#y6eda6d8] おおガタガタしない. #media(PuyoPuyoChap22/PuyoPuyoChap22.flv);