キャラクターを移動する
キャラクターを移動する
地面とキャラクターとカメラが使えるようになったので、今回は地面の上をキャラクターが移動するものを作ります。
地面との当たり判定を行って、常にキャラクターが地面の上にいるように移動します。
Easy3Dは地面との当たり判定用の命令が用意されており、簡単に地表を移動させることが出来るようになります。
いきなりですが…省略します
いきなりですが、一部の命令の解説を省略します。
移動で言えばE3DPosForwardやE3DRotateYとかです。
それと、追跡カメラも今回は説明を省略。
単にめんどくさがってるだけなのですが…、とにかく、詳細はマニュアル参照してください…。m(_ _)m
今回は地面をどうやって派って移動するかに焦点を絞って説明します。
地面とのあたり判定
地面の上をはうように移動させるだけならE3DSetPosOnGroundPartでいいのかもしれませんが、ちょっと不便なので違う方法をやることにします。
地面はE3DLoadGroundBMPかE3DLoadMQOFileAsGroundで作成したものを使用します。
E3DLoadGroundBMPはBMP画像から、E3DLoadMQOFileAsGroundはメタセコで地面モデルを作成します。
メタセコで地面を作成するときは地面に隙間が出来ないよう注意して作りましょう。
当たり判定と地面の座標取得にはE3DChkConfGround命令を使用します。
E3DChkConfGround charahsid, groundhsid, mode, diffmaxy, mapminy, result, adjustx, adjustx, adjustx, nx, ny, nz |
パラメータはこんな感じになっています。
パラメータ | IN/OUT | 内容 |
---|---|---|
charahsid | IN | キャラクターモデルID |
groundhsid | IN | 地面モデルID |
mode | IN | 0:フライトモード 1:地面を這うモード |
diffmaxy | IN | 最大高さ E3DLoadGroundBMPで設定した地面の高さの最大値を指定しておけばOKです。 |
mapminy | IN | 高さ0 実際の最小値より、少し小さな値を入れておくようです。 |
result | OUT | 当たり判定の結果 |
adjustx adjusty adjustz | OUT | 地面の座標 |
nx, ny, nz | OUT | 法線ベクトル |
フライトモード?這うモード?
フライトモードは地面モデルを通常のモデルと同様に当たり判定を行うモードのようです。衝突した瞬間だけ検知するのでフライトシミュレーションを作るときに良いかもしれません。
這うモードはそのものズバリ、地面をはって移動する…つまり歩くときのモードです。常に地面座標を返してくれるので地表を移動するのに使うと便利です。
3DCGの世界にはじめから上下の概念があるというのは、物理に慣れ親しんだ方にはちょっと以外かもしれませんが、ゲームを作る上ではある程度環境を限定したほうが
使いやすいものなのです。ちなみに、E3Dでの「上」はY軸の+方向、「下」はY軸の-方向。
高さ
diffmaxyを超える急激な高さの変化があるとresultに1を返します。(例えば階段など)
mapminyより低い地面は高さmapminyとして検出されます。(ためしに1000.0などするとよく分かります。)
法線ベクトル
地面の面に垂直なベクトルのことです。向きは表方向。
マニュアルにあるおとり、跳ね返るようなアクションを作ろうとしない限りは特に気にする必要はありません。
今回は一切気にしない。
さて、E3DChkConfGround命令は、使用前にE3DSetBeforePos命令を実行しておく必要があるようです。
ためしにE3DSetBeforePos命令なしにしてみましたが、問題なく動作しました…なくてもいいのかな?
まあ、とりあえずE3DSetBeforePosを、一番最初のE3DSetPos直後と、メインループの最後で呼んでおいてください。
使い方
流れはこんな感じです。
- キャラクターを移動。
- 地面との当たり判定をとる。(這うモード)
- キャラクターを地表の座標に移動する。
あたり判定と言っても、這うモードなら常に地面座標を返すので、単なる地面座標の取得だと思ってください。
さてこれにより、地面にめり込むことも地面がから離れて空を飛ぶこともなくなります。
サンプル
タコが地表を移動して山を登ったり出来るサンプルです。
操作はキーボードの矢印キー(左右)で向き変更、矢印キー(上下)で前進と後退。
実行に必要なファイル:e3d3004.zip
解凍に成功すると、Mediaフォルダとe3d3004.hspが作成されます。
作成されたMediaフォルダにタコのファイルをコピーするので次の作業を行ってください。
HSP3のインストールフォルダからsample→easy3d→Mediaとフォルダを開いてください。
tako.sigとtako01.PNGをコピーします。
e3d3004.zipを解凍してできたMediaフォルダにコピーしたファイルを貼り付けます。
これで必要なファイルはそろいました。
次に、下のスクリプトをコピーして、HSPのスクリプトファイルを作成してください。
作成したファイルは、e3d3004.hspがある場所と同じ場所におきます。
これでサンプルを実行することが出来ます。
; ; キャラクターを移動する ; #include "e3dhsp3.as" ;///////////////// ; ; 初期化 ; wid = 0 ;ウインドウID objid = -1 ;オブジェクトID fullscreenflag = 0 ;フルスクリーンフラグ bits = 16 ;色数ビット数(fullscreenflag = 1 のときのみ有効) multisamplenum = 0 ;アンチエイリアスのマルチサンプル数(0,2~16) ;scid スワップチェインID E3DInit wid, objid, fullscreenflag, bits, multisamplenum, scid dim keybuf, 256 ;キー入力 ;///////////////// ; ; ライトの設定 ; E3DCreateLight lid1 ;光源を作成 lightdirx1 = 1 ;平行光の向き lightdiry1 = -1 lightdirz1 = 0 lightr1 = 255 ;平行光の色 lightg1 = 255 lightb1 = 255 E3DSetDirectionalLight lid1, lightdirx1, lightdiry1, lightdirz1, lightr1, lightg1, lightb1 ;光源を平行光源に設定 ;///////////////// ; ; カメラの初期化 ; camposx = 0 : camposy = 1000 : camposz = -4200 ; camposx = 0 : camposy = 0 : camposz = 4200 ;デフォルト値 E3DSetCameraPos camposx, camposy, camposz ;カメラ座標を設定 targetx = 0 ;注視点座標 targety = 0 targetz = 0 upvecx = 0 ;カメラの上方向のベクトル upvecy = 1 upvecz = 0 E3DSetCameraTarget targetx, targety, targetz, upvecx, upvecy, upvecz ;カメラの注視点を設定 ;プロジェクションの設定 proj_near = 100.0 : proj_far = 50000.0 : proj_fov = 45.0 E3DSetProjection proj_near, proj_far, proj_fov ;///////////////// ; ; 地面の作成 ; sdim pathbuf, 2048, 4 pathbuf.0 = dir_cur + "\\Media\\yama.bmp" ;地面の座標情報 pathbuf.1 = dir_cur + "\\Media\\michi.bmp" ;地面の道の情報 pathbuf.2 = dir_cur + "\\Media\\kawa.bmp" ;地面の川の情報 pathbuf.3 = dir_cur + "\\Media\\bazou.bmp" ;地面、道、川の模様を決める、BMPファイル ;地面作成用の値 mapsize = 60000.0 ;X,Z座標の最大値 mapdiv = 60 ;座標の分割数 mapheight = 3000.0 ;高さの最大値 E3DLoadGroundBMP pathbuf.0, pathbuf.1, pathbuf.2, pathbuf.3, mapsize, mapsize, mapdiv, mapdiv, mapheight, hsid0 posx0 = 0.0 : posy0 = 0.0 : posz0 = 0.0 degx0 = 0.0 : degy0 = 0.0 : degz0 = 0.0 E3DSetPos hsid0, posx0, posy0, posz0 ;地面表示位置を設定 E3DSetDir hsid0, degx0, degy0, degz0 ;地面の向きを設定 frameno0 = 0 ;モーションは使用しない。 ;///////////////// ; ; 形状データのロード ; sdim mediadir, 2048 mediadir = dir_cur + "\\Media\\tako.sig" E3DSigLoad mediadir, hsid1 ; E3DSetPos hsid1, 13000, -1000, 16000 E3DSetPosOnGroundPart hsid1, hsid0,, mapheight,, 13000, 16000 E3DRotateY hsid1, 180 frameno1 = 0 ;モーションは使用しない。 E3DSetBeforePos hsid1 ;///////////////// ; ; メインループ ; *main E3DGetKeyboardState keybuf ;キー状態取得 E3DBeginScene ;-----シーンスタート E3DChkInView scid, hsid0 ;モデルが、視野内にあるか判定 E3DChkInView scid, hsid1 if keybuf.VK_ESCAPE = 1 : goto *bye ; [ESC]で終了 gosub *MoveChara ;キャラクター移動 gosub *ChkConf ;地面との当たり判定 gosub *MoveCamera ;カメラ移動 ;不透明部分の描画をする E3DRender scid1, hsid0, 0, frameno0, 0 ;バックバッファにレンダリングする。(地面描画) E3DRender scid1, hsid1, 0, frameno1, 0 ;バックバッファにレンダリングする。(タコ描画) ;半透明部分の描画をする E3DRender scid1, hsid1, 1, frameno1, 0, 0, 0, 1 E3DEndScene ;-----シーン終了 E3DPresent scid1 ;バックバッファの内容を、プライマリバッファに転送。描画する。 E3DSetBeforePos hsid1 E3DWaitByFPS 60, chkfps1 : await 0 title ""+chkfps1 + " FPS" goto *main ; ; 終了処理 ; *bye E3DDestroyLight lid1 ;ライトを破棄 E3DBye end ;///////////////// ; ; キャラクター移動 ; *MoveChara forwardstep = 100 ;移動速度(前進) backstep = -forwardstep ;移動速度(後退) degstep = 5 mdegstep = -degstep if keybuf.VK_UP = 1 : E3DPosForward hsid1, forwardstep ;矢印上 if keybuf.VK_DOWN = 1 : E3DPosForward hsid1, backstep ;矢印下 if keybuf.VK_LEFT = 1 : E3DRotateY hsid1, mdegstep ;矢印左 if keybuf.VK_RIGHT = 1 : E3DRotateY hsid1, degstep ;矢印右 return ;///////////////// ; ; カメラ移動(キャラクター追跡型) ; *MoveCamera ;キャラクターを後ろに2500移動して座標を取得。backpos E3DGetPos hsid1, saveposx1, saveposy1, saveposz1 E3DPosForward hsid1, -2500 E3DGetPos hsid1, backposx, backposy, backposz E3DSetPos hsid1, saveposx1, saveposy1, saveposz1 ;カメラをキャラクタ後方に設置 E3DSetCameraPos backposx, backposy + 1500, backposz E3DSetCameraTarget saveposx1, saveposy1 + 800, saveposz1, 0, 1, 0 return ;///////////////// ; ; キャラクタの地面との当たり判定 ; *ChkConf mapminy = -100 ;地面データのY座標の最小値。実際の最小値より、少し小さな値を入れる。 E3DChkConfGround hsid1, hsid0, 1, mapheight, mapminy, result, adjustx, adjusty, adjustz, nx, ny, nz E3DSetPos hsid1, adjustx, adjusty, adjustz ;地面の上に移動 return