人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

ジャンプ

上キーでジャンプできるようにしてきます。ジャンプをかっこよく見せるには重力を実装する必要があります。

jump.zip
f:id:aidiary:20100812205740p:plain

ジャンプ処理

Pythonのupdate()をみてください。

    JUMP_SPEED = 8.0  # ジャンプの初速度
    GRAVITY = 0.2     # 重力加速度

    def __init__(self):
        ...
        # 地面にいるか?
        self.on_floor = False

    def update(self):
        """スプライトの更新"""
        # キー入力取得
        pressed_keys = pygame.key.get_pressed()
        
        # ジャンプ
        if pressed_keys[K_UP]:
            if self.on_floor:
                self.fpvy = - self.JUMP_SPEED  # 上向きに初速度を与える
                self.on_floor = False

ジャンプの基本は上向きに速度を加えることです。上キーを押すと、fpvyを-JUMP_SPEED というようにマイナスの値にセットしています。画面の座標系では、上方向=Y座標のマイナス方向になります。fpvyをマイナスの値にセットすることで上向きの速度が加わり上へ移動します。基本的にジャンプは地面の上にいないとできません。そこで、ジャンプする前に地面にいるかどうか調べています。 on_floorがTrueのとき地面(画面の一番下)にいます。on_floor=Trueのときだけ上向き速度を加えてますね。ジャンプすると地面の上にいないのでon_floorをFalseにしておきます。

重力の実装

fpvyをマイナスの値をセットしましたが、vyをマイナスにしたままではずっと上の方に移動し続けてしまいます。ご自分でジャンプしてみるとわかりますが、ジャンプすると最初は上に進みますが、やがて止まり、最後は下へ落ちてきます。

f:id:aidiary:20100812205741p:plain

これは地上に重力があるためです。ジャンプしてもちゃんと下に戻ってくるように重力を実装します。速度は位置を変化させる量であったのに対し、重力は速度を変化させる加速度と呼ばれる量です。速度(fpvx, fpvy)は位置(fpx, fpy)を更新するのに対し、重力(GRAVITY)は速度(fpvy)を更新します。重力は下のように定義してます。

    GRAVITY = 0.2     # 重力加速度

「あれっ、重力って9.8じゃなかったっけ」って思った方もいると思います。確かに現実世界で重力の値は9.8m/s^2です。ただ、今作っているのはゲームであってシミュレーションではないので都合のよい値を使えばいいわけです。重力を大きくするほど下に落ちるスピードが速くなります。逆に小さい価にすると月面にいるようになかなか落ちてこなくなります。あんまり大きくするとジャンプすらできませんが(笑)次にupdate()を見てください。

    def update(self):
        """スプライトの更新"""
               
        # 速度を更新
        if not self.on_floor:
            self.fpvy += self.GRAVITY  # 下向きに重力をかける
        
        # 浮動小数点の位置を更新
        self.fpx += self.fpvx
        self.fpy += self.fpvy
        
        # 着地したか調べる
        if self.fpy > SCR_RECT.height - self.rect.height:
            # 床にめり込まないように位置調整
            self.fpy = SCR_RECT.height - self.rect.height
            self.fpvy = 0
            self.on_floor = True
        
        # 浮動小数点の位置を整数座標に戻す
        # スプライトを動かすにはself.rectの更新が必要!
        self.rect.x = int(self.fpx)
        self.rect.y = int(self.fpy)

ジャンプ中には重力がつねに下向きにかかりfpvy(速度)を変更しています。ジャンプしたときはfpvyの値がマイナスになりどんどん上に進みますが、プラスの値である GRAVITYがどんどん足されていってやがてfpvyが0になり、空中で止まります。さらに足されていくとfpvyの値はプラスになり下へ落ちてきます。これがジャンプの仕組みです。

ジャンプすると下へ落ちてきますが、地面に到達したらfpvy > 0で下向きにかかっていた速度を0に戻す必要があります。そうしないとずーっと下に落ち続けてしまいます。パイソンのY座標が地面の場所に到達したら fpvyを0にして床にめり込まないように位置も調整しています。また床についたのでon_floor=Trueにしています。