キャラクターを移動する

地表を移動するキャラクター  地面とキャラクターとカメラが使えるようになったので、今回は地面の上をキャラクターが移動するものを作ります。
地面との当たり判定を行って、常にキャラクターが地面の上にいるように移動します。
これはhgimgなどでやろうとすると地面座標の取得など非常に面倒で難しいのですが、 Easy3Dは地面との当たり判定用の命令が用意されており、簡単に地表を移動させることが出来るようになります。


地面はE3DLoadGroundBMPE3DLoadMQOFileAsGroundで作成したものを使用します。

当たり判定と地面の座標取得にはE3DChkConfGround命令を使用します。


  E3DChkConfGround charahsid, groundhsid, mode, diffmaxy, mapminy, result, adjustx, adjusty, adjustz, nx10000, ny10000, nz10000


パラメータはこんな感じになっています。

パラメータ 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 地面の座標
nx10000
ny10000
nz10000
OUT 法線ベクトル×10000

E3DChkConfGround命令は、使用前にE3DSetBeforePos命令を実行しておく必要があるようです。
ためしにE3DSetBeforePos命令なしにしてみましたが、問題なく動作しました…なくてもいいのかな?
まあ、とりあえずE3DSetBeforePosを、一番最初のE3DSetPos直後と、メインループの最後で呼んでおいてください。


使い方

流れはこんな感じです。
  1. キャラクターを移動。
  2. 地面との当たり判定をとる。
  3. キャラクターを地表の座標に移動する。
当たり判定と書きましたが、地面走行モードの時はキャラクターが地面の上または下にいるかで 判断しているようです。このへんの条件ははっきりとは分かりません。(^_^;
ともかく、判定結果(result)が有効(0意外)のときは、キャラクターを地表の座標に移動します。
これにより、地面にめり込むことも地面がから離れて空を飛ぶこともなくなります。


サンプル

タコが地表を移動して山を登ったり出来るサンプルです。
操作はキーボードの矢印キー(左右)で向き変更、矢印キー(上下)で前進と後退。
タコモデルのファイルtako.sigとタコ用テクスチャファイルtako01.bmpを用意しておいてください。
実行に必要なファイル:e3d006.zip

大きな更新個所のみ赤色で表示しています。細かい変更点は自分で見つけてください。


;
;	キャラクターを移動する
;

#include "e3dhsp.as"

	;/////////////////
	;
	;	初期化
	;
	E3DInit
	dim keybuf, 256		;キー入力

	;/////////////////	
	;
	;	カメラの初期化
	;
	E3DSetProjection 100, 50000


	;/////////////////	
	;
	;	ライトの設定
	;
	E3DCreateLight lid1		;光源を作成
	lightdirx1 = 1		;平行光の向き
	lightdiry1 = -1
	lightdirz1 = 0
	lightr1 = 255	;平行光の色
	lightg1 = 255
	lightb1 = 255
	E3DSetDirectionalLight lid1, lightdirx1, lightdiry1, lightdirz1, lightr1, lightg1, lightb1	;光源を平行光源に設定


	;/////////////////	
	;
	;	形状データのロード
	;
	sdim mediadir, 2048
	mediadir = curdir + "\\tako.sig"
	E3DSigLoad mediadir, hsid1
	E3DSetPos hsid1, 5000, 0, 5000
	frameno1 = 0	;モーションは使用しない。
	E3DSetBeforePos hsid1


	;/////////////////	
	;
	;	地面の作成
	;
	sdim pathbuf, 2048, 4
	pathbuf.0 = curdir + "\\yama.bmp"	;地面の座標情報
	pathbuf.1 = curdir + "\\michi.bmp"	;地面の道の情報
	pathbuf.2 = curdir + "\\kawa.bmp"	;地面の川の情報
	pathbuf.3 = curdir + "\\bazou.bmp"	;地面、道、川の模様を決める、BMPファイル

	;地面作成用の値
	mapsize = 60000		;X,Z座標の最大値
	mapdiv = 60			;座標の分割数
	mapheight = 3000	;高さの最大値

	E3DLoadGroundBMP pathbuf.0, pathbuf.1, pathbuf.2, pathbuf.3, mapsize, mapsize, mapdiv, mapdiv, mapheight, hsid0
	frameno0 = 0	;モーションは使用しない。


;////////////////////////////////////////////////////////////////

;/////////////////
;
;	メインループ
;
*main

	E3DGetKeyboardState keybuf	;キー状態取得

	;モデルが、視野内にあるか判定
	E3DChkInView hsid1	;キャラクター
	E3DChkInView hsid0	;地面
	gosub *ChkConf	;地面との当たり判定

	E3DBeginScene	;-----シーンスタート
		;バックバッファへの書き込み作業を行う

		if keybuf.VK_ESCAPE = 1 : goto *bye ; [ESC]で終了
		gosub *MoveChara		;キャラクター移動
		gosub *MoveCamera		;カメラ移動

		;バックバッファにレンダリングする。
		E3DRender hsid1, 0, frameno1, 0
		E3DRender hsid0, 0, frameno0, 0

	E3DEndScene		;-----シーン終了
	E3DPresent		;バックバッファの内容を、プライマリバッファに転送。描画する。

	E3DSetBeforePos hsid1

	E3DWaitbyFPS 60 : await 0
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
	if ( result != 0 ) : E3DSetPos hsid1, adjustx, adjusty, adjustz	;地面の上に移動
	return





- HOME -

GHP(仮)