▶ 実 行
▶ 実行
クリア
スマートボールっぽいゲーム(ThreeJS+AmmoJS)
by てぃふと@うぇいく
!「https://n3s.nadesi.com/plain/plugin_weykthree.js」を取り込む !「https://n3s.nadesi.com/plain/plugin_weykammo.js」を取り込む AMOベースURL=「https://weyk.sakura.ne.jp/storage/ammojs」 # 長さの単位をcmといて扱う。重力加速度を98とすることで時間とのスケールを合わせる。 # 質量はキログラム単位。 # 床を突き抜けるようなら、ボールを大きくするか床を厚くする。 ボール個数は15 ボール半径は1.5 # 半径1.5cm球 ボール質量は3 # 3kg 重力は98 # 98cm/s^2 初期弾数は30 緑色大当は15 緑色中当は3 緑色小当は3 黄色大当は10 黄色小当は5 水色大当は15 水色小当は8 全当追加は20 # 基本空間情報(1m*1m*50cm) 床辺長は100 # 1m四方 床厚は0.2 # 2mm 壁高は50 # 50cm # スマートボール台情報 板厚は0.2 # 枠等の厚さ。2mm。 台厚は4 # 台のボールの転がる空間の高さ。4cm 台幅は60 # 台の幅。60cm 台奥は80 # 台の奥行。80cm 射出部幅は4 # ボール射出部の幅 射出部根本長は5 # ボール射出部の根本の横の壁の長さ 防止板長は6 # ボール射出部根本の逆流防止板の長さ 射出部廃弾幅は5 # ボール射出部根本の逆流防止部分の隙間の幅 #衝突時に跳ね返りはぶつかったもの同士での反発率の積で決まります。 #積が1.0を超える場合、ぶつかる勢いより跳ね返る勢いが強くなります(総エネルギーが増加する) 床反発率は0.7 # 黄色い地面 壁反発率は0.7 # 黄色い地面の外周にある見えない壁 ボール反発率は0.8 # ボール自身。全て、この値との積になる。 枠反発率は0.1 # 本体全般部分 ガラス反発率は1.0 # ガラス部分。いまのところ未使用。蓋は無い。 釘反発率は0.8 # 釘。 ゴム反発率は0.3 # ゴム。 # 衝突判定の許容誤差(距離) 衝突マージンは0.001 # 0.1mm カップ位置リストは[ [-12,-13],[12,-13], [-8,-8],[8,-8], [0,5], [-10,10],[10,10] [-15,20],[0,20],[15,20] ] 釘位置リストは[ [-15,-25],[-10,-25],[-5,-28],[0,-28],[5,-28],[10,-25],[15,-25], [-8,-23],[-2.5,-23],[2.5,-23],[8,-23], [-18,-20],[-13,-20],[-8,-18],[0,-18],[8,-18],[13,-20],[18,-20], [-4,-14],[0,-12],[4,-14], [-20,-6],[-16,-5],[16,-5],[20,-6],[24,-7], [-2,-3],[2,-3], [-18,-1],[-14,-1.5],[-10,-1],[-6,-1.5],[-2.5,-1],[1.5,-1],[6,-1.5],[10,-1],[14,-1.5],[18,-1],[22,-1.5], [-21,4],[-16,4],[-11,4],[-6,4],[6,4],[11,4],[16,4],[21,4],[26,4], [-20,10],[-16.5,10],[-2.5,11],[2.5,11],[16.5,10],[20,10],[23.5,10], [-19,15],[-15,15],[0,14.5],[15,15],[19,15], [-7,18],[7,18] ] WEBGLキャンバスはNULL レンダラはNULL ココはNULL カメラはNULL 物理ワールドはNULL 前回タイムスタンプは0 床はNULL 床鋼体はNULL スマートボール台はNULL 元防止板はNULL 元防止板固定先はNULL # Ammo適用用 変動物リストは空配列 ボール鋼体リストは空配列 鋼体索引は{} ワールドマトリクスワークはNULL インカップ配列は空配列 カップ幽体リストは空配列 ゲームオーバはオン 残弾は0 シュート中はオフ シュートメータは0 シュートメータ初期値は10 シュートメータ方向は1 シュートメータ上限は100 シュートパワー基本値は150 シュートパワー可変幅は100 開始する ●ライブラリ準備とは TJSライブラリ読み込み後には プラグイン準備 ここまで ここまで ●プラグイン準備とは ["controls/OrbitControls.js", "libs/ammo.wasm.js"]をTJSプラグイン読み込み後には AMMOライブラリ準備 ここまで ここまで ●AMMOライブラリ準備とは AMOライブラリ読込後には 準備完了 ここまで ここまで ●準備完了とは WEBGLキャンバス要素準備 描画準備 描画中キャンバスの「pointerdown」に「キャンバスクリックON」をDOMイベント追加する 描画中キャンバスの「pointerup」に「キャンバスクリックOFF」をDOMイベント追加する 0でアニメート ここまで ●WEBGLキャンバス要素準備とは WEBGLキャンバスは"#three_cv"のDOM要素取得 もし、WEBGLキャンバスでなければ、 Pは描画中キャンバス["parentNode"] WEBGLキャンバスは"CANVAS"のDOM要素作成 WEBGLキャンバス["id"]は"three_cv" WEBGLキャンバス["width"]は描画中キャンバス["width"] WEBGLキャンバス["height"]は描画中キャンバス["height"] WEBGLキャンバス["style"]["display"]は「none」 PにWEBGLキャンバスをDOM子要素追加 ここまで ここまで ●後始末とは 描画中キャンバスの「pointerdown」から「キャンバスクリックON」をDOMイベント削除する 描画中キャンバスの「pointerup」から「キャンバスクリックOFF」をDOMイベント削除する ここまで ●シュート開始とは シュート中はオン シュートメータはシュートメータ初期値 シュートメータ方向は1 ここまで ●シュート終了とは シュート中はオフ 結果は(シュートメータ/シュートメータ上限)でボールシュートする もし、結果ならば、 残弾は残弾-1 ここまで ここまで ●キャンバスクリックOFFとは もし、シュート中ならば、 シュート終了する ここまで ここまで ●キャンバスクリックONとは EVTはWINDOW["event"] 要素位置はEVT["target"]の"getBoundingClientRect"を[]でJSメソッド実行 XはEVT["clientX"]-要素位置["left"] YはEVT["clientY"]-要素位置["top"] もし、Y≦40ならば、 # 上部のコントロールパネル部分のどこかを押している もし、X≧40*10+5+1&&X≦40*10+5+1+60-2&&Y≧0+1&&Y≦0+1+40-2ならば、 # 開始・払出ボタンの場所を押している もし、ゲームオーバならば、 スタート処理する 違えば、 払出処理する ここまで ここまで 違えばもし、残弾>0ならば、 もし、X≧5+40/2-16&&X≦5+40/2+16&&Y≧描画中キャンバス["height"]-200+195-20-16&&Y≦描画中キャンバス["height"]-200+195-20+16ならば、 # シュートボタンのあたりを押している シュート開始する ここまで ここまで ここまで ●ボール位置リセットとは # 全ボールを初期位置に戻す # ボール同士の重なり回避のため、カップ以外のボールも全て戻す Iは0 ボール鋼体リストを反復する 鋼体は対象 Xは-28+4+I*(ボール半径*2+0.2) Yは3.5 Zは33 ワールドマトリクスワークにAMO単位行列設定 ワールドマトリクスワークに[X, Y, Z]をAMO原点設定 鋼体にワールドマトリクスワークをAMOワールド変換行列設定 (鋼体からAMO状態管理器取得)にワールドマトリクスワークをAMOワールド変換行列設定 鋼体をAMO力静止 鋼体に[0, 0, 0]をAMO移動速度設定 鋼体に[0, 0, 0]をAMO回転速度設定 鋼体をAMO活性化 IはI+1 ここまで ここまで ●スタート処理とは 残弾は初期弾数 ボール位置リセット ゲームオーバはオフ ここまで ●払出処理とは # 各カップにボールがあるかどうかをチェック カップインは空配列 Iは0 Jは0 カップ幽体リストを反復する 幽体は対象 数は幽体からAMOオーバーラップ数取得 もし、数>0ならば、 カップイン[I]は1 JはJ+1 違えば、 カップイン[I]は0 ここまで IはI+1 ここまで # ボールのあるカップの組み合わせに対して払い出す もし、カップイン[0]+カップイン[1]+カップイン[2]+カップイン[3]=4ならば、 # 緑色大当たり 残弾は残弾+緑色大当 違えばもし、カップイン[0]+カップイン[1]+カップイン[2]+カップイン[3]=3ならば、 # 緑色中当たり 残弾は残弾+緑色中当 違えばもし、カップイン[0]+カップイン[1]+カップイン[2]+カップイン[3]=2ならば、 # 緑色小当たり 残弾は残弾+緑色小当 ここまで もし、カップイン[4]+カップイン[5]+カップイン[6]=3ならば、 # 黄色大当たり 残弾は残弾+黄色大当 違えばもし、カップイン[4]+カップイン[5]+カップイン[6]=2ならば、 # 黄色小当たり 残弾は残弾+黄色小当 ここまで もし、カップイン[7]+カップイン[8]+カップイン[9]=3ならば、 # 水色大当たり 残弾は残弾+水色大当 違えばもし、カップイン[7]+カップイン[8]+カップイン[9]=2ならば、 # 水色小当たり 残弾は残弾+水色小当 ここまで もし、J=10ならば、 残弾は残弾+全当追加 ここまで ボール位置リセット もし、残弾=0ならば、 ゲームオーバはオン ここまで ここまで ●シュートパネル表示とは X0=5 Y0=描画中キャンバス["height"]-200 # 地色描画 1に線太さ設定 "#000000FF"に線色設定 "#ccccccFF"に塗り色設定 [X0,Y0,40,195]に四角描画 # シュートボタンを描画 もし、シュート中ならば、 "#88ff88FF"に塗り色設定 違えばもし、残弾>0ならば、 "#448844FF"に塗り色設定 違えば、 "#884444FF"に塗り色設定 ここまで [X0+40/2,Y0+195-20]に16の円描画 描画中コンテキスト["textAlign"]は"center" 描画中コンテキスト["textBaseline"]は"middle" "#000000FF"に塗り色設定 「16px bold sans-serif」に描画フォント設定 [X0+40/2,Y0+195-20]に「打」を文字描画 # シュートパワーメータを描画 "#444444FF"に塗り色設定 [X0+10,Y0+10,20,145]に四角描画 もし、シュート中ならば、 "#00ffffFF"に塗り色設定 違えば、 "#00ccccFF"に塗り色設定 ここまで パワーはシュートメータ/シュートメータ上限 [X0+10,Y0+10+((1-パワー)*145),20,パワー*145]に四角描画 ここまで ●番号パネル表示とは 描画中コンテキスト["textAlign"]は"center" 描画中コンテキスト["textBaseline"]は"middle" Yは40/2 # 地色描画 "#ccccccFF"に塗り色設定 [0,0,描画中キャンバス["width"],40]に四角描画 # 払出ボタンの枠表示 Xは40*10+2 1に線太さ設定 "#000000FF"に線色設定 "#ffffffFF"に塗り色設定 [40*10+5+1,0+1,60-2,40-2]に四角描画 空に線色設定 「36px bold sans-serif」に描画フォント設定 # 背景部分塗分け "#88ff88FF"に塗り色設定 [0,0,40*4,40]に四角描画 "#ffff88FF"に塗り色設定 [40*4,0,40*3,40]に四角描画 "#aaffffFF"に塗り色設定 [40*7,0,40*3,40]に四角描画 # カップイン状態表示 Iは0 カップ幽体リストを反復する 幽体は対象 数は幽体からAMOオーバーラップ数取得 もし、数>0ならば、 もし、I<4ならば、 "#22aa66ff"に塗り色設定 違えばもし、I<7ならば、 "#ff8800ff"に塗り色設定 違えば、 "#0044ffff"に塗り色設定 ここまで 違えば、 黒色に塗り色設定 ここまで XはI*40+20 [X,Y]にIを文字描画 IはI+1 ここまで # 残弾数表示 描画中コンテキスト["textAlign"]は"right" 黒色に塗り色設定 Xは描画中キャンバス["width"]-10 [X,Y]に"{残弾} 回"を文字描画 # 払出・開始ボタンの文字表示 描画中コンテキスト["textAlign"]は"center" 「28px bold sans-serif」に描画フォント設定 "#cc4444FF"に塗り色設定 もし、ゲームオーバならば、 文言は「開始」 違えば、 文言は「払出」 ここまで [40*10+5+60/2,Y]に文言を文字描画 ここまで # 基本単位に従いものを配置する。 # この世界では、長さはメートル、重さはキログラム、時間は秒で指定する。 # ただし、あまり細かい数値はうまく扱えない。 ●描画準備とは # 物理エンジンの空間(力学ワールド)を準備 # 物理ワールドは標準鋼体ワールド作成 # 表示するためのシーンを準備 # ココは、TJSシーン作成 ココに0x004400をTJS背景設定 # カメラを準備 # カメラは、[50,WEBGLキャンバス["width"]/WEBGLキャンバス["height"],0.5,200]のTJS透視投影カメラ作成 カメラを[5,100,25]にTJS位置設定 カメラを"+Y"にTJSカメラ上方設定 ココにカメラをTJS登場 カメラのTJS投影マトリクス更新 ココに基本空間作成する スマートボール台はスマートボール作成 ココにスマートボール台をTJS登場 スマートボール台を[0,8,0]にTJS位置設定 スマートボール台["rotation"]["x"]は8/180*PI スマートボール台に一括鋼体作成 # 光源を準備 # # 全体をぼやっと照らす環境光源を生成 光は0x202020のTJS環境光源作成 ココに光をTJS登場 # 1方向から照らす平行光源を生成 太陽は[0xffffff, 0.9]のTJS平行光源作成 太陽を[5,50,5]にTJS位置設定 太陽にオンをTJS影投設定 ココに太陽をTJS登場 #太陽の["シャドー"]に[512,512]をTJSマップサイズ設定 #太陽の["シャドー","カメラ"]に0.1をTJSカメラ最近距離設定 #太陽の["シャドー","カメラ"]に150をTJSカメラ最遠距離設定 #太陽の["シャドー","カメラ"]に[-64,-64,64,64]をTJSカメラ矩形距離設定 ボール形状は{半径:ボール半径, 横分割数:8, 縦分割数:8, バッファ:オン}のTJS球体作成 ボール素材は{ color: 0x44ff22 }のTJS拡散反射材質作成 形状はボール半径のAMO球形状作成 形状に衝突マージンをAMOマージン設定 (ボール個数)回繰り返す ボールはボール形状とボール素材のTJSメッシュ作成 Xは-28+4+(回数-1)*(ボール半径*2+0.2) Yは3.5 Zは38 ボールを[X,Y,Z]にTJS位置設定 ボールにオンをTJS影投設定 ココにボールをTJS登場 ボール鋼体はボールから形状のボール質量でMESH付鋼体作成 ボール鋼体にボール反発率でAMO反発係数設定 変動物リストに{表示体:ボール, 鋼体:ボール鋼体}を配列追加する 鋼体索引[ボール["id"]]はボール鋼体 ボール鋼体リストにボール鋼体を配列追加 物理ワールドにボール鋼体をAMO鋼体追加 ここまで # ThreeJSの表示準備 # レンダラは'three_cv'にTJS描画準備 レンダラに[WEBGLキャンバス["width"],WEBGLキャンバス["height"]]をTJSサイズ設定 レンダラに0x000000をTJSクリア色設定 レンダラをTJS影処理有効 # ThreeJSのオービットコントロールを作成して適用 # # DOMには採取的に表示に使うキャンバスを指定する コントローラはカメラに描画中キャンバスのTJS衛星軌道コントローラ作成 ここまで ●(ココに)基本空間作成とは # 床を生成する # # 床の見た目 床材は{"幅":床辺長,"高":床厚,"奥行":床辺長,バッファ:オン}のTJS箱作成 床素材は{color: 0xffff00}のTJS拡散反射材質作成 床は床材と床素材のTJSメッシュ作成 床にオンをTJS影受設定 床をココにTJS登場 # 床の物理エンジン空間の実体 形状は[床辺長÷2,床厚÷2,床辺長÷2]でAMO箱形状作成 形状に衝突マージンをAMOマージン設定 床鋼体は床から形状の0でMESH付鋼体作成 床鋼体に床反発率でAMO反発係数設定 物理ワールドに床鋼体をAMO鋼体追加 # 壁を物理エンジン空間に配置。表示はしない。側面の四方を囲む。 形状は[床辺長÷2,壁高÷2,床厚÷2]でAMO箱形状作成 形状に衝突マージンをAMOマージン設定 マトリクスはAMO変形マトリクス作成 マトリクスをAMO単位行列設定 マトリクスに[0, 壁高÷2, 床辺長÷2]をAMO原点設定 壁鋼体はマトリクスから形状の0でMESH無鋼体作成 壁鋼体に壁反発率でAMO反発係数設定 物理ワールドに壁鋼体をAMO鋼体追加 マトリクスはAMO変形マトリクス作成 マトリクスをAMO単位行列設定 マトリクスに[0, 壁高÷2, (-床辺長÷2)]をAMO原点設定 壁鋼体はマトリクスから形状の0でMESH無鋼体作成 壁鋼体に壁反発率でAMO反発係数設定 物理ワールドに壁鋼体をAMO鋼体追加 形状は[床厚÷2,壁高÷2,床辺長÷2]でAMO箱形状作成 形状に衝突マージンをAMOマージン設定 マトリクスはAMO変形マトリクス作成 マトリクスをAMO単位行列設定 マトリクスに[床辺長÷2, 壁高÷2, 0]をAMO原点設定 壁鋼体はマトリクスから形状の0でMESH無鋼体作成 壁鋼体に壁反発率でAMO反発係数設定 物理ワールドに壁鋼体をAMO鋼体追加 マトリクスはAMO変形マトリクス作成 マトリクスをAMO単位行列設定 マトリクスに[(-床辺長÷2), 壁高÷2, 0]をAMO原点設定 壁鋼体はマトリクスから形状の0でMESH無鋼体作成 壁鋼体に壁反発率でAMO反発係数設定 物理ワールドに壁鋼体をAMO鋼体追加 ここまで ●(パワーで)ボールシュートする シュートフラグはオフ ボール鋼体リストを反復する 鋼体は対象 姿勢状態は鋼体のAMO状態管理器取得 姿勢状態からワールドマトリクスワークにAMOワールド変換行列取得 位置はワールドマトリクスワークからAMO原点取得 VECは(位置のTJSVec3) もし、VEC["z"]>35ならば、 シュートフラグはオン Xは-28 Yは3.5 Zは38 ワールドマトリクスワークにAMO単位行列設定 ワールドマトリクスワークに[X, Y, Z]をAMO原点設定 鋼体にワールドマトリクスワークをAMOワールド変換行列設定 (鋼体からAMO状態管理器取得)にワールドマトリクスワークをAMOワールド変換行列設定 力加減はシュートパワー基本値+シュートパワー可変幅*パワー+(5の乱数)+(5の乱数) 鋼体をAMO力静止 鋼体に[0, 0, 0]をAMO移動速度設定 鋼体に[0, 0, 0]をAMO回転速度設定 鋼体を[0, 0, -力加減]でAMO重心押 鋼体をAMO活性化 抜ける ここまで ここまで シュートフラグで戻る ここまで # スマートボールの盤を作成する。足は無い(後から傾けるため) # グループごと毎傾けるので、本関数内ではY+0の上に平に設定する ●スマートボール作成とは # 各パーツを生成してGroupにまとめる コレはTJSグループ作成 # 板素材を準備する # ローダは{パス:"https://n3s.nadesi.com/"}でTJSテクスチャローダ作成 色TEXはローダから「image.php?f=31.jpg」をTJS読み込み 視差TEXはローダから「image.php?f=32.jpg」をTJS読み込み ラフTEXはローダから「image.php?f=33.jpg」をTJS読み込み 法線TEXはローダから「image.php?f=35.jpg」をTJS読み込み 板素材は{map:色TEX,bumpMap:視差TEX,normalMap:法線TEX,roughnessMap:ラフTEX}のTJS標準材質作成 板素材["map"]["warpS"]はTHREE["RepeatWrapping"] 板素材["map"]["warpT"]はTHREE["RepeatWrapping"] 裏板素材は{map:色TEX,bumpMap:視差TEX,normalMap:法線TEX,roughnessMap:ラフTEX, side: THREE["BackSide"]}のTJS標準材質作成 裏板素材["map"]["warpS"]はTHREE["RepeatWrapping"] 裏板素材["map"]["warpT"]はTHREE["RepeatWrapping"] ゴム素材は{color: 0x080808, roughness: 0.8}のTJS標準材質作成 釘素材は{color: 0xcccccc}のTJS標準材質作成 # 底を生成する 構造は{"幅":台幅,"高":板厚,"奥行":台奥,バッファ:オン}のTJS箱作成 物は構造と板素材のTJSメッシュ作成 物を[0,板厚/2,0]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 # 手前壁を生成する 構造は{"幅":台幅,"高":台厚,"奥行":板厚,バッファ:オン}のTJS箱作成 物は構造と板素材のTJSメッシュ作成 物を[0,台厚/2+板厚,板厚/2-台奥/2]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 # 奥壁を生成する 物は構造と板素材のTJSメッシュ作成 物を[0,台厚/2+板厚,台奥/2-板厚/2]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 # 左壁を生成する 構造は{"幅":板厚,"高":台厚,"奥行":台奥,バッファ:オン}のTJS箱作成 物は構造と板素材のTJSメッシュ作成 物を[板厚/2-台幅/2,台厚/2+板厚,0]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 # 右壁を生成する 物は構造と板素材のTJSメッシュ作成 物を[台幅/2-板厚/2,台厚/2+板厚,0]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 # 左壁その2根本を生成する 構造は{"幅":板厚,"高":台厚,"奥行":射出部根本長,バッファ:オン}のTJS箱作成 物は構造と板素材のTJSメッシュ作成 物を[0-(台幅/2-板厚-射出部幅-板厚/2),板厚+台厚/2,台奥/2-板厚-射出部根本長/2]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 元防止板固定先は物 # 左壁その2先を生成する 構造は{"幅":板厚,"高":台厚,"奥行":42,バッファ:オン}のTJS箱作成 物は構造と板素材のTJSメッシュ作成 物を[0-(台幅/2-板厚-射出部幅-板厚/2),板厚+台厚/2,6.8]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 # 左壁その2先の防止板ストッパを生成する 構造は{"幅":2,"高":台厚,"奥行":3.5,バッファ:オン}のTJS箱作成 物は構造と板素材のTJSメッシュ作成 物を[0-(台幅/2-板厚-板厚-射出部幅-2/2),板厚+台厚/2,台奥/2-板厚-射出部根本長-射出部廃弾幅-0.5-3/2]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 # 上部カーブ端のバウンダを生成する 構造は{"半径":1,"高":台厚,"円分割数":8,バッファ:オン}のTJSシリンダ体作成 物は構造とゴム素材のTJSメッシュ作成 物を[台幅/2-1,台厚/2+板厚,台幅/2-台奥/2]にTJS位置設定 物["name"]は「ゴム」 物をコレにTJS登場 # 上部カーブを生成する 構造は{"半径":台幅/2,"高":台厚,"円分割数":30,"上下開放":1,円開始位置:PI/2,円長:PI,バッファ:オン}のTJSシリンダ体作成 物は構造と裏板素材のTJSメッシュ作成 物を[0,板厚+台厚/2,台幅/2-台奥/2]にTJS位置設定 物["name"]は「木枠」 物をコレにTJS登場 # 戻り防止版を生成する 構造は{"幅":板厚,"高":台厚-板厚-板厚,"奥行":防止板長,バッファ:オン}のTJS箱作成 物は構造と板素材のTJSメッシュ作成 物を[0-(台幅/2-板厚-射出部幅-板厚/2),板厚+台厚/2,台奥/2-板厚-射出部根本長-防止板長/2]にTJS位置設定 物["name"]は「防止板」 物をコレにTJS登場 元防止板は物 # 釘 構造は{"半径":0.2,"高":台厚,"円分割数":8,バッファ:オン}のTJSシリンダ体作成 # 左側沿いの釘 Xは0-(台幅/2-板厚-板厚-射出部幅-2+1.2) 6回繰り返す 物は構造と釘素材のTJSメッシュ作成 Zは台奥/2-板厚-射出部根本長-射出部廃弾幅-0.5-3/2-4-(回数-1)*7 物を[X,台厚/2+板厚,Z]にTJS位置設定 物["name"]は「釘」 物をコレにTJS登場 ここまで 物は構造と釘素材のTJSメッシュ作成 Xは0-(台幅/2-板厚-板厚-射出部幅-2+1.5)+1 Zは台奥/2-板厚-射出部根本長-射出部廃弾幅-0.5-3/2-4+1.5 物を[X,台厚/2+板厚,Z]にTJS位置設定 物["name"]は「釘」 物をコレにTJS登場 # 右側沿いの釘 Xは0+(台幅/2-板厚-2+1.2) 5回繰り返す 物は構造と釘素材のTJSメッシュ作成 Zは台奥/2-板厚-射出部根本長-射出部廃弾幅-0.5-3/2-3-(回数-1)*8 物を[X,台厚/2+板厚,Z]にTJS位置設定 物["name"]は「釘」 物をコレにTJS登場 ここまで # 釘製のカップもどきを並べる カップ位置リストを反復する XZは対象 コレのXZに構造と釘素材で釘カップ作成 ここまで # 釘製を並べる 釘位置リストを反復する XZは対象 物は構造と釘素材のTJSメッシュ作成 XはXZ[0] ZはXZ[1] 物を[X,台厚/2+板厚,Z]にTJS位置設定 物["name"]は「釘」 物をコレにTJS登場 ここまで コレで戻る ここまで # 釘製のカップもどきとなる釘を配置する # 釘でボールより2割大きい半円を描く ●(コレのXZに構造と釘素材で)釘カップ作成とは 分割数は6 (分割数)回繰り返す Iは回数-1 物は構造と釘素材のTJSメッシュ作成 XはXZ[0]+ボール半径*SIN(PI/(分割数-1)*I-PI/2)*1.2 ZはXZ[1]+ボール半径*COS(PI/(分割数-1)*I-PI/2)*1.2 物を[X,台厚/2+板厚,Z]にTJS位置設定 物["name"]は「釘」 物をコレにTJS登場 ここまで ここまで ●(コレに)一括鋼体作成とは 防止板鋼体はNULL 固定先鋼体はNULL # 非可動部の設定を行う コレ["children"]を反復する 物は対象 物にオンをTJS影受設定 物にオンをTJS影投設定 重量は0 反発率は0.0 物["name"]で条件分岐する 「木枠」ならば、 反発率は枠反発率 ここまで 「ゴム」ならば、 反発率はゴム反発率 ここまで 「ガラス」ならば、 反発率はガラス反発率 ここまで 「釘」ならば、 反発率は釘反発率 ここまで 「防止板」ならば、 可動はオン 重量は0.5 反発率は枠反発率 ここまで ここまで 鋼体は物から重量でMESH鋼体作成 鋼体に反発率でAMO反発係数設定 物理ワールドに鋼体をAMO鋼体追加 もし、重量>0ならば、 物をコレからTJS退場 物をココにTJS登場 変動物リストに{表示体:物, 鋼体:鋼体}を配列追加する 鋼体索引[物["id"]]は鋼体 鋼体に4をAMO活性状態設定 ここまで もし、元防止板固定先=物ならば、 固定先鋼体は鋼体 ここまで もし、元防止板=物ならば、 防止板鋼体は鋼体 ここまで ここまで 軸は[0,1,0]のTJSVec3 位置Aは[0-板厚/2,0,-2.5]のTJSVec3 位置Bは[0-板厚/2,0,3.5]のTJSVec3 接合点Aは固定先鋼体の位置Aに軸でAMO接合軸作成 接合点Bは防止板鋼体の位置Bに軸でAMO接合軸作成 制約は接合点Aと接合点BのAMO蝶番制約作成 物理ワールドに制約をAMO制約追加 制約を5.0と1でAMO回転トルク力有効化 # 制約の"setLimit"を[-0.001,PI/2]でJSメソッド実行 形状は0.2でAMO球形状作成 MATはコレからTJSワールドマトリクス取得 カップ位置リストを反復する XZは対象 位置は[XZ[0], 台厚/2+板厚, XZ[1]+1]のTJSVec3 位置にMATをTJSマトリクス適用 幽体はAMO幽体作成 幽体に形状をAMO形状設定 ワールドマトリクスワークにAMO単位行列設定 ワールドマトリクスワークに(位置からAMOVec3)をAMO原点設定 幽体にワールドマトリクスワークをAMOワールド変換行列設定 物理ワールドに幽体をAMO衝突オブジェクト追加 カップ幽体リストに幽体を配列追加 ここまで ここまで # アニメーションのループを構成する # 呼び出しごとの時間差の算出もここで行う ●(タイムスタンプで)アニメートとは もし、前回タイムスタンプが0でなければ、 経過秒は(タイムスタンプ-前回タイムスタンプ)÷1000 経過秒でワンフレーム ここまで 前回タイムスタンプはタイムスタンプ 画面更新時実行には(タイムスタンプ) タイムスタンプでアニメート ここまで ここまで # アニメーションの1フレーム分を処理する ●(経過秒で)ワンフレームとは # 力学ワールドの時間を経過時間分進める 物理ワールドを経過秒で10までAMO時間経過 # 力学ワールド上の鋼体の位置・姿勢を3Dモデル空間のモデルに反映する 変動物リストを反復する 表示体は対象["表示体"] 鋼体は対象["鋼体"] 鋼体を表示体に物体姿勢反映 ここまで もし、シュート中ならば、 シュートメータはシュートメータ+シュートメータ方向*3 もし、シュートメータ<0||シュートメータ>シュートメータ上限ならば、 シュートメータ方向はシュートメータ方向*(-1) シュートメータはシュートメータ+シュートメータ方向*3 ここまで ここまで レンダラにココをカメラでTJS描画 WEBGLキャンバスを[0,0]へ画像描画 番号パネル表示 シュートパネル表示 ここまで ●開始とは ライブラリ準備 ここまで # ThreeJS - Ammo 利用簡易支援 # ThreeJSのexamples/js/physics/AmmoPhysics.jsを参考に作成 # よくある組み合わせで力学ワールドを生成する ●標準鋼体ワールド作成とは CALLBACKはAMO幽体ペア追加削除処理作成 CONFはAMOデフォルト衝突判定法作成 DISPはCONFのAMO衝突判定ディスパッチャ作成 BPHASEはAMODbvt作成 SOLVERはAMO物理ソルバー作成 ワールドは[DISP,BPHASE,SOLVER,CONF]でAMO離散力学ワールド作成 ワールドに[0,(-重力),0]でAMO重力設定 ワールドマトリクスワークはAMO変形マトリクス作成 ワールドにCALLBACKをAMO幽体ペアコールバック設定 ワールドで戻る ここまで # AmmoJSの鋼体の位置・姿勢をThreeJSのMESHに反映する ●(BODYをMESHに)物体姿勢反映とは 姿勢状態はBODYのAMO状態管理器取得 姿勢状態からワールドマトリクスワークにAMOワールド変換行列取得 位置はワールドマトリクスワークからAMO原点取得 回転はワールドマトリクスワークからAMO回転取得 MESHを位置にTJS位置設定 MESHを回転にTJS四元数設定 ここまで # ThreeJSのBoxGeometoryのMESHを情報を元に静的なAmmoJSの鋼体を作成する ●(MESHからMASSで)MESH鋼体作成とは 構造はMESH["geometry"] パラメータは構造["parameters"] 構造["type"]で条件分岐する 「BoxGeometry」ならば、 Wは0.5 Hは0.5 Dは0.5 もし、パラメータ["width"]≠NULLならば、Wはパラメータ["width"]÷2 もし、パラメータ["height"]≠NULLならば、Hはパラメータ["height"]÷2 もし、パラメータ["depth"]≠NULLならば、Dはパラメータ["depth"]÷2 形状は[W,H,D]でAMO箱形状作成 ここまで 「SphereGeometry」ならば、 Rは0.5 もし、パラメータ["radius"]≠NULLならば、Rはパラメータ["radius"] 形状はRでAMO球形状作成 ここまで 「CylinderGeometry」ならば、 もし、パラメータ["thetaStart"]≠NULL&&パラメータ["thetaStart"]≠0ならば、 面配列は空配列 INDEX配列は構造["index"]["array"] 頂点配列は構造["attributes"]["position"]["array"] 点数は(頂点配列の配列要素数)÷3 INDEX数はINDEX配列の配列要素数 (INDEX数÷3)回繰り返す Iは(回数-1)*3 IAはINDEX配列[I+0]*3 IBはINDEX配列[I+1]*3 ICはINDEX配列[I+2]*3 点Aは{x:頂点配列[IA+0], y:頂点配列[IA+1], z:頂点配列[IA+2]} 点Bは{x:頂点配列[IB+0], y:頂点配列[IB+1], z:頂点配列[IB+2]} 点Cは{x:頂点配列[IC+0], y:頂点配列[IC+1], z:頂点配列[IC+2]} 面は[点A, 点B, 点C] 面配列に面を配列追加する ここまで 形状は面配列でAMO凹形状作成 違えば、 RTは0.5 RBは0.5 Hは0.5 もし、パラメータ["radiusTop"]≠NULLならば、RTはパラメータ["radiusTop"] もし、パラメータ["radiusBottom"]≠NULLならば、RBはパラメータ["radiusBottom"] もし、パラメータ["height"]≠NULLならば、Hはパラメータ["height"]÷2 Rは(RT+RB)÷2 形状は[R,H,R]でAMOシリンダ形状作成 ここまで ここまで 違えば、 「この鋼体作成はBoxまたはSphereのみ対応しています。異なる形状は扱えません」でエラー発生 ここまで ここまで 形状に衝突マージンをAMOマージン設定 BODYはMESHから形状のMASSでMESH付鋼体作成 BODYで戻る ここまで # ThreeJSのMESHを情報を元にAmmoJSの鋼体を作成する ●(MESHからSHAPEのMASSで)MESH付鋼体作成とは 位置はNULLのTJSVec3 回転はTJS四元数作成 位置にMESHからTJSワールド位置取得 回転にMESHからTJSワールド四元数取得 マトリクスはAMO変形マトリクス作成 マトリクスをAMO単位行列設定 マトリクスに(位置からAMOVec3)をAMO原点設定 マトリクスに(回転からAMO四元数)をAMO回転設定 BODYはマトリクスからSHAPEのMASSでMESH無鋼体作成 BODYで戻る ここまで # 変換マトリクスから鋼体を作成する ●(マトリクスからSHAPEのMASSで)MESH無鋼体作成とは もし、MASSでなければ、 MASSは0 ここまで 状態管理器はマトリクスからAMOデフォルト状態管理器作成 慣性は[0,0,0]からAMOVec3 SHAPEにMASSと慣性でAMO局所慣性計算 構成情報は[MASS, 状態管理器, SHAPE, 慣性]からAMO鋼体構成情報作成 BODYは構成情報からAMO鋼体作成 BODYで戻る ここまで # 型付配列のヘルパー命令 ●(ARGの)UI8配列とは 『(function (a) {return new Uint8Array(a)})』を[ARG]でJS関数実行で戻る ここまで ●(ARGの)F32配列とは 『(function (a) {return new Float32Array(a)})』を[ARG]でJS関数実行で戻る ここまで