1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

watnowAdvent Calendar 2023

Day 6

昔作った横スクロールゲームをオブジェクト指向に

Last updated at Posted at 2023-12-06

はじめに

お世話になっております。
watnow所属の山内と申します。

ますます厳しさを増す寒さの中、お身体の調子はいかがでしょうか。どうかお体を温め、ご自身の健康を最優先にお過ごしください。

さて、現在私は大学で「オブジェクト指向論」を履修しております。この学びを実践する一環として、以前pythonで作成した横スクロールゲームをオブジェクト指向に書き直しました。その過程での変更点や課題について、この記事で共有していきたいと思います。

初めての記事執筆、拙いコードですが、どうか温かい目で見守っていただければと願っております。

目次

  1. before
  2. after
  3. 感想

Before

元のコードの特徴として、ほとんどの処理がmain内に記述されていました。さすがに見にくすぎたのか、いくつかの機能は関数として定義されています。

main.py
import pygame
from pygame.locals import *
import sys

def map_make(map_data, screen, map_now, size):
    # 配列 map_data のデータからブロックを配置
    # ...

def map_check(map_data, x_now, y_now, next_x, next_y, size):
    # 当たり判定の計算
    # ...

# リスタート状態
def restart(setup):
    #リスタートの際のマップ、プレイヤーの状態
    # ...

def main():
    # 各変数初期化
    # ...

    # マップデータの入った.txtファイルの読み込み、配列に保存
    # ...

    # ステージの読み込み、ブロックの配置
    # ...

    # キー入力に応じたプレイヤーの移動
    # ...

    # 以下たくさんのコード
    # ...

if __name__ == "__main__":
    main()

下の画像がゲーム画面です。黄緑の丸がプレイヤーです。青のブロックには触れても問題なく、赤のブロックに触れたらゲームオーバーです。
main 2023_12_06 21_14_15.png
main 2023_12_06 22_50_51.png

After

こんな感じになりました。
(一部の機能しか実装できていません)

main.py
import pygame
import sys


class GameObject:
    def __init__(self, x, y, size, color):
        self.rect = pygame.Rect(x, y, size, size)
        self.color = color

    def draw(self, screen):
        pygame.draw.rect(screen, self.color, self.rect)


class Player(GameObject):
    def __init__(self, x, y, size, color):
        super().__init__(x, y, size, color)
        self.speed = 5
        self.jump_status = False
        self.jump_status_up = 1
        self.jump_speed = self.speed * 2
        self.jump_high = size * 5
        self.jump_start = 0

    def move(self, direction):
        if direction == "a":
            self.rect.x -= self.speed
        elif direction == "d":
            self.rect.x += self.speed
        elif direction == "space" and not self.jump_status:
            self.jump_status = True
            self.jump_start = self.rect.y

    def jump(self):
        if self.jump_status:
            if self.jump_status_up == 1:
                if self.jump_start - self.rect.y >= self.jump_high:
                    self.jump_status_up *= -1
            else:
                if self.jump_start - self.rect.y == 0:
                    self.jump_status = False
                    self.jump_status_up *= -1
            self.rect.y -= self.jump_speed * self.jump_status_up


class Game:
    def __init__(self, width, height, size):
        self.width = width
        self.height = height
        self.screen = pygame.display.set_mode((width, height))
        pygame.display.set_caption("main")
        self.clock = pygame.time.Clock()
        self.player = Player(size*2, height-size*3, size, (0, 255, 0))
        self.game_objects = [self.player]

    def handle_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_a]:
            self.player.move("a")
        if keys[pygame.K_d]:
            self.player.move("d")
        if keys[pygame.K_SPACE]:
            self.player.move("space")
        if keys[pygame.K_ESCAPE]:
            pygame.quit()
            sys.exit()          
        self.player.jump()

    def draw(self):
        self.screen.fill((0, 0, 0))
        for obj in self.game_objects:
            obj.draw(self.screen)
        pygame.display.flip()

    def run(self):
        while True:
            self.handle_events()
            self.update()
            self.draw()
            self.clock.tick(60)

if __name__ == "__main__":
    pygame.init()
    game = Game(1000, 500, 25)
    game.run()

GameObjectクラス:

・ゲーム内のオブジェクトを表す基底クラス
・_init_メソッド : 引数からpygame.Rect オブジェクトと色を初期化
・draw メソッド : オブジェクトを画面に描画

Player クラス:

・GameObject クラスを継承したプレイヤークラス
・_init_メソッド : プレイヤー固有の変数を初期化
・move メソッド : キー入力に応じてプレイヤーの移動、ジャンプの開始を制御
・jump メソッド : ジャンプの制御

Game クラス:

・ゲーム全体の制御を行うクラス
・_init_メソッド: ウィンドウ、ゲームオブジェクトのリストなどの初期化
・handle_events メソッド: Pygameイベントの処理
・update メソッド: キー入力に応じてプレイヤーの移動やジャンプを制御
・draw メソッド: 背景、ゲームオブジェクトの描画
・run メソッド: ゲームのメインループ

main:

・Pygame の初期化、Gameクラスのインスタンスの作成、runメソッドの呼び出し

感想

オブジェクト指向で作成したプログラムのほうが可読性と保守性を高めることができたと思います。

授業の内容だけではうまくプログラムを作成できなかったため、chatGPT君にたくさん助けてもらいました。時間的な問題で一部の機能しか実装できなかったので、いつか完成させたいです。

最後まで見ていただきありがとうございます。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?