はじめての3Dプログラミング・ジャンプ(色んな意味で)編

download report

Transcript はじめての3Dプログラミング・ジャンプ(色んな意味で)編

プロジェクト演習Ⅱ インタラクティブゲーム制作 イントロダクション2 第6回 はじめての3Dプログラミング ジャンプ(色んな意味で)編

今日の内容

• 跳びたい! – 状態による条件分岐 – 速度と加速度 – 衝突判定の効率化 • そろそろmain()が膨らむのがつらい… – クラスと関数を導入したプログラム • こちらも結構な「ジャンプ」かも……

今週のプロジェクト

• 授業資料ページからダウンロードします – 落としたZipファイルを解凍して、出てきたフォルダ を好きなところに配置

ちょびっとProcessingチックに書いてみようか プログラムの構造を整理しよう

そろそろ行数辛くないですか?

• main()がどんどん 伸びるよ! – やったね!…ではない • 100行超えた関数を うじうじいじるのは ちょっとイケてない – と言いつつ私も顔を 背ける…… { int main(int argc, char *argv[]) // 準備処理がごちゃー! … } // ここからループ! while(update() ==true) { // 条件分岐がごちゃー! … } return 0;

なので、関数化したい

• • 準備でやることは setup() 毎フレーム処理するこ とはdraw() • あれあれ、これって Processingチック? { void setup() // ここで準備 }; { void draw() // ここでループ while(update() == true) { // 処理本体 } };

• • • setup()やdraw()の中身も 用途に応じて関数に分ける やることが増えると 結局setup()やdraw()が爆 発する 処理のカタマリごとで 関数に分けると見通しが 良くなる { void draw() } while(update() == true) { are(); sore(); }; { void are() // 超複雑なアレに関する処理 }; 関数の基本 – 名前を呼ばれたらそこへ ジャンプ – 終わったらもどの場所へ ジャンプ { void sore() // 超難解なソレに関する処理 };

• そんなプログラミングを 実現するために 「クラス」を導入 – privateのところに プログラムで使いたい オブジェクトや変数を 用意する • 関数内で使い捨てるもの は関数内でもいい – publicのところに関数を書 く • • • 準備はsetup() ループはdraw() それ以外にも関数は 作ってよい • • main()関数から、 きちんとsetup()と draw()を呼んでいる のを確認しておこう – ゲームがオブジェクトに なってる?と思った人はな かなか鋭い 今のやり方だと結局 1ファイルは長くなるが、 これを分割する方法はい ずれまた

前回の課題でやりたかった人もいるでしょう キーを押したら勝手に動く、は どーやるの?

以前に教えた条件分岐で できたこと • • キーを「押してる間」こうしろ キーを「押した瞬間」こうしてね だけど • キーを押したら「こう動き始めてね」 – で、一定時間過ぎたら動作終了するような

フラグ、立ってますか?

1. キーが押された!フラグが立った! if(キー押された) { フラグON } 2. フラグ立ってる間はこうしなさい! アクションが終了したら、 フラグをベキッ!と折りなさい } if(フラグON) { アクション1コマ分の処理 if(アクション終わり?) { フラグOFF }

飛べないアクションはただのアクションだ お前ちょっと跳んでみろよ

ジャンプはアクションの命

• ジャンプもフラグによっ て管理できる アクションのひとつ – 右図は驚異的な 跳躍力でお馴染みの 配管工Mさん

フラグ(モード)管理の流れ

• • • • 普通の状態を0とする キーを押されたら上昇モード(1)とする 頂点に達したら下降モード(2)とする 着地したら0に戻す

上昇と下降ってどういう処理?

• 単純に一定距離ぶん上下移動させる – – glTranslate()で動かせばいいのだが… ずっと一定値だと単調で気持ち悪い • 速度と加速度の関係を思いだそう – – 速度をいじってやることで動きに緩急が付く 重力加速度とかに則ってもいいけど、 そのままだとあんまり面白くない – 気持ちいい動きを探してみよう

モードの境目

• • • 通常→上昇 – キーが押された瞬間 上昇→下降 – y方向の速度がマイナスになった時 下降→着地 – 地面とぶつかった時 • 先週覚えた「衝突判定」が使えそう! • 通常→下降 – 足元に地面が無くなったとき!

今回の当たり判定

• • 障害物はfkut_BlockModel プレイヤーはfkut_SphereModel • 当たり判定には、fkut_BlockModelの変数に対して checkToMovingSphere()を使う – block.checkToMovingSphere(other, spd, back); • otherの部分に操作しているSphereModelを、 spdに動かす予定の速度を、backには空のfk_Vectorを渡す – if(命令 == true)でYesなら衝突している • backの部分に渡したfk_Vectorには、spdをどれだけ 減算すれば衝突寸前まで戻せるかを表すベクトルが入る

真の衝突判定とは

• • ある瞬間にぶつかってるかどうか、を 調べるだけでは「干渉判定」でしかない 「これくらい動く予定なんだけど、 どこかでぶつかっちゃう?」を調べる !!!!

!

!

?

spdが非常に重要な変数になる

• • まずは次のフレームでどれだけ動かしたいか をspdに蓄積し、当たり判定で修正 修正が済んだspdをモデルにglTranslate()で 適用する • Block対BlockならcheckToMovingBlock()で同 じように 判定できる

用途に応じて使い分け

• • キャラクターは球 – 見た目はゴージャスに 作った形状でもいい – それらを覆うような球を 当たり判定用に用意し て、親子関係を結べば いい • entry()しなければ表示さ れない マップはブロック – 球だとつるつるすべって 操作性に難がある

その他もろもろ

カメラを一緒に動かす

• 自分で用意したfk_Modelの変数をカメラとして セットすると、物体同様に動きをコントロール することが可能 • キャラクターの動きと同期すれば、 FPS的な画面も作れる

Modelシリーズの回転制御命令

• • 今のところ「方向」を指定するやり方しか教え ていないが、他にも色々あります – XYZ軸それぞれについてこのくらいの角度で!な どといった姿勢の指定が可能 • glAngle() – 現在位置からここを中心に回転しろ、なんて命令 も • glRotateWithVec() リファレンスを見て実験して確かめよう

ぶつかるためじゃない当たり判定 • ゲームでは「ある地点に到達したら何かがお きる」という処理も必要 • fkut_BlockModelを配置して、そこに接触した らイベント発生、という使い方もできる – entryしなければ表示はされない

今日の課題

• • • BASIC – Xキーを押すと、5秒間(300フレーム)球が赤くなり、 3倍の速さで走るようにしてみよう • フラグとして秒数をカウントする変数を用意 • • フラグが立っているかいないかで処理を分岐 フラグが立っている場合の処理で、残り時間を減算していく ADVANCED – 2段ジャンプをできるようにしてみよう EXTREME – ジャンプで上っていけるフィールドを作り、 ゴールに到達したらクリアを褒めるメッセージを 出して終了するゲームを作ってみよう

複雑なフィールドを作ってしまった人へ 当たった場合の戻し方

戻し方の罠

• • • • 動物体の次フレームでの位置を仮定する その動きを阻害する可能性のある物体全てと 衝突判定を行う 戻しベクトルが発生したら動物体に適用する 全物体と判定を終えたら終了… ではない

以下のようなシチュを考える

• • 右図のような状況の場 合、Aに衝突して発生し た戻しベクトルによって、 Bに衝突する危険性が ある A→Bの順に判定でき ればいいが、そうならな かったらどうする? 真上から見た図

解決案

• • 全部の物体と判定して、 「戻しベクトルが発生しな かったら」判定終了とする 色々効率化の余地はあ るだろうが、とりあえずは こうしておこう do { 戻しベクトル初期化 for(障害物全部) { 当たり判定する 戻しベクトル加算 } 動物体に適用 } while(適用したベクトルが ゼロじゃなかったらもう1 回ループ);

重力の扱い

• • • 基本的には常時下向き の力を働かせる そうすると、同じ高さで 並べたブロックでつっか かる – 足下のブロックから先に 判定できればいいが、 そうもいかない 速度をXZ方向とY方向 に分解して2回判定 真横から見た図 A B

物体を押せるようにした場合

• 押されて動いた物体vs全物体での 判定も必要 – 判定回数が爆発的に増加する • 押して動かせるのは限定的にするべき – でも関数を上手く作れば処理はコンパクトに書け るはず