pythonで作る戦車ゲーム 戦車の挙動について

pythonを勉強していて、戦車の挙動をとてもうまく作ることができたので紹介します。挙動といっても戦車の移動をどうやってコードに書き起こすかという感じです。僕はpythonを利用しましたが、他の言語でも応用はとても簡単だと思います。
#環境
・Python3.9.0
・pygame(ライブラリ)を使っています。


#使う知識
・ちょっぴりのプログラミング知識
・高校物理(力学)

高校物理と言ってもとても簡単なものなのでご安心ください。
***
今回は戦車の動きを作るのにあたって、二つのステップを作りました。それは**速度**と**方向**です。それとこのゲームはwキーで上、aキーで左、dキーで右、sキーで下に動くようにしています。

#速度(位置)編
速度とは何か、と聞かれたらおそらくほとんどの人が「単位時間あたりに進む距離」と考えると思います。そうです。これをコードに起こしてしまうのです。物理で習う式は
```
x=a*t^2+b*t+x_0
```
という感じですよね。tは時間、x_0は最初の位置、そしてa,bは定数です。
これをプログラミングで表すにはどうすればよいのか。大前提として、このプログラムではwhileループごとに戦車の位置差を計算してます。それを速度と呼ぶこととします。話を戻して、プログラミングでこの式を表すには、tを方向キーを押している時間と捉えることで上手く解決します。この式を利用するとゆっくりと発進する動作は書けるようになります。でもここまで来たらゆっくり慣性があるように止まってほしいので、この式をさらに少しいじります。
```
x=a*t^2+b*t+x_0-c*t_stop^2
```
後ろに新しい項を追加しました。t_stopとは、キーが押されていないかつ、速度が0でないときにカウントしていく変数です。これを追加することで現実のようにゆっくり滑らかに進み始めてゆっくり滑らかに止まるようになります。

```python
            pressed_key=pygame.key.get_pressed()
            if speed == 0:
                if pressed_key[K_a]:
                    power_left = 1
                if pressed_key[K_d]:
                    power_right = 1
                if pressed_key[K_w]:
                    power_up = 1
                if pressed_key[K_s]:
                    power_down = 1

            if(pressed_key[K_a] or pressed_key[K_s] or pressed_key[K_d] or pressed_key[K_w]):       # キーを押したとき
                t += 0.1  # 時間の計測を始める
                t_stop = 0

            else:  # 戦車が動いていてかつ速度があるときに慣性を使うためにt_stopの計測を始める。
                if speed > 0:
                    t_stop += 0.01
                else:  # 速度が０でキーも押されてないときに初期化
                    t = 0
                    speed = 0
            speed = 20*t*t+1*t-18*t_stop*t_stop  # 移動速度の計算
            if(speed > 7):  # 最高速度の設定
                speed = 7
```

#方向編
速度編でスピードは計算できたので次にそのスピードをどの方向に割り振るかを考えていきます。この処理を考えることで曲がるときの慣性を表現しました。でもこの式は物理法則に則ったわけでは無いのでもっといい方法があるとは思います。しかし、かなり高精度にカーブの慣性を表せていると思うので参考にしてみてください。まず、

```py
    power_left = 1  
    power_right = 1
    power_up = 1
    power_down = 1
```
と四つの変数を用意します。そして、

```py
            # 速度がどの横行に向いているのかを計算して、なめらかな方向転換を実現
            # 処理開始
            if pressed_key[K_a]:
                power_left += 0.1
                last_key = 2
            elif(power_left > 1):
                power_left -= 0.1
            if pressed_key[K_d]:
                power_right += 0.1
                last_key = 3
            elif(power_right > 1):
                power_right -= 0.1
            if pressed_key[K_w]:
                power_up += 0.1
                last_key = 0
            elif(power_up > 1):
                power_up -= 0.1
            if pressed_key[K_s]:
                power_down += 0.1
                last_key = 1
            elif(power_down > 1):
                power_down -= 0.1
            # 処理終了

```
このようにして方向キーが押されている間、四つの変数の値を増やしていきます。そして最後に、

```py
            x -= speed*hit[0]*power_left / \
                (power_left+power_right+power_up+power_down)  # 実際の位置の計算
            x += speed*hit[1]*power_right / \
                (power_left+power_right+power_up+power_down)
            y -= speed*hit[2]*power_up/ \
(power_left+power_right+power_up+power_down)
            y += speed*hit[3]*power_down / \
                (power_left+power_right+power_up+power_down)
            # 戦車の移動処理の終了

```
x,yというのは戦車(プレイヤー)の座標です。また、ここのhitという配列は当たり判定の返り値で、障害物に当たっているとこの値が0になり移動できなくなります。こうすることで滑らかなカーブを実現することができました。まっすぐ進んでいて急に曲がろうとしても曲がれないあの慣性をコードに書き起こすことができました。

#まとめ
かなりこだわって作ったので、ぜひ参考になればうれしいです。