Zenn
Closed5

Pygameでオーディオ再生

kun432kun432

ゲーム用途ではなく、音声処理ライブラリとして、ChatGPTがなんか推奨してきたので、ちょっと調べてみる。

kun432kun432

GitHubレポジトリ

https://github.com/pygame/pygame

Pygame

Pygame は、Python を使用してビデオゲームのようなマルチメディアアプリケーションを開発するための、無料でオープンソースのクロスプラットフォームライブラリです。
Simple DirectMedia Layer ライブラリ やその他の人気のあるライブラリを利用し、一般的な機能を抽象化することで、これらのプログラムの作成をより直感的に行えるようにします。

特徴

Pygame はゲーム開発に適した強力なライブラリであり、コーディングを簡単にする多くの機能を提供します。その主な特徴を紹介します。

グラフィックス

Pygame を使用すると、動的で魅力的なグラフィックを簡単に作成できます。2D グラフィックやアニメーションのためのツールが充実しており、画像、長方形、ポリゴンの描画をサポートします。

サウンド

Pygame には、サウンドや音楽を再生・操作する機能も含まれています。WAV、MP3、OGG などのファイルフォーマットに対応しており、効果音や BGM を簡単に追加できます。

入力処理

キーボード、マウス、ジョイスティックの入力処理が直感的に行えます。これにより、プレイヤーの操作をスムーズに実装できます。

ゲーム開発機能

Pygame は、ゲーム開発に特化した包括的なツールセットを提供します。衝突検出、スプライト管理など、さまざまな機能を備えており、プラットフォーマーやパズルゲームなど、あらゆるジャンルのゲーム開発に対応できます。

公式サイト

https://www.pygame.org/news.html

kun432kun432

目的は、サウンド部分の処理を知りたいだけなのだけど、まずはGetting Startedを簡単にやってみる。

https://www.pygame.org/wiki/GettingStarted

インストール

作業ディレクトリ作成

mkdir pygame-work && cd pygame-work

Python仮想環境作成。最近はuvを使っている。

uv venv -p 3.12.8

ではpygameをインストール

uv pip install pygame
出力
Installed 1 package in 16ms
 + pygame==2.6.1

サンプルのゲームを起動

uv run python -m pygame.examples.aliens

Quick start

ちょっとリンクがわかりにくかったけど、これかな。

https://www.pygame.org/docs/#quick-start

でこれをやる前に、まず以下を見ると良さそう。冒頭8分だけでいいと思うので、以下をざっくり理解する。(もちろんこの動画の内容をそのまま進めるのもいいと思う。)

  • How games work(ゲームはどう動いているのか)
  • What Pygame does(Pygameは何をやってくれるのか)

https://www.youtube.com/watch?v=AY9MnQ4x3zk

NotebookLMにまとめてもらった

How games work(ゲームはどう動いているのか)

ビデオゲームの仕組みの要約は以下の通りです。

  • ビデオゲームは、映画と似ており多数の画像を高速で連続して再生することで動いているように見せている。
  • 映画とビデオゲームの主な違いは、ビデオゲームでは、各画像が固定されておらず、動的に作成される点。
  • ビデオゲームでは、プレイヤーからの入力に応じて画像が変化する。例えば、敵の位置やプレイヤーのボタン操作に応じて、表示される画像が異なる。
  • ビデオゲームは、プレイヤーの入力をチェックし、その情報を使用して画面上に要素を配置する。
  • ビデオゲームの基本的な流れは、プレイヤーからの入力を受け取り(イベントループ)、その情報に基づいて画面上に要素を配置し、画像を完成させる。そして、このプロセスを何度も繰り返す
  • Pygameは、画像の表示、サウンドの再生、プレイヤー入力の取得など、ゲーム開発に必要な機能を提供する。
  • Pygameを使用すると、ウィンドウを作成し、画像を表示したり、マウスの位置キーボード入力を取得したりできる。また、衝突判定テキストの作成タイマーなどの機能も利用できる。

What Pygame does(Pygameは何をやってくれるのか)

Pygameの機能は以下の通りです。

  • 画像の表示に優れており、Pythonでウィンドウを作成したり、画像アニメーションを表示したりするのが簡単になる。
  • サウンドも再生できる。
  • プレイヤーからの入力をサポートする。マウスの位置キーボードゲームパッドから入力を得ることが可能。標準的なPythonのinputメソッドとは異なり、ゲームを中断せずに入力を取得できる。
  • 衝突検出テキストの作成タイマーなど、ゲームの開発に役立つ機能もある。
  • 高度なゲームの開発には向いていない。より複雑なゲーム(Dark SoulsやAssassin's Creedなど)では、Unreal、Unity、Godotなどのゲームエンジンが推奨される。
  • Pygameは、コーディングの学習システム構築に非常に役立ち、プログラミング・スキルの向上に役立つ。
  • Pygameは、本格的なゲーム開発だけでなく、映画グラフの表示にも利用できる。

特に重要なのは「ゲームループ」という考え方なのだと思う。

ということでQuickstartに戻って、サンプルコード。

pygame_quickstart.py
# 基本的なpygame「ゲームループ」の例
import pygame

# pygameの初期化
pygame.init()
screen = pygame.display.set_mode((1280, 720))
clock = pygame.time.Clock()
running = True

while running:
    # イベントをポーリング
    # pygame.QUITイベントはユーザーがウィンドウを閉じるためにXをクリックしたことを意味します
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 前のフレームの内容を消すために画面を色で塗りつぶす
    screen.fill("purple")

    # ここにゲームの描画処理を記述

    # ディスプレイを更新して作業内容を画面に表示
    pygame.display.flip()

    clock.tick(60)  # FPSを60に制限

pygame.quit()

whileの中がゲームループにあたる。イベントを拾う→何らかの処理をする→画面を更新する、というのを高速に回すことで、ゲームが進行するということ。

実行してみる。

uv run pygame_quickstart.py

ウインドウが開く。

「ウインドウを閉じる」というイベントで、ループを抜けて、処理が終了する。

もう1つのサンプル

pygame_quickstart2.py
# 円が動くサンプル
import pygame

# pygameの初期化
pygame.init()
screen = pygame.display.set_mode((1280, 720))
clock = pygame.time.Clock()
running = True
dt = 0

player_pos = pygame.Vector2(screen.get_width() / 2, screen.get_height() / 2)

while running:
    # イベントをポーリング
    # pygame.QUITイベントはユーザーがウィンドウを閉じるためにXをクリックしたことを意味します
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 前のフレームの内容を消すために画面を色で塗りつぶす
    screen.fill("purple")

    pygame.draw.circle(screen, "red", player_pos, 40)

    keys = pygame.key.get_pressed()
    if keys[pygame.K_w]:
        player_pos.y -= 300 * dt
    if keys[pygame.K_s]:
        player_pos.y += 300 * dt
    if keys[pygame.K_a]:
        player_pos.x -= 300 * dt
    if keys[pygame.K_d]:
        player_pos.x += 300 * dt

    # ディスプレイを更新して作業内容を画面に表示
    pygame.display.flip()

    # FPSを60に制限
    # dtは前のフレームからの経過時間(秒)で、フレームレートに依存しない物理計算に使用されます
    dt = clock.tick(60) / 1000

pygame.quit()

実際にオブジェクトを操作する例。

実行。

uv run pygame_quickstart2.py

円が表示される。

以下で操作ができる。

w: 上
s: 下
a: 左
d: 右

ゲームループの考え方は以下のチュートリアルのコードも参考になる。

http://pygametutorials.wikidot.com/tutorials-basic

Quickstartの2つ目のコードをクラスで書き換えたもの。

import pygame


class App:
    def __init__(self):
        # アプリケーションの実行状態と表示サーフェスを初期化
        self._running = True
        self._display_surf = None
        # 画面サイズを設定
        self.size = self.width, self.height = 1280, 720
        # プレイヤーの位置と経過時間を初期化
        self.player_pos = pygame.Vector2(self.width / 2, self.height / 2)
        self.dt = 0

    def on_init(self):
        # pygameを初期化し、表示サーフェスを作成
        pygame.init()
        self._display_surf = pygame.display.set_mode(self.size, pygame.HWSURFACE | pygame.DOUBLEBUF)
        self._running = True
        # フレームレート制御用のClockオブジェクトを作成
        self.clock = pygame.time.Clock()

    def on_event(self, event):
        # イベント処理: ウィンドウの閉じるボタンが押されたら終了
        if event.type == pygame.QUIT:
            self._running = False

    def on_loop(self):
        # キー入力処理
        keys = pygame.key.get_pressed()
        if keys[pygame.K_w]:
            self.player_pos.y -= 300 * self.dt
        if keys[pygame.K_s]:
            self.player_pos.y += 300 * self.dt
        if keys[pygame.K_a]:
            self.player_pos.x -= 300 * self.dt
        if keys[pygame.K_d]:
            self.player_pos.x += 300 * self.dt

    def on_render(self):
        # 画面を紫色で塗りつぶす
        self._display_surf.fill("purple")
        # プレイヤーを赤い円として描画
        pygame.draw.circle(self._display_surf, "red", self.player_pos, 40)
        # ディスプレイを更新
        pygame.display.flip()

    def on_cleanup(self):
        # pygameを終了
        pygame.quit()

    def on_execute(self):
        # 初期化処理
        if self.on_init() == False:
            self._running = False

        # メインゲームループ
        while( self._running ):
            # イベント処理
            for event in pygame.event.get():
                self.on_event(event)
            # ゲームロジック更新
            self.on_loop()
            # 描画処理
            self.on_render()
            # FPSを60に制限し、経過時間を計算
            self.dt = self.clock.tick(60) / 1000
        # 終了処理
        self.on_cleanup()


if __name__ == "__main__" :
    # アプリケーションのインスタンスを作成して実行
    theApp = App()
    theApp.on_execute()

あとは公式ドキュメントの上のリンクや、いろいろなチュートリアル集を見つつ試していく感じかな。

公式ドキュメント
https://www.pygame.org/docs/

いろいろなチュートリアルへのリンク集
https://www.pygame.org/wiki/tutorials

kun432kun432

GitHubにいろいろサンプルコードがある。

https://github.com/pygame/pygame/tree/master/examples

今回知りたいオーディオ関連はこのへんかな。

  • audiocapture.py
    マイクからの音声を録音し、再生する例。
  • music_drop_fade.py
    音楽ファイルをドロップして、再生時にフェード効果を適用する方法を示しています。
  • playmus.py
    コマンドラインから音楽ファイルを再生するためにmixerモジュールを使用する例です。
  • sound.py
    サウンドエフェクトや音楽の実装方法を紹介しています。
  • sound_array_demos.py
    エコーやディレイなど、配列を使った音処理の例を示しています。

ドキュメントだと多分これ

https://www.pygame.org/docs/ref/mixer.html

https://www.pygame.org/docs/ref/music.html

https://www.pygame.org/docs/ref/sndarray.html

kun432kun432

ちょっと自分がイメージしていた使い方とはやっぱり違うかもしれない。

また気が向いたらもう少し試してみる。

このスクラップは2ヶ月前にクローズされました
ログインするとコメントできます