7 月 28 2008

Papervision3Dでレースゲーム制作 07 - いろいろ強化

Posted by tanjo at 6:27 PM

大変そうな壁判定はひとまず置いておき、それ以外の必要な要素を少しずつ作っていきます。

ハンドル動作

ステアリングホイールが動くようにします。
技術的には難しいこと無いです。でも、やってみて気づいたのが、キー入力 → ステアが動く → 車が旋回する …という流れのレスポンスだとか動きの細かい演出だとかって、結構ゲーム的に重要だっていうこと。0.1秒反応が違うだけで、かなり車の重さの感じ方とかは変わってきますね。それに初心者への敷居にも関係してきます。
ま、それはさておき、よくありそうなテクを使ったのでここではそのメモを。

まず、「中心を軸に画像を回転させる」方法。
別に中心じゃなくて任意の点でも同様です。
やりかたは、Bitmap > Sprite > Stage のように addChild していって、Bitmap 左上にずらした後、Sprite を回転させるだけ。今回のように常に同じ軸で回転すればいい場合は、この方法が使えます。

var steerSprite:Sprite = new Sprite();
var steerBitmap:Bitmap = new Bitmap();
steerBitmap.bitmapData = new steerImage(0, 0);
steerBitmap.x = -steerBitmap.width / 2;
steerBitmap.y = -steerBitmap.height / 2;
steerSprite.addChild(steerBitmap);
addChild(steerSprite);

steerSprite.rotation = myInputSteer;

もう1つは、「簡易トゥイーン」。
デジタルなキー入力に対して、自然な感じにステア舵角が動くようにします。

var targetSteer:Number;

//左ステア
if (keyPressLeft && !keyPressRight)
{
	targetSteer = -myFullSteer;
}
//右ステア
else if (!keyPressLeft && keyPressRight)
{
	targetSteer = myFullSteer;
}
//ステアを戻す
else
{
	targetSteer = 0;
}

//スナップ
if (Math.abs(targetSteer - myInputSteer) < 1)
{
	myInputSteer = targetSteer;
}
//目標に近づける
else
{
	myInputSteer += (targetSteer - myInputSteer) / 6;
}

なにやらいろいろ書いてありますが、要は、A を現在値、B を目標値としたとき、 A += (B - A) / n でトゥイーンさせているってだけです。目標値に近づいたときのスナップのさせ方は、もっとスマートにできるような。。。
ちなみに(疑似)荷重移動も、加速度や旋回角をもとにこのような処理をして、サスペンションっぽさを表現しています。

遠景の追加

空と地平線に絵を入れて、ちゃんと車の向きについてくるようにします。
この辺は案の定2D処理です。細長い画像を用意しておいて、車の向きに合わせてそれを横にスクロールします。車の向きは 0 ~ 359.9… 度までの値をとるようにしてあるので、図のようにループ部分を少し作っておけば、あとは自動で景色がパノラマになってくれます。

これで余裕…かと思いきや、Flash の描画仕様に起因する(?)妙なトラブルがあったのでその報告を。
このゲームでは荷重や車の揺れを表現するために、2Dも3Dもあわせて viewContainer というスプライトに addChild していて、それを傾けたり揺らしたりしています。もともとは背景画像も直接そこに追加していました。
が、そうすると viewContainer を傾けたときになぜか背景画像のスプライトだけ動きがフィットしない…!(数ピクセル上下にずれて表示されました。)

どうやら原因は、Flash の画質設定が「低」であったことと、スプライトが 3840 × 250 px とかなり変則的なサイズだったこと。(…だと思います。画質「高」にしたらずれなくなりました。)つまり、Flash の画質設定は描画を荒くしているだけでなく、内部処理の有効数字とかもはしょっちゃっているんでしょうね。

しかたがないので BitmapData.draw メソッドを使って、必要な範囲 720 × 250 px だけをキャプチャして addChild する、という回りくどい処理にしています。つまり配置するインスタンスを、あらかじめ切り取ってコンパクトなサイズにしたわけです。これで viewContainer が傾いても問題なく描画されるようになりました。細長インスタンスをX移動させるだけの方がはるかに高速なのにッ。

コース全体モデルの作成

最後にコースの3Dモデルを充実させておきます。
欠けたり歪みすぎたりしないギリギリのローポリゴンを目指してひたすらモデリング~。だけど壁衝突判定をどうしようか悩み中でして、壁のモデリングは見送ってます。モデリングが完了したら、以前紹介したシェーディングテクスチャ作成方法で、一気に陰影をつけました。

今回のデモ

いろいろ処理を追加したのと、遠方クリッピングしているとはいえ3Dモデル自体が増えてきたせいで、動作負荷が高くなっちゃってきていますね。Celeron D クラスだと処理落ちするかも。しかも壁ポリゴンは結構細かい分割になるから、壁追加後が少し心配です。

レースゲーム・デモ画面

デモをプレイする (要:Flash Player 9.0.115.0以降)

*ソースファイル Main.as の全文はこちらから参照できます。
(試行錯誤中のソースなんで怪しい行がいっぱいです。)

Leave a Reply