▶ 実 行
▶ 実行
クリア
迷路ゲーム改(3Dダンジョン風) - 迷路自動生成付
by てぃふと@うぇいく
## 迷路ゲーム改(クジラ飛行机 作)の3D表示版 # マップ表示がトップビューから3Dダンジョン風に変更 # 視点の変更に伴い移動が方向転換または移動に変更 # マップ生成を壁倒法の改良版に変更 # プレイヤーの初期座標と向きを指定 PX = 1 PY = 1 PD = 1 # その他の定数 W=200 H=300 表示領域は[0,0,W,H] # 一点透視法で3Dもどきの壁・床を表示する。 # このとき、消失点とDと[示唆点,0]からなる3角形を用いる 消失点は[W/2,H/2] D=[-20,消失点[1]] 示唆点=W*10 # 視界、比率、歩幅は、以下の2種類の組み合わせで # 歩く感じが変わります。 # 5,1,1,6,1 # 14,10,1,60,2 # 何升先まで描画するか 視界距離=14 # 壁の長さの比率。奇数・偶数は視点からの距離数。 真横壁比率=10 奇数升比率=1 偶数升比率=60 # 1回の移動で進む升数 歩幅=2 # 向きの値に対する座標の変化 DIR = [ [ 0, -1], [ 1, 0], [ 0, 1], [ -1, 0] ] 方向 = ["北","東","南","西"] COLORS = ["white", "brown", "blue"] HELP = 「[←][↑][↓][→]/[h][k][j][l]/マウス可」 交点マトリクスは{ 消失点:消失点, 視界距離:視界距離, 真横壁比率:真横壁比率, 奇数升比率:奇数升比率, 偶数升比率:偶数升比率 }で交点マトリクス作成 壁描画情報は交点マトリクスから{ 消失点:消失点, 表示幅:W, 表示高: H }で壁描画情報準備 迷路サイズ=7 # どんどん大きくなる 迷路 = 迷路サイズの迷路作成。 迷路[迷路サイズ-2][迷路サイズ-2]=2 # ゴール生成 HELPのラベル作成して、情報ラベルに代入。 マップ表示。 # キー操作に応じてゲームを進める DOCUMENTをキー押した時には K=押されたキー。 もし、K=「ArrowUp」ならば、前進む。 違えば、もし、K=「ArrowDown」ならば、後ろ向く。 違えば、もし、K=「ArrowLeft」ならば、左向く。 違えば、もし、K=「ArrowRight」ならば、右向く。 違えば、もし、K=「k」ならば、前進む。 違えば、もし、K=「j」ならば、後ろ向く。 違えば、もし、K=「h」ならば、左向く。 違えば、もし、K=「l」ならば、右向く。 ここまで。 描画中キャンバスをマウス押した時には もし、マウスX=0ならば戻る。 W=描画中キャンバスの「width」をDOM属性取得。 H=描画中キャンバスの「height」をDOM属性取得。 XX=W/2-マウスX YY=H/2-マウスY もし、ABS(XX) > ABS(YY)ならば もしXX<0ならば 右向く。 違えば 左向く。 ここまで 違えば もしYY<0ならば 後ろ向く。 違えば 前進む。 ここまで。 ここまで。 ここまで。 # 方向転換もしくは確認付き移動 ●右向くとは 1で方向転換。 ここまで ●左向くとは (-1)で方向転換。 ここまで ●前進むとは PDで移動確認。 ここまで ●後ろ向くとは 2で方向転換。 ここまで ●後戻るとは ((PD+2)%4)で移動確認。 ここまで ●(Dで)方向転換とは PD=(PD+D+4)%4 情報ラベルに「{HELP} = ({PX},{PY},{方向[PD]})」をテキスト設定。 マップ表示。 ここまで ●(Dで)移動確認とは NX=DIR[D][0]+PX NY=DIR[D][1]+PY もし、NX<0または、NY<0ならば 情報ラベルに「不正な座標」をテキスト設定。 戻る。 ここまで NO=INT(迷路[NY][NX]) もし、NO=1ならば、 情報ラベルに「{HELP} = そこは壁!{NO}」をテキスト設定。 違えば PX=DIR[D][0]×歩幅+PX PY=DIR[D][1]×歩幅+PY 情報ラベルに「{HELP} = ({PX},{PY},{方向[PD]})」をテキスト設定。 マップ表示。 NO=INT(迷路[PY][PX]) もし、NO=2ならば 迷路サイズ=迷路サイズ×2+1 「ゲームクリア!{改行}そして新しい迷路{迷路サイズ}へようこそ!」と言う。 迷路 = 迷路サイズの迷路作成。 迷路[迷路サイズ-2][迷路サイズ-2]=2 # ゴール生成 PX=1。PY=1。PD=1。マップ表示。 ここまで。 ここまで。 ここまで # 画面にマップを表示する処理 ●(壁を)壁描画とは CTXは描画中コンテキスト CTXの"beginPath"を[]でJSメソッド実行 CTXの"moveTo"を壁[0]でJSメソッド実行 CTXの"lineTo"を壁[1]でJSメソッド実行 CTXの"lineTo"を壁[2]でJSメソッド実行 CTXの"lineTo"を壁[3]でJSメソッド実行 CTXの"closePath"を[]でJSメソッド実行 CTXの"fill"を[]でJSメソッド実行 CTXの"stroke"を[]でJSメソッド実行 ここまで ●(XYDの)前とは [XYD[0]+DIR[XYD[2]][0], XYD[1]+DIR[XYD[2]][1], XYD[2]]で戻る ここまで ●(XYDの)左とは [XYD[0]+DIR[(XYD[2]+3)%4][0], XYD[1]+DIR[(XYD[2]+3)%4][1], XYD[2]]で戻る ここまで ●(XYDの)右とは [XYD[0]+DIR[(XYD[2]+1)%4][0], XYD[1]+DIR[(XYD[2]+1)%4][1], XYD[2]]で戻る ここまで ●マップ表示 表示領域に描画クリア CTXは描画中コンテキスト キャンバス状態保存 # 表示領域を制限 CTXの"beginPath"を[]でJSメソッド実行 CTXの"rect"を表示領域でJSメソッド実行 CTXの"clip"を[]でJSメソッド実行 列数=迷路の要素数。 # 視界の1番遠い正面の位置に初期化する (視界距離)回、 奥行は視界距離-回数 茶色に塗り色設定 黒色に線色設定 XYD0は[PX+DIR[PD][0]*奥行, PY+DIR[PD][1]*奥行, PD] XYD=XYD0の左の左の前 5回、 列は回数-3 XはXYD[0] YはXYD[1] もし、X≧0&&X<列数&&Y≧0&&Y<列数ならば、 もし、迷路[Y][X]=1ならば、 壁描画情報["正面"][列][奥行]を壁描画 ここまで ここまで XYD=XYDの右 ここまで XYD=XYD0の左の左の左 3回、 列は回数-3 XはXYD[0] YはXYD[1] もし、X≧0&&X<列数&&Y≧0&&Y<列数ならば、 もし、迷路[Y][X]=1ならば、 壁描画情報["左側"][列][奥行]を壁描画 ここまで ここまで XYD=XYDの右 ここまで XYD=XYD0の右の右の右 3回、 列は3-回数 XはXYD[0] YはXYD[1] もし、X≧0&&X<列数&&Y≧0&&Y<列数ならば、 もし、迷路[Y][X]=1ならば、 壁描画情報["右側"][列][奥行]を壁描画 ここまで ここまで XYD=XYDの左 ここまで 黄色に塗り色設定 白色に線色設定 XYD=XYD0の左の左 5回、 列は回数-3 XはXYD[0] YはXYD[1] もし、X≧0&&X<列数&&Y≧0&&Y<列数ならば、 もし、迷路[Y][X]=2ならば、 壁描画情報["床"][列][奥行]を壁描画 ここまで ここまで XYD=XYDの右 ここまで ここまで キャンバス状態復元 ここまで # 迷路を作成する処理 ●(列数の)迷路作成とは 迷路は列数の初期迷路作成 迷路を1と1から2で到達チェック 迷路に2で穴開け 迷路から2のマーククリア 迷路を戻す ここまで ●(列数の)初期迷路作成とは 方位は[ [-1, 0], [ 1, 0], [ 0,-1], [ 0, 1] ] # 迷路データを全部0で初期化 迷路は[] Yを0から(列数-1)まで繰り返す 迷路[Y] = [] Xを0から(列数-1)まで繰り返す 迷路[Y][X] = 0 ここまで ここまで。 # 外周を壁にする 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つ壁を配置する Yを2から(列数-3)まで繰り返す Xを2から(列数-3)まで繰り返す もし(X%2=1)または(Y%2=1)ならば続ける。 迷路[Y][X] = 1 # 上下左右のいずれかの空いてる方向を壁にする 方位を配列シャッフルする。 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からマークで到達チェック モウ一度フラグはオン 抜ける ここまで ここまで。 ここまで ここまで ここまで。 ここまで # 疑似3D表示の際に使う壁や床の座標を求める ●(AとBの)交点とは det=(A[0][0]-A[1][0])*(B[1][1]-B[0][1])-(B[1][0]-B[0][0])*(A[0][1]-A[1][1]) t=((B[1][1]-B[0][1])*(B[1][0]-A[1][0])+(B[0][0]-B[1][0])*(B[1][1]-A[1][1]))/det x=t*A[0][0]+(1-t)*A[1][0] y=t*A[0][1]+(1-t)*A[1][1] [x,y]で戻る ここまで ●(環境情報で)交点マトリクス作成とは MTXは[] 原点は[0,0] 消失点は環境情報["消失点"] 視界距離は環境情報["視界距離"] 真横壁比率は環境情報["真横壁比率"] 奇数升比率は環境情報["奇数升比率"] 偶数升比率は環境情報["偶数升比率"] 比率合計=真横壁比率 視界距離回、 もし、回数%2=1ならば、比率合計=比率合計+奇数升比率。 もし、回数%2=0ならば、比率合計=比率合計+偶数升比率。 ここまで 交点リストは[] 交点リストに原点を配列追加 距離は真横壁比率 視界距離回、 XYは[原点,消失点]と[[示唆点*距離/比率合計,0],D]の交点 XYを交点リストに配列追加 もし、回数%2=1ならば、距離=距離+奇数升比率。 もし、回数%2=0ならば、距離=距離+偶数升比率。 ここまで MTX[0]は交点リスト XYはMTX[0][1] W1はW-XY[0]*2 X1は原点[0]+XY[0]-W1 Y1はXY[1] 原点1は[[X1, Y1],消失点]と[原点,[X1,原点[1]]]の交点 交点リストは[] 交点リストに原点1を配列追加 視界距離回、 XY1はMTX[0][回数] XYは[原点1,消失点]と[XY1,[原点1[0],XY1[1]]]の交点 XYを交点リストに配列追加 ここまで MTX[1]は交点リスト XYはMTX[0][1] X2は原点[0]+XY[0]-W1*2 Y2はXY[1] 原点2は[[X2, Y2],消失点]と[原点,[X2,原点[1]]]の交点 交点リストは[] 交点リストに原点2を配列追加 視界距離回、 XY1はMTX[0][回数] XYは[原点2,消失点]と[XY1,[原点2[0],XY1[1]]]の交点 XYを交点リストに配列追加 ここまで MTX[2]は交点リスト MTXで戻る ここまで ●(交点マトリクスから環境情報で)壁描画情報準備とは 消失点は環境情報["消失点"] Wは環境情報["表示幅"] Hは環境情報["表示高"] WALLは{正面:{}, 右側:{}, 左側:{}, 床:{}} # 視界方向の側面に見える壁 3回、 路地番号は回数-1 左壁リストは[] 右壁リストは[] ((交点マトリクス[路地番号]の配列要素数)-1)回、 XY0は交点マトリクス[路地番号][回数-1] XY1は交点マトリクス[路地番号][回数] X0=(消失点[0]-XY0[0])/消失点[0]*(W-消失点[0])+消失点[0] Y0=(消失点[1]-XY0[1])/消失点[1]*(H-消失点[1])+消失点[1] X1=(消失点[0]-XY1[0])/消失点[0]*(W-消失点[0])+消失点[0] Y1=(消失点[1]-XY1[1])/消失点[1]*(H-消失点[1])+消失点[1] 左壁リストに[XY0, XY1, [XY1[0], Y1], [XY0[0], Y0]]を配列追加 右壁リストに[[X0, XY0[1]], [X1, XY1[1]], [X1, Y1], [X0, Y0]]を配列追加 ここまで WALL["左側"][路地番号*(-1)]は左壁リスト WALL["右側"][路地番号]は右壁リスト ここまで # n本となりの列の正面に見える壁 2回、 路地番号は回数 左壁リストは[] 右壁リストは[] ((交点マトリクス[路地番号]の配列要素数)-1)回、 XY0は交点マトリクス[路地番号-1][回数] XY1は交点マトリクス[路地番号][回数] X0=(消失点[0]-XY0[0])/消失点[0]*(W-消失点[0])+消失点[0] Y0=(消失点[1]-XY0[1])/消失点[1]*(H-消失点[1])+消失点[1] X1=(消失点[0]-XY1[0])/消失点[0]*(W-消失点[0])+消失点[0] Y1=(消失点[1]-XY1[1])/消失点[1]*(H-消失点[1])+消失点[1] 左壁リストに[XY0, XY1, [XY1[0], Y1], [XY0[0], Y0]]を配列追加 右壁リストに[[X0, XY0[1]], [X1, XY1[1]], [X1, Y1], [X0, Y0]]を配列追加 ここまで WALL["正面"][路地番号*(-1)]は左壁リスト WALL["正面"][路地番号]は右壁リスト ここまで # 正面の列 前壁リストは[] (WALL["正面"][1]の配列要素数)回、 XY0はWALL["正面"][1][回数-1][0] XY1はWALL["正面"][-1][回数-1][0] XY2はWALL["正面"][-1][回数-1][3] XY3はWALL["正面"][1][回数-1][3] 前壁リストに[XY0, XY1, XY2, XY3]を配列追加 ここまで WALL["正面"][0]は前壁リスト # n本となりの列の床 2回、 路地番号は回数 左床リストは[] 右床リストは[] (WALL["右側"][路地番号]の配列要素数)回、 壁1はWALL["左側"][路地番号*(-1)][回数-1] 壁2はWALL["左側"][(路地番号-1)*(-1)][回数-1] 左床リストに[壁1[2], 壁1[3], 壁2[3], 壁2[2]]を配列追加 壁1はWALL["右側"][路地番号][回数-1] 壁2はWALL["右側"][路地番号-1][回数-1] 右床リストに[壁1[2], 壁1[3], 壁2[3], 壁2[2]]を配列追加 ここまで WALL["床"][路地番号*(-1)]は左床リスト WALL["床"][路地番号]は右床リスト ここまで # 床 床リストは[] (WALL["床"][1]の配列要素数)回、 床1はWALL["床"][-1][回数-1] 床2はWALL["床"][1][回数-1] 床リストに[床1[2], 床1[3], 床2[3], 床2[2]]を配列追加 ここまで WALL["床"][0]は床リスト WALLを戻す ここまで ●(列を)壁表示テストとは 表示領域に描画クリア CTXは描画中コンテキスト 1に線太さ設定 もし、オフならば、 黒色に線色設定 CTXの"beginPath"を[]でJSメソッド実行 CTXの"moveTo"を交点マトリクス[0][0]でJSメソッド実行 CTXの"lineTo"を消失点でJSメソッド実行 CTXの"stroke"を[]でJSメソッド実行 ここまで 視界距離回、 黒色に線色設定 壁リストは壁描画情報["正面"][列] 壁リスト[回数-1]を壁描画 もし、列≧0ならば、 緑色に線色設定 壁リストは壁描画情報["右側"][列] 壁リスト[回数-1]を壁描画 ここまで もし、列≦0ならば、 青色に線色設定 壁リストは壁描画情報["左側"][列] 壁リスト[回数-1]を壁描画 ここまで 黄色に線色設定 壁リストは壁描画情報["床"][列] 壁リスト[回数-1]を壁描画 ここまで ここまで