Pygameでリアルタイム処理の実装
下記コードを実行するとクライアント領域にプログラム開始からの秒数がカウントされていく。Pygameではまずサーフェスと呼ばれる描画面にグラフィックを描き込み、クライアント領域にサーフェスを載せる。直接クライアント領域に描き込まない。
import pygame
import sys
FONT_COLOR = (255, 255, 255) # 文字列の色を定数で定義
BG_COLOR = (0, 0, 0) # 背景色を定数で定義
def main():
pygame.init() # Pygameの初期化
pygame.display.set_caption("Pygameでリアルタイム処理") # ウィンドウタイトルの指定
screen = pygame.display.set_mode((300, 300)) # サーフェス(クライアント領域)の幅と高さを指定
clock = pygame.time.Clock() # PygameのClockオブジェクトを作成
font = pygame.font.Font(None, 80) # フォントオブジェクトを作成
tmr = 0
while True: # 無限ループ
tmr = tmr + 1
for event in pygame.event.get():
if event.type == pygame.QUIT: # プログラムの終了処理
pygame.quit()
sys.exit()
txt = font.render(str(tmr), True, FONT_COLOR) # サーフェスに文字列を描画
screen.fill(BG_COLOR) # スクリーンを指定色でクリア
screen.blit(txt, [150, 150]) # サーフェスをスクリーンに転送
pygame.display.update() # 画面更新を指示
clock.tick(10) # フレームレート(1秒間に何回画面更新を行うか)の指定
if __name__ == '__main__':
main()
Pygameでタイマーを使う場合、11行目のpygame.time.Clock()でClockオブジェクトを作成し、26行目のclock.tick()で実行。引数はフレームレート。ここでは10を指定し1秒間に10回(10FPS)処理するよう指定している。
Pygameで画像を表示
2枚のキャラクター画像を交互にアニメーション表示させて歩いているように見せる。Pygameで扱える画像形式はbmp、png、jpeg、gif等。
import pygame
import sys
BG_COLOR = (0, 0, 0)
def main():
pygame.init()
pygame.display.set_caption("Pygameで画像を表示")
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock() # Clockオブジェクトを作成
img_prayer = [ # アニメーションさせる2枚の画像を読み込み配列で管理
pygame.image.load("prayer_1.png"),
pygame.image.load("prayer_2.png")
]
tmr = 0
while True:
tmr = tmr + 1
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_F1: # F1キー押下でフルスクリーン化
screen = pygame.display.set_mode((300, 300), pygame.FULLSCREEN)
if event.key == pygame.K_ESCAPE: # Escキー押下でフルスクリーン解除
screen = pygame.display.set_mode((300, 300))
screen.fill(BG_COLOR) # 指定背景色で描画しクライアント領域をリセット
screen.blit(img_prayer[tmr % 2], [10, 10]) # モジュロ演算子で2枚の自機画像を交互に描画
pygame.display.update()
clock.tick(3) # フレームレート3で処理
if __name__ == '__main__':
main()
30行目でblit()で読み込んだ画像を表示。第一引数に画像を指定するが、モジュロ演算子を利用して2枚の画像を交互に表示させている。変数tmrの値は1ずつ増加し2で割ると余りが0か1となる。それを配列の添字に使いimg_prayer[0]またはimg_prayer[1]を指定させている。第二引数はX座標、Y座標を配列を指定する。tkinterは中央から指定する方式だが、Pygameはスクリーン座標であり左上隅からの指定。
画像は拡大縮小、回転、その両方を指定可能。
拡大縮小 | 変数 = pygame.transform.scale(イメージオブジェクト変数, [幅, 高さ]) |
---|---|
回転 | 変数 = pygame.transform.rotate(イメージオブジェクト変数, 回転角) |
回転 + 拡大縮小 | 変数 = pygame.transform.rotozoom(イメージオブジェクト変数, 回転角, 大きさの比率) |
上記コードの30行目を下記に変更してみる。
img_rz = pygame.transform.rotozoom(img_prayer[tmr % 2], 45, 3)
screen.blit(img_rz, [10, 10])
実行結果
24、26行目はフルスクリーン化と戻す処理。F1キーでフルスクリーン、Escで元に戻る。
Pygameでキー入力を取得
下記コードを実行すると、押された方向キーをクライアント領域にテキストで表示する
import pygame
import sys
FONT_COLOR = (255, 255, 255)
BG_COLOR = (0, 0, 0)
def main():
pygame.init()
pygame.display.set_caption("Pygameでキー入力")
screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 40) # フォント情報を設定
key_status = font.render("Not Entered", True, FONT_COLOR) # 文字列を描画するサーフェスに初期文字列を設定
while True:
keys = pygame.key.get_pressed() # 全てのキーの入力状態を取得
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if keys[pygame.K_UP]:
key_status = font.render("Press UP key", True, FONT_COLOR) # サーフェスにテキストを描画
if keys[pygame.K_DOWN]:
key_status = font.render("Press Down key", True, FONT_COLOR)
if keys[pygame.K_LEFT]:
key_status = font.render("Press Left key", True, FONT_COLOR)
if keys[pygame.K_RIGHT]:
key_status = font.render("Press Right key", True, FONT_COLOR)
screen.fill(BG_COLOR)
screen.blit(key_status, [10, 10])
pygame.display.update()
clock.tick(10)
if __name__ == '__main__':
main()
キー | 定数 |
---|---|
方向キー | K_UP、K_DOWN、K_LEFT、K_RIGHT |
スペースキー | K_SPACE |
エンターキー | K_RETURN |
Escキー | K_ESCAPE |
アルファベットキー | K_a〜K_z |
数字キー | K_0〜K_9 |
Shiftキー | K_RSHIFT、K_LSHIFT |
Fキー | K_F1〜 |
Pygameでマウス入力を取得
下記コードはクライアント領域上でマウスカーソルを動かすと、リアルタイムでX、Y座標が表示され続ける。さらにマウスボタンがクリックされるとFalseからTrueに変わる
import pygame
import sys
FONT_COLOR = (255, 255, 255)
BG_COLOR = (0, 0, 0)
def main():
pygame.init()
pygame.display.set_caption("Pygameでマウス入力")
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 40)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
mouseX, mouseY = pygame.mouse.get_pos() # マウスの位置情報を2つの変数に同時に代入
mouse_potison = font.render("{}, {}".format(mouseX, mouseY), True, FONT_COLOR) # サーフェスにマウス座標を描画
mb_click = pygame.mouse.get_pressed() # pygame.mouse.get_pressed()で現在のクリック状態をタプルで取得
mb_click_info = font.render(format(mb_click), True, FONT_COLOR) # クリック情報の入ったタプルの内容をサーフェスに描画
screen.fill(BG_COLOR)
screen.blit(mouse_potison, [10, 10]) # マウスの位置情報のサーフェスを貼り付け
screen.blit(mb_click_info, [10, 50]) # クリック情報のサーフェスを貼り付け
pygame.display.update()
clock.tick(10)
if __name__ == '__main__':
main()
23行目でpygame.mouse.get_pressed()からマウスボタンのクリック状態をタプルで取得。左ボタン、中央ボタン、右ボタンの順で格納されている。24行目でタプルの内容をそのまま書き込んでいるが、mb_click[0]などと表記して個別の値を取り出すことも可能。
上記はmouse.get_pressed()を使ったが別の方法もある。下記コードはMOUSEBUTTONDOWN等とボタン番号を組み合わせ左ボタン、中央ボタン、右ボタンのクリックを別々に取得している。ボタン番号を指定しない場合は区別無く全てに反応する。
イベント名 | 説明 |
---|---|
MOUSEBUTTONDOWN | マウスが押されたときに発生 |
MOUSEBUTTONUP | マウスボタンが離されたときに発生 |
MOUSEMOTION | マウスポインタが動いたとき |
ボタン番号 | ボタンの位置 |
---|---|
1 | 左ボタン |
2 | 中ボタン |
3 | 左ボタン |
4 | ホイールを上スクロール |
5 | ホイールを下にスクロール |
import pygame
import sys
from pygame.constants import MOUSEBUTTONDOWN, MOUSEBUTTONUP
FONT_COLOR = (255, 255, 255)
BG_COLOR = (0, 0, 0)
def main():
pygame.init()
pygame.display.set_caption("Pygameでマウス入力")
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 40)
mouse_click = font.render("Not Entered", True, FONT_COLOR) # クリック情報文字列を描画するサーフェスに初期値を設定
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# マウスの各ボタン毎に処理を条件分岐
if event.type == MOUSEBUTTONDOWN and event.button == 1:
mouse_click = font.render("LeftButton Click!", True, FONT_COLOR)
if event.type == MOUSEBUTTONDOWN and event.button == 2:
mouse_click = font.render("CenterButton Click!", True, FONT_COLOR)
if event.type == MOUSEBUTTONDOWN and event.button == 3:
mouse_click = font.render("RigthButton Click!", True, FONT_COLOR)
if event.type == MOUSEBUTTONUP:
mouse_click = font.render("Not Entered", True, FONT_COLOR)
mouseX, mouseY = pygame.mouse.get_pos() # マウスの位置情報を2つの変数に同時に代入
mouse_potison = font.render("{}, {}".format(mouseX, mouseY), True, FONT_COLOR) # マウスのX、Y座標をサーフェスに描画
screen.fill(BG_COLOR)
screen.blit(mouse_potison, [10, 10]) # マウスの位置情報文字列のサーフェスを貼り付け
screen.blit(mouse_click, [10, 50]) # マウスのクリック情報文字列のサーフェスを貼り付け
pygame.display.update()
clock.tick(10)
if __name__ == '__main__':
main()
Pygameでサウンドを鳴らす
Pygameではpygame.mixer.music.load()とpygame.mixer.Sound()の2つの関数が提供されている。前者はBGM、後者は効果音に使い分けるとよい。
下記コードを実行するとスペースキーでBGMの再生と停止、Sキーで効果音の再生が可能。BGM再生中に効果音を鳴らすことも可能。
import pygame
import sys
from pygame.constants import K_SPACE, K_s
FONT_COLOR = (255, 255, 255)
BG_COLOR = (0, 0, 0)
def main():
pygame.init()
pygame.display.set_caption("Pygameで音声データを再生")
screen = pygame.display.set_mode((400, 100))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 40)
pygame.mixer.music.load("sample_bgm.mp3")
se = pygame.mixer.Sound("sample_se.ogg")
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE] == 1:
if pygame.mixer.music.get_busy() == False: # get_busy()で再生中かどうか取得し判定
pygame.mixer.music.set_volume(0.1) # ボリュームを設定(0.0〜1.0)
pygame.mixer.music.play(-1) # 停止中ならループ再生
else:
pygame.mixer.music.stop() # 再生中なら停止
if keys[pygame.K_s] == 1:
se.set_volume(0.2)
se.play() # 効果音を再生
bgm_txt = font.render("BGM Start and Stop [SPACE]", True, FONT_COLOR)
se_txt = font.render("SE [S]", True, FONT_COLOR)
screen.fill(BG_COLOR)
screen.blit(bgm_txt, [10, 10])
screen.blit(se_txt, [10, 50])
pygame.display.update()
clock.tick(10)
if __name__ == '__main__':
main()
pygame.mixer.music.load()はmp3、ogg形式を再生可能、pygame.mixer.Sound()はwav、ogg形式を再生可能。
27行目と32行目でボリュームを設定している。0.0〜1.0の範囲で設定可能。
28行目のpygame.mixer.music.play()に引数-1を渡しループ再生を設定している。正数は再生回数で1なら1回再生、10なら10回再生。
コメント