仮眠プログラマーのつぶやき

自分がプログラムやっていて、思いついたことをつぶやいていきます。 2025年からzennに移行

自作ゲームやツール、ソースなどを公開しております。
①ポンコツ自動車シュライシュラー
DOWNLOAD
②流体力学ソース付き
汚いほうDOWNLOAD
綺麗なほうDOWNLOAD
③ミニスタヲズ
DOWNLOAD
④地下鉄でGO
DOWNLOAD
⑤ババドン
DOWNLOAD
⑥圧縮拳(ツール)
DOWNLOAD
⑦複写拳
DOWNLOAD
⑧布シミュレーション
DOWNLOAD
⑨minecraft巨大電卓地形データ
DOWNLOAD
⑩フリュードランダー
デジゲー博頒布α版
DOWNLOAD
⑪パズドラルート解析GPGPU版
DOWNLOAD
⑫ゲーム「流体de月面着陸」
DOWNLOAD

技術解説「地下鉄でGO!」

技術解説「地下鉄でGO!」その8 0cm停車を器用にこなすAI③

前回の説明はもう絶対読んだ人を眠くさせる自信があります!


他の人ならもうちょっとわかりやすく説明できたと思います。すいません・・


が、まぁ話を戻して



例のAIを起動させるAIはどうなってるのかというと↓これです



if tstu="停車駅":if (xej*xej+aa1*3)*496>y:za=1



まず、次が停車駅だというのは当たり前の条件ですよね。zaは通常0が代入されていて、1が代入されると停車AIが起動するって意味付けされています。



(xej*xej+aa1*3)*496>y

では、速度を2乗+補正して距離と比べてブレーキかけはじめのタイミングをうかがっています。

xejはただの速度の変数です。

aa1には「実際」の加速度が代入されています。

実際とは、P5からB8に急にマスコンを操作したときに実際の電車のようにブレーキが遅れて効いてくる、いわゆる急に加速度が変わらないように補正をかけたってことです。



そこらへんのリアリティは追求してみたかったんで・・



基本は速度の2乗に影響されてきます。ブレーキAIのところとかなり似ていると思いませんか?

大体、B5くらいのブレーキでうまく停車できる程度の距離になったら、ブレーキAI開始ってなっています。



当然、定数の*496を増減変化させればB4でもB6でも好きなようにできます。




というわけでブレーキの遅れも考慮に入れたAIブレーキ始動AIでした。




ところで書いてて途中で気づいたのですが、ブレーキに非常ブレーキが無いことに気づきました!



これはヤバイ!



完全にど忘れしていました!



そこらへんのリアリティは追及しようと思わなかったのか・・自分!?



よく考えたら、対抗電車とかも駅名も終点も、もう何も無いですね!


未だ発展途上過ぎるゲームですね・・・





さて今度は、速度制限とかカーブつきとか本格的に電車でGOに近づけたゲームを作ろうかな!?

技術解説「地下鉄でGO!」その7 0cm停車を器用にこなすAI②

前回の緑色の部分だけピックアップしてきました。

if xxx/12>y:aa=-1
if xxx/19>y:aa=-2
if xxx/30>y:aa=-3
if xxx/40>y:aa=-4
if xxx/49>y:aa=-5
if xxx/57>y:aa=-6
if xxx/63>y:aa=-7
if xxx/72>y:aa=-8
この1行目から解説します。

if xxx/12>y:aa=-1


だと速度の2乗を12で割ったときの数が残り距離より大きければブレーキをB1にするというプログラムです。


つまり今の速度と距離では、B1のブレーキでは少なくとも0cmをオーバーしてしまいますよ、という意味です。

(でも12という数字は自分で適当だと思って決めた数字なので多少なりとも誤差はあります。)


なのでB1より強いブレーキにしなければなりません。そのための次の行です。


if xxx/19>y:aa=-2


今度は19で割っているので12で割ったときより小さい値になっています。

それでもまだxxx/19のほうが大きいなら、B2でうまく停車できる場合よりもっと速度が速いことになるのでさらに強いブレーキをかけなければいけません。


もしxxx/19のほうが小さいならaa=-2は読まれないのでaa=-1のままとなってしまうのでしばらくB1のブレーキが続くわけですが、

ブレーキで減速中にも常にこのプログラムは読まれ続けているのでいつかB2でも間に合わなくなるまで距離が詰まる瞬間がきます。


そこで2行目のさっきの

xxx/19>y

が満たされはじめてブレーキがB2となります。


こうして徐々に距離が縮まっていくのですが、このままではブレーキがどんどん強くなって限界のB8まで

いってしまいそうです・・・が、そうならないために少しB5あたりで補正を入れてあります。


B6より強いブレーキをなるべく使わせないためです。


まず、B5で停車する位置を計算上で少し狂わせます。


if xxx/49>y:aa=-5

とありますがB5のときに必ずしも

xxx/49

の位置で停車するわけではありません。少し補正を入れて停車までの距離を長く見積もらせています。


するとどうなるのかというと本来B5では手前に停車するはずの距離でもB5のブレーキがかかるということです!



そうすればB6のブレーキがかかることは滅多にないはずです!


B5でずっとブレーキをかけ続けていると手前で停車しそうになるので、だんだんB4でも良くなりブレーキがB4になります。あとはB4とB5の間を行ったりきたりして、うまく0cmに停まります。



一応、勾配とか、加速度の急激な変化を軽減する補正など、様々な要因がはらんでいてブレーキが思うように効かないこともあるのでB6以上でも使われないわけではありません。

なので、B6以上のブレーキアルゴリズムでは、B5のときよりもっと補正をかけて、0m地点よりもっと奥に停車するように見積もらせておきます。



そうすればブレーキが強く効いてB5でも停車できる速度に落ち着くようになります。


当然、補正次第でB6に落ち着かせることやB3に落ち着かせることも可能です。




あとの問題は、ブレーキの効き始めのタイミングをどう決定するかです。

どう言う事かと言うと、残り距離がまだ800mもあるのにB1で停車位置がオーバーするといってブレーキをかけ始めてしまったのでは、惰性走行も加速も思うようにできません。



効率よく電車を停車させるには、駅に残り何m以内に近づいたらAIが機能し始めるというようにしなければいけない・・・と思いつくのですが、速度によってその何mというのが大きく変わることが予想されるので、停車AIを起動し始める残り距離を計算するAIも搭載しておかなきゃいかんのだ、ということになるんですね。



ややこしいかもしれませんが、そうなんです。


国語6点の私の文章は読みにくいかもしれませんが、なんとか悟ってください。



次回はそこのプログラムの解説。


次回:技術解説「地下鉄でGO!」その8 0cm停車を器用にこなすAI③

技術解説「地下鉄でGO!」その6 0cm停車を器用にこなすAI①

自慢になりますが「地下鉄でGO!」の機能として画期的なのはAIがついていること!


今日から3回くらいに分けて自慢の停車AIについて語っていきたいと思います!


0cm停車を自動でする(たまに外す)プログラムは以下の通りです



xxx=x-kohi/50:xxx=xxx/2110*xxx
paa=aa
if xxx/12>y:aa=-1
if xxx/19>y:aa=-2
if xxx/30>y:aa=-3
if xxx/40>y:aa=-4
if xxx/49>y:aa=-5
if xxx/57>y:aa=-6
if xxx/63>y:aa=-7
if xxx/72>y:aa=-8
if paa<aa:aa=paa+1
if paa>aa:aa=paa-1


ここで重要なのは緑色の部分。


緑色の部分では

変数yは残りの距離、xは速度が代入されている変数で

xxxは多少の補正がかかっているもののxの2乗に比例する変数です。


aaはマスコンのブレーキ「B?」の?が代入されている変数です。

マイナスがついているのは加速減速を区別するための意味づけにすぎません。

気にしなくていいです。



(今更ですがこの電車はワンハンドル操作です、加速減速P5~B8までひとつの変数で管理してます)



さて、基礎知識としてここで速度と距離の関係の話をしましょう。


ある速度で移動している物体が一定の減速度で減速して止まったとき、それまでに進んだ距離は最初減速し始めるときの速度の2乗に比例する、っていう法則みたいなのがあります。

たとえば時速60キロで走っている電車がブレーキをかけたら200m先で停車したとしましょう。

同じ強さのブレーキでは時速30で減速した場合50m先で停車することが計算から分かります。



つまり話を戻すと、電車が走っているときのブレーキの強さを決定するAIはどうなっているのかというと、

ブレーキの強さが8パターンあるので、8回、各々の強さのブレーキで減速した場合どこに停車するかを

計算で出し、一番0m(停車位置)に近いときのブレーキの強さを加速度の変数aaに代入する

というふうになっているのです。


計算で出すというのはつまりさっきの2乗の法則で計算すれば出るということです。


8回各々の強さで計算というのは、ちょうど緑のところですね。


このアルゴリズムでは、停車位置が0mをオーバーするものの中で一番近い停車位置の場合のブレーキを計算しています。


さて次は緑の行を1行1行解説していきます。


次回:技術解説「地下鉄でGO!」その7 0cm停車を器用にこなすAI②

技術解説「地下鉄でGO!」その5 擬似3Dをプログラムする

まで分かりやすくあえて遠近法といってましたが、正確には遠近法はただ遠くにあるものが小さく見えるだけ、

って定義らしいので、厳密な式にするのはできないそうです。


上の文は嘘です。


さて遠近法の式をつくりましょうか。


まず、近いほど大きく、遠いほど小さく見えるといいますが、どのくらいがわからなければいけません。


図に描いて見れば分かりますが、これは奥行き(z座標)の距離に反比例して大きく見えます。


だから、画面の中心を320,240とすれば

例えば40,50,90という空間の点は、2D画面では

320+k*40/90 240+k*50/90 っていう点で表されます。(kは係数)


ここでkは大体500とか、そのくらいの数になるはずです。


では地下鉄でGOの柱のプログラムを公開しましょう。多分理解できるはずです。

(ちなみに左右にあるあの茶色っぽい細長いのが柱です・・・一応・・・)


color 3573450/q7.cnt+19,3573450/q7.cnt+19,3573450/q7.cnt+19
boxf 192+(8000000/q7.cnt),170-(5100000/q7.cnt),191+(7300000/q7.cnt),170+(5100000/q7.cnt)
boxf 188-(8000000/q7.cnt),170-(5100000/q7.cnt),188-(7300000/q7.cnt),170+(5100000/q7.cnt)

ほい。

カラー指定は、奥なほど濃くってことでしょう。

q7.cntは自分とその柱までの距離が代入された変数です。

cntはループのなかでしか意味をなさない、今何週ループ目?が代入されているシステム変数です。


柱はいくつもあるので、この3行の命令は20回ループで読ませています。


画面の中心はなぜか190,170みたいですね。

そして (8000000/q7.cnt) ここの部分


割り算を使っているの分かりますか?

q7.cntは奥行きの距離でしたよね?

また、8000000や5100000とかものすごい数になっているのは、kに1000倍されたx座標を掛けたからです。


精度のところで説明したように、全部の距離が1000倍にされて計算されています。

小数も扱える変数だったらこんな事しないんですけどね



今日の名言はー


「びゃあ゛ぁ゛゛ぁうまひぃ゛ぃぃ゛ぃ゛(訳:ああ、うまい)」 by M・H

技術解説「地下鉄でGO!」その4 擬似3Dとは

忘れっぽいのは素敵なことです~そうじゃありませんか~

空しいテストの数ばかり飽和の量より増えたなら忘れるよりほかないじゃありませんか~ (傾斜 中島みゆき)



何回目でしょーかテストの点を忘れた回数・・・



いえいえ、こっちの話です。


今回は擬似3D描写のお話。


一応、プログラムを知らない人も読んでくださってるかもしれないので2D描写のことから話し始めたいと思います。


まずスクリーンに画像を貼り付ける場合、必ずスクリーン上のポジションを数値で指定して、貼り付けます。


pos という命令ですが、例えばpos 100,200と指定した場合、このあと来る画像貼り付け命令で貼り付ける画像が、スクリーンの左から数えて100ピクセル、上から数えて200ピクセルの位置に表示されます。


一応2Dはこうやって表示位置の設定をしているのですが、3Dの場合ではpos 100,200,300とz座標が加わったり根本的にまったく違う方法で座標指定している・・・・・・・なんてことはないんです。


画面に奥行きはないし画面自体はxとy座標しか存在しません。


機械(パソコンの画面)にとってはx、y座標が知りたいわけで、z座標なんか言われてもチンプンカンプンなのです。

だからわざわざ私たちが遠近法の計算式で、3次元を2次元で見た場合x、y座標がどうなるか計算してz座標を消してあげないといけないわけですね。


つまり結局は3Dも、2Dと(概念としては)同じプロセスで画像を貼り付けているのです。



プログラム経験者の方はアレと思ったかもしれません。

確かに、3Dプログラミングの場合普通x座標y座標z座標の3つの座標を指定しないと表示できませんし、というか指定してくださいってマニュアルに書いてあるし。


でもそれはプラグインのほうであなたが指定したxyz座標をxy座標に勝手に変換して、最終的に画面に表示しているのです。


プラグインを作った人が、スクリプターに開発しやすいようにと、わざわざちゃんとxyzの3つを指定できるような命令を作っておいてくれていた、という訳ですね。


(例外として光源を計算する方法もありますがこれは処理時間が膨大に膨れ上がるためCGやムービーにしか使われないそうです。)

で、ここからが本題。


今(次)から解説する擬似3Dとは、そこまで高度な3Dを求めていないプログラマーが、そのためにプラグインを使うのが面倒だといって、自分で遠近法の式を作って3Dを再現しちゃうことをいいます。


シューティングの背景とか、ゲーム自体は2Dだけど雲と地面みたいに背景が2重スクロールになってあたかも奥行きがあるように見せるような場合に頻繁に使われます。


でそのためには第一に、遠近法の式を自分で考えて作らないといけませんが、まそれは次回。


次回:技術解説「地下鉄でGO!」その5 擬似3Dをプログラムする





ところで、とあるブログで名言集みたいなことやり始めたみたいです。毎回誰かの名言を最後に載せるのですが、なんか面白いなーと、言うか急にうらやましくなったんでこっちも真似してやってみようかと思います!

さて、最初の名言はー・・


「そのうち、一家に一台の時代が来るかもしれん!」by N・I

プロフィール

toropippi

記事検索
アクセスカウンター

    QRコード
    QRコード
    • ライブドアブログ