« Windows8の性能で気になること | トップページ | 初音ミク冒険記の「多重スクロールのバグ」対応 »

2013.02.07

初音ミク冒険記で多重スクロールを実装!(テスト動画付き)

| |コメント (0)|トラックバック (0)

 このエントリーをはてなブックマークに追加

悪魔城ドラキュラやAstlibraをやっていて
カッコイイな!
と思っていた多重スクロール。

奥行きが出てて良いじゃないか!
ということで実装してみた!

言葉での説明よりも実際に動画で見てもらった方が良いかな?
と思ったので無料のmp4プレーヤーを探したら
良さそうなのを発見!

AviUtilでテロップをつけて動画を作ってみた。
(右側に青い線があるのはキャプチャ範囲の指定をミスったためです)

動画を再生するには、videoタグをサポートしたブラウザが必要です。

さて、どうやって実装したかですが。

多重スクロールのポイントは
Astlibraのソースにコメントで書かれていた。

どうやら
プレイヤーよりも奥のレイヤ(階層)は、
奥に行くほどゆっくりスクロールし、
プレイヤーよりも手前のレイヤは、
手前に行くほどより速くスクロール
すれば良いらしい。

もともと初音ミク冒険記では
Astlibraのソースやマップエディタを参考にして
4階層にマップ画像を重ねてスクロールをしている。
(実際には他にも階層はあるんだけどマップ表示に限ると4階層なのだ)

  • 第1階層(レイヤ1):背景マップ画像
  • 第2階層(レイヤ2):背景マップ画像と
               ミクに合わせて動くマップ画像の中間の画像
  • 第3階層(レイヤ3):ミクに合わせて動くマップ画像
  • 第4階層(レイヤ4):ミクよりも手前で動くマップ画像

つまり、レイヤ3のスクロールスピードを1とした時に
レイヤ1、レイヤ2は遅く、レイヤ4は速くスクロールすれば良い。

このため、暫定的にスクロールスピードを以下のように設定する。

  • レイヤ1:レイヤ3の0.5倍
  • レイヤ2:レイヤ3の0.75倍
  • レイヤ3:スクロールの基準速度1.0倍
  • レイヤ4:レイヤ3の1.5倍

ここで初音ミク冒険記でスクロールに関わる変数たちを図解してみる。

Scrollkanren1

修正前


void scrollToLeft(float jikiposx){
//スクロール可能かをチェック
if ((int)jikiposx - SCROLL_LIMIT_LEFT_RIGHT > (int)g_stagesize.lefttop.x){
g_current_field_pos.x = jikiposx - SCROLL_LIMIT_LEFT_RIGHT;
g_framerect.lefttop.x = g_current_field_pos.x - MOVE_SIZE;
g_framerect.lefttop.y = g_current_field_pos.y - MOVE_SIZE;
g_framerect.rightbottom.x = g_current_field_pos.x + SCREEN_WIDTH + MOVE_SIZE;
g_framerect.rightbottom.y = g_current_field_pos.y + SCREEN_HEIGHT + MOVE_SIZE;
}
}

修正後


void scrollToLeft(float jikiposx){
//スクロール可能かをチェック
if ((int)jikiposx - SCROLL_LIMIT_LEFT_RIGHT > (int)g_stagesize.lefttop.x){
g_current_field_pos.x = jikiposx - SCROLL_LIMIT_LEFT_RIGHT;
// 多重スクロール対応で左右の移動のみレイヤ毎にスクロールスピードを調整する
// レイヤ3のスクロールスピードを1.0とした時に
// 奥のレイヤほどスクロールが遅く(レイヤ1とレイヤ2)、
// 手前のレイヤはスクロールが速くする(レイヤ4)
g_current_field_pos_Layer1.x = g_current_field_pos.x * 0.5f;
g_current_field_pos_Layer2.x = g_current_field_pos.x * 0.75f;
g_current_field_pos_Layer4.x = g_current_field_pos.x * 1.5f;
// 画面領域(当たり判定)の位置調整
g_framerect.lefttop.x = g_current_field_pos.x - MOVE_SIZE;
g_framerect.lefttop.y = g_current_field_pos.y - MOVE_SIZE;
g_framerect.rightbottom.x = g_current_field_pos.x + SCREEN_WIDTH + MOVE_SIZE;
g_framerect.rightbottom.y = g_current_field_pos.y + SCREEN_HEIGHT + MOVE_SIZE;
}
}

同様にscrollToRightも修正した。

次に問題となるのはデータ上の座標を
画面表示用座標に変換する関数である
XInViewとYInView関連

もともとのXInView関数


int XInView(float inx){
return (int)(inx - g_current_field_pos.x);
}

新しく作るXInViewL1関数


int XInViewL1(float inx){
return (int)(inx - g_current_field_pos_Layer1.x);
}

といった感じでレイヤ1用の関数名は最後にL1を
レイヤ2、レイヤ4用の関数名は
それぞれL2、L4をつけて作ってやる。
関数で使うg_current_field_pos_LayerXのXはレイヤ番号だ。

XInViewとYInViewはオーバーロード関数
(関数名が同じで違う型や違う数の引数を受け取る)にしているので
実際にはXInViewL1は引数がintのものとfloatのもの2種類を作成。

引数がintのXInViewL1関数


int XInViewL1(int inx){
return (inx - (int)g_current_field_pos_Layer1.x);
}

これでレイヤ1で画像描画で指定するx座標を
XInView関数→XInViewL1関数にすると良いんじゃない?

ということで動かしてみたのが先の動画の動きでした。

ここまではOKだ


 このエントリーをはてなブックマークに追加

| |コメント (0)|トラックバック (0)

このエントリーへのリンク

このエントリーのリンクを入れるHTML:

トラックバック

この記事へのトラックバックの一覧です: 初音ミク冒険記で多重スクロールを実装!(テスト動画付き):

コメント

このブログの新着コメントをRSSリーダに登録する為のxml




←名前とメールアドレスは必須です。
URLも記入すれば、URLのみが公開されます。
メールアドレスのみですと、メールアドレスが公開されてしまいますので、御注意ください。

↓コメント本文では、「a href」「b」「i」「br/」「p」「strong」「em」「ul」「ol」「li」「blockquote」「pre」のタグが使えます。絵文字をクリックすると、本文にタグを挿入できます。