0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】自作マリオ キーイベント処理

Posted at

Pygameでマリオのキーイベントを追加する

マリオをPythonで作成するハンズオン動画を見つけたので、実装してみる。
参考:【#4 キーイベント処理】マリオを左右に動かそう!マリオを一緒に作ってみませんか!pythonで!【ハンズオン実践解説】

1. マリオの動きの実装

(1) キーボード入力に応じた移動の追加

  • update() メソッド内で pygame.key.get_pressed() を使用し、右 ()、左 ()、ジャンプ (スペースキー) に対応。
def update(self):
        # キーボードの状態を取得
        keys = pygame.key.get_pressed()
        if keys[pygame.K_RIGHT]:
            self.__right()
        if keys[pygame.K_LEFT]:
            self.__left()
        if keys[pygame.K_SPACE]:
            self.__jump()

(2) 移動処理の追加

  • __right() → 右移動 (rect.x += 5)
  • __left() → 左移動 (rect.x -= 5)
  • __jump() → ジャンプ (self.__vy = -10 に設定し、地面から離れる`)
    def __right(self):
        self.rect.x += 5
        self.__isleft = False
        self.__walkidx += 1

    def __left(self):
        self.rect.x -= 5
        self.__isleft = True
        self.__walkidx += 1
    
    def __jump(self):
        if self.__on_ground:
            self.__vy = -10
            self.__on_ground = False

(3) Y軸の移動処理

  • __vy を用いた重力処理を追加。
    • if not self.__on_ground: で空中にいる場合 self.rect.y__vy の値だけ変化させる。
    • __vy の値を +1 ずつ増やし、落下する動作を実現。
    • 地面 (y = 180) に着いたら __on_ground = True にしてジャンプ可能にする。
    # Y軸方向に移動
        if not self.__on_ground:
            self.rect.y += self.__vy
            self.__vy += 1

            if self.rect.y >= 180:
                self.rect.y = 180
                self.__on_ground = True

2. 歩行アニメーションの追加

(1) 画像のフレーム切り替え

  • 前回: mario001.png という1枚の画像のみを表示。
  • 今回: mario001.png mario002.png の2枚の画像を配列 self.__imgs に格納し、歩行時に交互に切り替え。
    • WALK_ANIME_IDX = [0, 0, 0, 1, 1, 1] を用いて、6フレームのうち 0 (mario001) と 1 (mario002) を交互に表示。
        # marioの画像を読み込む
        self.__imgs = [
            pygame.image.load('mario001.png'),
            pygame.image.load('mario002.png')
        ]
        self.image = self.__imgs[0]
        self.rect = pygame.Rect(150, 180, 20, 20)

mario001.png mario002.png

(2) 左右の向きの判定

  • self.__isleft で左右の向きを記録し、画像の反転を実現。
    • pygame.transform.flip(self.__imgs[self.WALK_ANIME_IDX[self.__walkidx % 6]], self.__isleft, False)
        # 左右どちら向きかのフラグを定義
        self.__isleft = False
    
        ~~~

        self.image = pygame.transform.flip(self.__imgs[self.WALK_ANIME_IDX[self.__walkidx % 6]], self.__isleft, False)

完全なコード

import pygame

# 画面サイズを定義
W, H = 320, 270

# タイル数
TILE_X = 16
TILE_Y = 14

class Mario(pygame.sprite.Sprite):
    ''' マリオのクラス
    '''
    WALK_ANIME_IDX = [0, 0, 0, 1, 1, 1]
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

        # 左右どちら向きかのフラグを定義
        self.__isleft = False
        # 歩くインデックス
        self.__walkidx = 0
        # Y軸方向移動郷里
        self.__vy = 0
        # マリオが地面にいるか
        self.__on_ground = True

        # marioの画像を読み込む
        self.__imgs = [
            pygame.image.load('mario001.png'),
            pygame.image.load('mario002.png')
        ]
        self.image = self.__imgs[0]
        self.rect = pygame.Rect(150, 180, 20, 20)

    def __right(self):
        self.rect.x += 5
        self.__isleft = False
        self.__walkidx += 1

    def __left(self):
        self.rect.x -= 5
        self.__isleft = True
        self.__walkidx += 1
    
    def __jump(self):
        if self.__on_ground:
            self.__vy = -10
            self.__on_ground = False


    def update(self):
        # キーボードの状態を取得
        keys = pygame.key.get_pressed()
        if keys[pygame.K_RIGHT]:
            self.__right()
        if keys[pygame.K_LEFT]:
            self.__left()
        if keys[pygame.K_SPACE]:
            self.__jump()

        # Y軸方向に移動
        if not self.__on_ground:
            self.rect.y += self.__vy
            self.__vy += 1

            if self.rect.y >= 180:
                self.rect.y = 180
                self.__on_ground = True

        self.image = pygame.transform.flip(self.__imgs[self.WALK_ANIME_IDX[self.__walkidx % 6]], self.__isleft, False)
def main():
    '''メイン関数'''
    # pygame初期化
    pygame.init()
    # 画面を構築
    win = pygame.display.set_mode((W, H))
    pygame.display.set_caption("Pygame Window")  # ウィンドウタイトルを設定
    # クロックを生成
    clock = pygame.time.Clock()

    # スプライトグループを定義
    group = pygame.sprite.RenderUpdates()
    # マリオクラスを定義
    mario = Mario()
    # マリオをグループに追加
    group.add(mario)


    # 背景色の初期値(黒)
    bg_color = (0, 0, 0)

    # イベントループ
    running = True
    while running:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                running = False  # ループを抜ける

        # 背景を塗りつぶす
        win.fill((135, 206, 235))

        # グループを更新
        group.update()

        # グループを描画
        group.draw(win)

        # 画面の更新
        pygame.display.flip()

        clock.tick(30)  # FPS制限 (60FPS)

    # pygameを終了する
    pygame.quit()

# Pythonのファイルが直接実行された場合のみmain()を実行
if __name__ == '__main__':
    main()

まとめ

変更点 前回 今回
キーボード入力 なし pygame.key.get_pressed() を使用
横移動 なし __right() __left() で移動可能
ジャンプ なし __jump() を追加
重力処理 なし self.__vy を用いた落下処理
画像 mario001.png のみ mario001.png mario002.png を交互に表示
向き判定 なし pygame.transform.flip() で左右反転

この修正により、マリオが移動・ジャンプし、歩行アニメーションがつくようになりました。

mario.gif

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?