▶ 実 行
▶ 実行
クリア
迷路ゲーム改(ThreeJS版3Dダンジョン) - 迷路自動生成付
by てぃふと@うぇいく
!「https://n3s.nadesi.com/plain/576.js」を取り込む 迷路サイズ=7 # どんどん大きくなる 回転フレーム数は30 移動フレーム数は30 画面縦 = 400 画面横 = 300 BLOCKSIZE=3 BLOCKTALL=3 MW=BLOCKSIZE カメラ高さ=1.8 視野角=60 HELP = 「[←][↑][↓][→]/[h][k][j][l]/マウス可」 移動座標 = { 北: { 前:[ 0,-1], 後:[ 0, 1] }, 東: { 前:[ 1, 0], 後:[-1, 0] }, 南: { 前:[ 0, 1], 後:[ 0,-1] }, 西: { 前:[-1, 0], 後:[ 1, 0] } } 回転 = { 北: { 前:"北", 右:"東", 後:"南", 左:"西" }, 東: { 前:"東", 右:"南", 後:"西", 左:"北" }, 南: { 前:"南", 右:"西", 後:"北", 左:"東" }, 西: { 前:"西", 右:"北", 後:"東", 左:"南" } } 視線 = { 北:0, 東:90, 南:180, 西:270 } 回転角 = { 前: 360, 右: 90, 左: -90, 後: 180 } 迷路サイズ=7 # どんどん大きくなる 情報ラベルは空 迷路は空 ココは空 カメラは空 ヒカリゴケは空 ランタンは空 レンダラは空 # プレイヤーの初期座標と向きを指定 PX = 1 PY = 1 PD = "東" 行動状態は「停止中」 行動オプションは空 継続中はオフ 行動フレームは0 ●入力受付設定とは # キー操作に応じてゲームを進める DOCUMENTをキー押した時には K=押されたキー。 もし、K=「ArrowUp」ならば、前進む。 違えば、もし、K=「ArrowDown」ならば、後ろ向く。 違えば、もし、K=「ArrowLeft」ならば、左向く。 違えば、もし、K=「ArrowRight」ならば、右向く。 違えば、もし、K=「Escape」ならば、継続中はオフ。 違えば、もし、K=「k」ならば、前進む。 違えば、もし、K=「j」ならば、後戻る。 違えば、もし、K=「h」ならば、左向く。 違えば、もし、K=「l」ならば、右向く。 違えば、もし、K=「q」ならば、継続中はオフ。 ここまで。 ('#three_div'のDOM要素取得)をマウス押した時には DIVは('#three_div'のDOM要素取得) もし、マウスX=0ならば戻る。 W=DIVの「width」をDOM属性取得。 H=DIVの「height」をDOM属性取得。 XX=W/2-マウスX YY=H/2-マウスY もし、ABS(XX) > ABS(YY)ならば もしXX<0ならば 右向く。 違えば 左向く。 ここまで 違えば もしYY<0ならば 後戻る。 違えば 前進む。 ここまで。 ここまで。 ここまで。 ここまで ●入力受付解除とは DOCUMENTをキー押した時には ここまで ('#three_div'のDOM要素取得)をマウス押した時には ここまで ここまで # 移動先の座標に移動できるか確認する ●右向くとは 「右」に方向転換。 ここまで ●左向くとは 「左」に方向転換。 ここまで ●前進むとは 「前」に移動開始。 ここまで ●後ろ向くとは 「後」に方向転換。 ここまで ●後戻るとは 「後」に移動開始。 ここまで ●(Dに)方向転換とは もし、行動状態が「停止中」ならば、 情報ラベルに「{HELP} = ({PX},{PY},{PD}):回転中」をテキスト設定。 行動状態は「回転中」 行動オプションはD 行動フレームは0 ここまで ここまで ●(Dに)移動開始とは もし、行動状態が「停止中」ならば、 情報ラベルに「{HELP} = ({PX},{PY},{PD}):移動中」をテキスト設定。 行動状態は「移動中」 行動オプションはD 行動フレームは0 ここまで ここまで ●アニメーションとは メイン もし、継続中ならば、 画面更新時実行には アニメーション ここまで 違えば、 入力受付解除 ここまで ここまで ●メインとは もし、行動状態が「移動中」ならば、 CXはPX*MW+MW/2+移動座標[PD][行動オプション][0]*MW*(行動フレーム/移動フレーム数) CYはPY*MW+MW/2+移動座標[PD][行動オプション][1]*MW*(行動フレーム/移動フレーム数) 行動フレームは行動フレーム+1 もし、行動フレーム=10ならば、 NXはPX+移動座標[PD][行動オプション][0] NYはPY+移動座標[PD][行動オプション][1] もし、NX<0または、NY<0ならば 情報ラベルに「不正な座標」をテキスト設定。 行動状態は「停止中」 違えば NO=INT(迷路[NY][NX]) もし、NO=1ならば 情報ラベルに「{HELP} = そこは壁!{NO}」をテキスト設定。 行動状態は「停止中」 ここまで ここまで 違えばもし、行動フレーム≧移動フレーム数ならば PXはPX+移動座標[PD][行動オプション][0] PYはPY+移動座標[PD][行動オプション][1] 情報ラベルに「{HELP} = ({PX},{PY},{PD})」をテキスト設定。 行動状態は「停止中」 NO=INT(迷路[PY][PX]) もし、NO=2ならば 迷路サイズ=迷路サイズ×2+1 「ゲームクリア!{改行}そして新しい迷路{迷路サイズ}へようこそ!」と言う。 迷路 = 迷路サイズの迷路準備。 迷路[迷路サイズ-2][迷路サイズ-2]=2 # ゴール生成 PX=1。PY=1。 ここまで。 ここまで 違えば、 CXはPX*MW+MW/2 CYはPY*MW+MW/2 ここまで もし、行動状態が「回転中」ならば、 angleは視線[PD]+回転角[行動オプション]*(行動フレーム/回転フレーム数) 行動フレームは行動フレーム+1 もし、行動フレーム≧回転フレーム数ならば PDは回転[PD][行動オプション] 情報ラベルに「{HELP} = ({PX},{PY},{PD})」をテキスト設定。 行動状態は「停止中」 ここまで 違えば、 angleは視線[PD] ここまで カメラを[CX, カメラ高さ, CY]にTJS位置設定 Qは『(function (angle) { const quaternion = new THREE.Quaternion(); quaternion.setFromAxisAngle( new THREE.Vector3( 0, -1, 0 ), angle / 180 * Math.PI ); return quaternion; })』を[angle]でJS関数実行 カメラの"setRotationFromQuaternion"を[Q]でJSメソッド実行 カメラを"+Y"にTJSカメラ上方設定 カメラのTJS投影マトリクス更新 ランタンをカメラ["position"]にTJS位置設定 ココをカメラでレンダラにTJS描画 ここまで ●描画環境準備とは # シーン作成 ココは、TJSシーン作成 ココに0x004400をTJS背景設定 # カメラ作成 カメラは、[視野角,画面横/画面縦,0.001,200]のTJS透視投影カメラ作成 カメラを[MW/2, カメラ高さ, MW/2]にTJS位置設定 カメラを[MW/2, カメラ高さ, MW]にTJS視点設定 カメラを"+Y"にTJSカメラ上方設定 ココにカメラをTJS登場 カメラのTJS投影マトリクス更新 # 光源作成 ヒカリゴケは0xffffffのTJS環境光源作成 ココにヒカリゴケをTJS登場 ランタンは[0x000000, 1, 10, 0.1]のTJS点光源作成 ランタンをカメラ["position"]にTJS位置設定 ココにランタンをTJS登場 レンダラは'three_div'にTJS描画準備 レンダラに[画面横,画面縦]をTJSサイズ設定 レンダラに0x000000をTJSクリア色設定 ここまで ●(ココに迷路を)迷路構造構築とは #マップ全体の3Dデータを構築 壁構造は{W:BLOCKSIZE,H:BLOCKTALL,D:BLOCKSIZE,buffer:1}のTJS箱作成 壁材質は{color:0xa52a2a}のTJS拡散反射材質作成 ゴール床構造は{W:BLOCKSIZE*0.9,H:0.02,D:BLOCKSIZE*0.9,buffer:1}のTJS箱作成 ゴール床材質は{color:0xfff100}のTJS拡散反射材質作成 (迷路の配列要素数)回 OYは回数-1 (迷路[OY]の配列要素数)回 OXは回数-1 NO = INT(迷路[OY][OX]) X = OX * BLOCKSIZE Y = OY * BLOCKSIZE もし、NOが1ならば、 物体は壁構造と壁材質のTJSメッシュ作成 物体を[X+BLOCKSIZE/2,BLOCKTALL/2,Y+BLOCKSIZE/2]にTJS位置設定 物体をココにTJS登場 違えばもし、NOが2ならば、 物体はゴール床構造とゴール床材質のTJSメッシュ作成 物体を[X+BLOCKSIZE/2,0.01,Y+BLOCKSIZE/2]にTJS位置設定 物体をココにTJS登場 ここまで ここまで ここまで。 ここまで # 迷路作成機能 ●(列数の)迷路準備とは 迷路=列数の迷路作成。 迷路を1と1から2で到達チェック 迷路に2で穴開け 迷路から2のマーククリア 迷路で戻る ここまで ●(列数の)迷路作成とは 方位は[ [-1, 0], [ 1, 0], [ 0,-1], [ 0, 1] ] # 迷路データを全部0で初期化 --- (*1) 迷路は[] Yを0から(列数-1)まで繰り返す 迷路[Y] = [] Xを0から(列数-1)まで繰り返す 迷路[Y][X] = 0 ここまで ここまで。 # 外周を壁にする --- (*2) Nを0から(列数-1)まで繰り返す 迷路[N][0] = 1 迷路[N][列数-1] = 1 迷路[0][N] = 1 迷路[列数-1][N] = 1 ここまで。 # 外周からの壁を配置する Nを2から(列数-3)まで繰り返す もし(N%2=1)または(N%2=1)ならば続ける。 もし、(4の乱数)が0ならば、迷路[1][N] = 1。 もし、(4の乱数)が0ならば、迷路[列数-2][N] = 1。 もし、(4の乱数)が0ならば、迷路[N][1] = 1。 もし、(4の乱数)が0ならば、迷路[列数-2][N] = 1。 ここまで。 # 2マスに1つ壁を配置する --- (*3) Yを2から(列数-3)まで繰り返す Xを2から(列数-3)まで繰り返す もし(X%2=1)または(Y%2=1)ならば続ける。 迷路[Y][X] = 1 # 上下左右のいずれかの空いてる方向を壁にする --- (*4) 方位を配列シャッフルする。 Dを0から3まで繰り返す もし、迷路[Y+方位[D][1]][X+方位[D][0]]=0ならば、 迷路[Y+方位[D][1]][X+方位[D][0]] = 1 抜ける ここまで ここまで。 ここまで ここまで。 それは迷路 ここまで。 ●(迷路からマークの)マーククリアとは Yを1から((迷路の配列要素数)-2)まで繰り返す Xを1から((迷路[0]の配列要素数)-2)まで繰り返す もし、迷路[Y][X]=マークならば迷路[Y][X]=0 ここまで ここまで。 ここまで ●(迷路をXとYからマークで)到達チェックとは 方位は[ [-1, 0], [ 1, 0], [ 0,-1], [ 0, 1] ] 分岐は空配列 分岐に[X,Y]を配列追加 ((分岐の配列要素数)>0)の間、 XYは分岐から配列ポップ XはXY[0] YはXY[1] もし、迷路[Y][X]=0でなければ、 続ける ここまで 迷路[Y][X] = マーク Dを0から3まで繰り返す もし、迷路[Y+方位[D][1]][X+方位[D][0]]=0ならば、 迷路[Y+方位[D][1]][X+方位[D][0]] = マーク 分岐に[X+方位[D][0]*2, Y+方位[D][1]*2]を配列追加 ここまで ここまで ここまで ここまで ●(迷路にマークで)穴開けとは 方位は[ [-1, 0], [ 1, 0], [ 0,-1], [ 0, 1] ] Yを1から((迷路の配列要素数)-2)まで繰り返す Xを1から((迷路[0]の配列要素数)-2)まで繰り返す もし(X%2=0)または(Y%2=0)ならば続ける。 もし、迷路[Y][X]=マークならば続ける。 Dを0から3まで繰り返す もし、迷路[Y+方位[D][1]][X+方位[D][0]]=1&&迷路[Y+方位[D][1]*2][X+方位[D][0]*2]=2ならば、 迷路[Y+方位[D][1]][X+方位[D][0]] = 0 迷路をXとYからマークで到達チェック 抜ける ここまで ここまで。 ここまで ここまで。 ここまで ●(迷路を)迷路表示とは # --- (*5) 壁幅=8 列数=迷路の要素数。 Yを0から(列数-1)まで繰り返す Xを0から(列数-1)まで繰り返す V = 迷路[Y][X] 灰色に線色設定。 もしV=0ならば、白色に塗り色設定。 違えばもしV=2ならば、水色に塗り色設定。 違えば、茶色に塗り色設定。 [X*壁幅, Y*壁幅, 壁幅, 壁幅]に四角描画。 ここまで。 ここまで。 ここまで。 ●DIV要素準備とは DIVは"#three_div"のDOM要素取得 もし、DIVでなければ、 Pは"#runbox"のDOM要素取得 DIVは"DIV"のDOM要素作成 DIV["id"]は"three_div" DIV["width"]は画面横 DIV["height"]は画面縦 PにDIVをDOM子要素追加 ここまで DIV["innerHTML"]は空 ここまで TJSライブラリ読込後には DIV要素準備する 描画環境準備する 迷路 = 迷路サイズの迷路準備。 迷路[迷路サイズ-2][迷路サイズ-2]=2 # ゴール生成 ココに迷路を迷路構造構築 継続中はオン ('#runbox'のDOM要素取得)にDOM親要素設定 HELPのラベル作成して、情報ラベルに代入。 入力受付設定 情報ラベルに「{HELP} = ({PX},{PY},{PD})」をテキスト設定。 アニメーション ここまで