▶ 実 行
▶ 実行
クリア
ライフゲーム(生命シミュレータ)
by てぃふと@うぇいく
「全て」の実行速度優先 画像位置は[0,40] nullはNULL 周囲リストは[ [-1,-1], [0 ,-1], [ 1,-1], [-1, 0], [ 1, 0], [-1, 1], [ 0, 1], [ 1, 1] ] 色リストは[ [ 0, 0, 0], [255, 0, 0], [ 0,255, 0], [ 0, 0,255], [255,255, 0], [255, 0,255], [ 0,255,255], [255,255,255] ] コントロールパネルリストは[ [[ 0, 0], [ 90, 20], "runInfo", "", 0, null], [[ 0, 20], [ 30, 20], "EndButton", "終", 0, "End"], [[ 30, 20], [ 20, 20], "StopButton", "⏸", 0, "Stop"], [[ 50, 20], [ 20, 20], "StepButton", "⏯", 0, "Step"], [[ 70, 20], [ 20, 20], "StartButton", "⏩", 0, "Start"], [[ 90, 0], [ 60, 20], "zoomInfo", "", 0, null], [[ 90, 20], [ 30, 20], "ZoomInButton", "大", 0, "ZoomIn"], [[120, 20], [ 30, 20], "ZoomOutButton", "小", 0, "ZoomOut"], [[150, 0], [120, 20], "PositionInfo", "", 0, null], [[150, 20], [ 20, 20], "LeftButton", "➡", 180, "PosLeft"], [[170, 20], [ 20, 20], "UpButton", "➡", 270, "PosUp"], [[190, 20], [ 20, 20], "DownButton", "➡", 90, "PosDown"], [[210, 20], [ 20, 20], "RightButton", "➡", 0, "PosRight"], [[230, 20], [ 40, 20], "HomeButton", "原点", 0, "PosHome"], [[270, 0], [ 60, 20], "SpeedInfo", "", 0, null], [[270, 20], [ 30, 20], "SpeedDownButton", "遅", 0, "SpeedDown"], [[300, 20], [ 30, 20], "SpeedUpButton", "速", 0, "SpeedUp"], [[330, 0], [160, 20], "TurnInfo", "", 0, null], [[330, 20], [ 80, 20], "ClearButton", "クリア", 0, "Clear"], [[410, 20], [ 80, 20], "SetRandomButton", "ランダム", 0, "SetRandom"] ] 最大表示倍率は8 最小表示倍率は1 # 現在の世界のセルの状態 # 表/裏と、X+Y*幅数の二次元配列 # 0=死/1>=生 セル配列は[] 表セル配列は0 表示起点は[0,0] 表示倍率は1 ターン数は1 実行状態は「停止」 表示速度は0.05 セル横数は((描画中キャンバス["width"]-画像位置[0])÷表示倍率)の整数部分 セル縦数は((描画中キャンバス["height"]-画像位置[1])÷表示倍率)の整数部分 画像データ幅はセル横数×表示倍率 画像データ高はセル縦数×表示倍率 REQIDは0 前回タイムスタンプは0 経過時間は0 ステータス更新はオフ コントロールパネルは{} # ワークエリア。高速化のため最初に確保して使いまわす イメージは空 ワーク配列は[] 開始する。 ●(セル配列のXYに)誕生とは 周囲リストを配列シャッフル 周囲リストを反復する Iは((XY[1]+対象[1]+セル縦数)%セル縦数)*セル横数+(XY[0]+対象[0]+セル横数)%セル横数 もし、セル配列[I]>0ならば、 セル配列[I]で戻る ここまで ここまで 1で戻る ここまで # 指定されたセル配列を元に次の世代を生成して次セル配列に設定する # 処理の際にワーク配列を作業エリアとして使用する ●(セル配列から次セル配列へ)次世代生成とは # ワーク配列に前後1セル(計3セル)の生の合計数を求めて設定する (セル縦数)回繰り返す Yは回数-1 # 行の先頭と末尾のカウンタはこの時点で0に初期化 ワーク配列[Y*セル横数]は0 ワーク配列[Y*セル横数+セル横数-1]は0 (セル横数)回繰り返す Xは回数-1 Iは(Y*セル横数+X) データはセル配列[I] もし、データ>0ならば J1はY*セル横数+(X-1+セル横数)%セル横数 J2はY*セル横数+X J3はY*セル横数+(X+1)%セル横数 ワーク配列[J1]はワーク配列[J1]+1 ワーク配列[J2]はワーク配列[J2]+1 # 右のセルが末尾と行頭の時は1を加算、違えば1に初期化 もし、X<セル横数-2ならば、 ワーク配列[J3]は1 違えば ワーク配列[J3]はワーク配列[J3]+1 ここまで 違えば、 # 右のセルが末尾と行頭ではない時は0に初期化 もし、X<セル横数-2ならば、 J3はY*セル横数+(X+1)%セル横数 ワーク配列[J3]は0 ここまで ここまで ここまで ここまで # ワーク配列の前後1セル(計3セル)の合計と現世代のセルから次世代のセルに更新する (セル縦数)回繰り返す Yは回数-1 (セル横数)回繰り返す Xは回数-1 Iは(Y*セル横数+X) データはセル配列[I] J1は((Y-1+セル縦数)%セル縦数)*セル横数+X J2はY*セル横数+X J3は((Y+1)%セル縦数)*セル横数+X 計はワーク配列[J1]+ワーク配列[J2]+ワーク配列[J3] # 自身のセルが計に含まれるので継続の条件が2と3から3と4になる # 誕生:データ=0&&計=3 # 継続して生存:データ>0&&計=3||計=4 もし、データ>0&&(計=3||計=4)ならば、 次セル配列[I]はデータ 違えばもし、計=3ならば、 次セル配列[I]はセル配列の[X,Y]に誕生する 違えば、 次セル配列[I]は0 ここまで ここまで ここまで ここまで # 操作パネルの指定した名称のところに文字を表示する ●(NAMEにLABELを)コントロールラベル描画とは CTLはコントロールパネル[NAME] もし、CTLでなければ、戻る XYはCTL["位置"] WHはCTL["サイズ"] RはCTL["回転"] [(XY[0]),(XY[1]),(WH[0]),(WH[1])]に描画クリア キャンバス状態保存 白色に塗り色設定 [(XY[0]+WH[0]/2), (XY[1]+WH[1]/2)]に描画起点設定 もし、R≠0ならば、 Rに描画回転 ここまで [0,0]にLABELを文字描画 キャンバス状態復元 ここまで # 情報表示・操作パネルを配列を元に表示 # 表示の際、辞書型の変数に格納しなおす ●コントロールパネル描画とは [0,0,280,40]に描画クリア キャンバス状態保存 コントロールパネルリストを反復する パネルは対象 XYはパネル[0] WHはパネル[1] NAMEはパネル[2] LABELはパネル[3] Rはパネル[4] EVTはパネル[5] もし、LABELが空でなければ、 キャンバス状態保存 もし、EVTならば、 緑色に線色設定 白色に塗り色設定 [(XY[0])+0.5, (XY[1])+0.5, (WH[0])-1, (WH[1])-1]へ四角描画 黒色に塗色設定 違えば、 空に線色設定 白色に塗り色設定 ここまで [(XY[0]+WH[0]/2), (XY[1]+WH[1]/2)]に描画起点設定 もし、R≠0ならば、 Rに描画回転 ここまで [0,0]にLABELを文字描画 キャンバス状態復元 ここまで コントロールは{ ID:NAME, ラベル:LABEL, 位置:XY, サイズ:WH, 回転:R, イベントID:EVT } コントロールパネル[NAME]はコントロール ここまで キャンバス状態復元 ここまで # 現在のセル世代の状態を表示する ●現世代描画とは セル配列[表セル配列]を表示起点から表示倍率でイメージに画像化する イメージを画像位置にイメージデータ設定 ここまで # セル配列を1世代進めて表示する ●世代更新とは # セル配列の表から裏に次世代を生成する 裏セル配列は1-表セル配列 セル配列[表セル配列]からセル配列[裏セル配列]へ次世代生成する # セル配列の表裏を入れ替える 表セル配列は裏セル配列 ターン数はターン数+1 現世代描画する ここまで # アニメーションフレームのメイン処理 ●(タイムスタンプで)アニメーションとは もし、実行状態が「停止」でなければ もし、表示速度が0ならば、 世代更新 もし、実行状態が「ステップ」ならば、 実行状態は「停止」 ステータス更新はオン ここまで 経過時間は0 違えばもし、前回タイムスタンプが0でなければ、 経過時間は経過時間+タイムスタンプ-前回タイムスタンプ もし、経過時間が(表示速度×1000)以上ならば、 世代更新 もし、実行状態が「ステップ」ならば、 実行状態は「停止」 ステータス更新はオン ここまで 経過時間は経過時間-(表示速度×1000) ここまで ここまで ここまで 前回タイムスタンプはタイムスタンプ もし、ステータス更新ならば、 ステータス表示 ステータス更新はオフ ここまで (""+ターン数+"世代")を"TurnInfo"にコントロールラベル描画 REQIDは「アニメーション」を画面更新時実行 ここまで ●ステータス表示とは 実行状態を"runInfo"にコントロールラベル描画 ("×"+表示倍率)を"zoomInfo"にコントロールラベル描画 ("("+表示起点[0]+","+表示起点[1]+")")を"PositionInfo"にコントロールラベル描画 (""+表示速度+"秒")を"SpeedInfo"にコントロールラベル描画 ここまで # セル横数×セル縦数のサイズを全て0(死)に初期化したセル配列を返す ●空作成とは 新セル配列は[] 新セル配列["length"]はセル横数×セル縦数 (セル縦数)回繰り返す Yは回数-1 (セル横数)回繰り返す Xは回数-1 Iは(Y*セル横数+X) 新セル配列[I]は0 ここまで ここまで 新セル配列で戻る ここまで # セル横数×セル縦数のサイズをランダムに初期化したセル配列を返す ●ランダム作成とは 新セル配列は[] 新セル配列["length"]はセル横数×セル縦数 (セル縦数)回繰り返す Yは回数-1 (セル横数)回繰り返す Xは回数-1 Iは(Y*セル横数+X) もし、(2の乱数)<1ならば、 もし、X<セル横数÷3ならば、 データは1 違えばもし、X<セル横数÷3×2ならば、 データは2 違えば、 データは3 ここまで もし、Y≧セル縦数÷2ならば、 データはデータ+3 ここまで 新セル配列[I]はデータ 違えば 新セル配列[I]は0 ここまで ここまで ここまで 新セル配列で戻る ここまで # 指定されたセル配列の内容を表示用にイメージデータに設定する ●(セル配列をイメージデータに表示起点から表示倍率で)画像化とは Yは(表示起点[1]+セル縦数)%セル縦数 YIは表示倍率 (画像データ高)回繰り返す GYは回数-1 Xは(表示起点[0]+セル横数)%セル横数 XIは表示倍率 (画像データ幅)回繰り返す GXは回数-1 IはY*セル横数+X データはセル配列[I] Jは(GY*画像データ幅+GX)*4 もし、データ>0ならば、 もし、データ≧(色リストの配列要素数)ならば、 データは(色リストの配列要素数)-1 ここまで イメージデータ["data"][J ]は色リスト[データ][0] イメージデータ["data"][J+1]は色リスト[データ][1] イメージデータ["data"][J+2]は色リスト[データ][2] イメージデータ["data"][J+3]は255 違えば、 イメージデータ["data"][J ]は色リスト[0][0] イメージデータ["data"][J+1]は色リスト[0][1] イメージデータ["data"][J+2]は色リスト[0][2] イメージデータ["data"][J+3]は0 ここまで XIはXI-1 もし、XI≦0ならば、 XIは表示倍率 Xは(X+1)%セル横数 ここまで ここまで YIはYI-1 もし、YI≦0ならば、 YIは表示倍率 Yは(Y+1)%セル縦数 ここまで ここまで イメージデータで戻る ここまで ●開始とは # 「死」のセルは透明なので背景を黒にする 描画中キャンバスの"背景色"に黒色をDOMスタイル設定 セル配列[表セル配列]はランダム作成 裏セル配列は1-表セル配列 セル配列[裏セル配列]は[] セル配列[裏セル配列]["length"]はセル配列[表セル配列]の配列要素数 # 作業エリアとなる変数準備 ワーク配列は[] ワーク配列["length"]はセル配列[表セル配列]の配列要素数 イメージは[画像データ幅, 画像データ高]のイメージデータ作成 # 初期設定 「16px bold sans-serif」に描画フォント設定 1に線太さ設定 描画中コンテキスト["textAlign"]は"center" 描画中コンテキスト["textBaseline"]は"middle" # 初期状態表示 現世代描画する コントロールパネル描画 ステータス更新はオン 描画中キャンバスの"click"に"クリック受付"をDOMイベント追加 # アニメーションフレーム予約 REQIDは「アニメーション」を画面更新時実行 ここまで ●後始末とは REQIDを画面更新処理取消 描画中キャンバスの"click"から"クリック受付"をDOMイベント削除 ここまで ●クリック受付とは EVTはWINDOW["event"] 要素位置はEVT["target"]の"getBoundingClientRect"を[]でJSメソッド実行 XはEVT["clientX"]-要素位置["left"] YはEVT["clientY"]-要素位置["top"] コントロールパネルを反復 CTLは対象 XYはCTL["位置"] WHはCTL["サイズ"] EVTはCTL["イベントID"] もし、EVTならば、 もし、(X≧XY[0])&&(X≦XY[0]+WH[0])ならば、 もし、(Y≧XY[1])&&(Y≦XY[1]+WH[1])ならば、 EVTでイベント処理 ここまで ここまで ここまで ここまで ここまで ●(EVTIDで)イベント処理とは EVTIDで条件分岐 "End"ならば、 もし、実行状態が「停止」ならば 後始末 実行状態は「終了」 ステータス表示 ここまで ここまで "Stop"ならば、 実行状態は「停止」 ステータス更新はオン ここまで "Step"ならば、 実行状態は「ステップ」 ステータス更新はオン ここまで "Start"ならば、 実行状態は「実行中」 ステータス更新はオン ここまで "PosLeft"ならば、 表示起点[0]は表示起点[0]-(画像データ幅÷表示倍率÷2)の整数部分 表示起点[0]は(表示起点[0]+セル横数)%セル横数 もし、実行状態が「停止」ならば、現世代描画する。 ステータス更新はオン ここまで "PosRight"ならば、 表示起点[0]は表示起点[0]+(画像データ幅÷表示倍率÷2)の整数部分 表示起点[0]は表示起点[0]%セル横数 もし、実行状態が「停止」ならば、現世代描画する。 ステータス更新はオン ここまで "PosUp"ならば、 表示起点[1]は表示起点[1]-(画像データ高÷表示倍率÷2)の整数部分 表示起点[1]は(表示起点[1]+セル縦数)%セル縦数 もし、実行状態が「停止」ならば、現世代描画する。 ステータス更新はオン ここまで "PosDown"ならば、 表示起点[1]は表示起点[1]+(画像データ高÷表示倍率÷2)の整数部分 表示起点[1]は表示起点[1]%セル縦数 もし、実行状態が「停止」ならば、現世代描画する。 ステータス更新はオン ここまで "PosHome"ならば、 表示起点[0]は(セル横数÷2-画像データ幅÷表示倍率÷2)の整数部分 表示起点[1]は(セル縦数÷2-画像データ高÷表示倍率÷2)の整数部分 もし、実行状態が「停止」ならば、現世代描画する。 ステータス更新はオン ここまで "ZoomIn"ならば、 もし、表示倍率<最大表示倍率ならば、 表示起点[0]は表示起点[0]+(画像データ幅÷表示倍率÷2)の整数部分 表示起点[1]は表示起点[1]+(画像データ高÷表示倍率÷2)の整数部分 表示倍率は表示倍率×2 表示起点[0]は表示起点[0]-(画像データ幅÷表示倍率÷2+0.5)の整数部分 表示起点[1]は表示起点[1]-(画像データ高÷表示倍率÷2+0.5)の整数部分 表示起点[0]は(表示起点[0]+セル横数)%セル横数 表示起点[1]は(表示起点[1]+セル縦数)%セル縦数 もし、実行状態が「停止」ならば、現世代描画する。 ステータス更新はオン ここまで ここまで "ZoomOut"ならば、 もし、表示倍率>最小表示倍率ならば、 表示起点[0]は表示起点[0]+(画像データ幅÷表示倍率÷2+0.5)の整数部分 表示起点[1]は表示起点[1]+(画像データ高÷表示倍率÷2+0.5)の整数部分 表示倍率は表示倍率÷2 表示起点[0]は表示起点[0]-(画像データ幅÷表示倍率÷2)の整数部分 表示起点[1]は表示起点[1]-(画像データ高÷表示倍率÷2)の整数部分 表示起点[0]は(表示起点[0]+セル横数)%セル横数 表示起点[1]は(表示起点[1]+セル縦数)%セル縦数 もし、実行状態が「停止」ならば、現世代描画する。 ステータス更新はオン ここまで ここまで "SpeedDown"ならば、 表示速度で条件分岐 0ならば、表示速度は0.02。ここまで。 0.02ならば、表示速度は0.05。ここまで。 0.05ならば、表示速度は0.1。ここまで。 0.1ならば、表示速度は0.2。ここまで。 0.2ならば、表示速度は0.5。ここまで。 0.5ならば、表示速度は1。ここまで。 1ならば、表示速度は3。ここまで。 3ならば、表示速度は5。ここまで。 5ならば、表示速度は10。ここまで。 ここまで ステータス更新はオン ここまで "SpeedUp"ならば、 表示速度で条件分岐 0.02ならば、表示速度は0。ここまで。 0.05ならば、表示速度は0.02。ここまで。 0.1ならば、表示速度は0.05。ここまで。 0.2ならば、表示速度は0.1。ここまで。 0.5ならば、表示速度は0.2。ここまで。 1ならば、表示速度は0.5。ここまで。 3ならば、表示速度は1。ここまで。 5ならば、表示速度は3。ここまで。 10ならば、表示速度は5。ここまで。 ここまで ステータス更新はオン ここまで "Clear"ならば、 もし、実行状態が「停止」ならば セル配列[表セル配列]は空作成 現世代描画する ターン数は1 ステータス更新はオン ここまで ここまで "SetRandom"ならば、 もし、実行状態が「停止」ならば セル配列[表セル配列]はランダム作成 現世代描画する ターン数は1 ステータス更新はオン ここまで ここまで ここまで ここまで # イメージデータ操作関数 # 全ピクセルが0x00000000(黒の完全透明)のイメージデータを新たに作成して返す # PARAMに、[幅,高]の配列を指定すると、指定したサイズのイメージデータを作成する # PARAMに、[イメージデータ]を指定すると、指定したイメージデータと同じサイズのイメージデータを作成する ●(PARAMの)イメージデータ作成とは 描画中コンテキストの"createImageData"をPARAMでJSメソッド実行で戻る ここまで # 現在のキャンバスにイメージデータを指定した座標にputImageDataにて描画する # DrawImageとイメージデータの画像で「置き換える」。描くより高速。 ●(イメージをXYに)イメージデータ設定とは 描画中コンテキストの"putImageData"を[イメージ,(XY[0]),(XY[1])]でJSメソッド実行 ここまで # 現在のキャンバス上の指定した位置・サイズをイメージデータとして取得して返す ●(XYからWHを)イメージデータ取得とは 描画中コンテキストの"gutImageData"を[(XY[0]),(XY[1]),(WH[0]),(WH[1])]でJSメソッド実行 ここまで ここまで