はじめに
前回、画面に四角形を描くことができましたが、まだ動きません。 ゲームとは、パラパラ漫画のように「少しずつ動かした絵」を高速で切り替えることで成立しています。多くの初心者はここで「while Trueループで回せばいいんでしょ?」と考えますが、GUIアプリでそれをやると画面がフリーズして死にます。今回は、PySide6における正しいループの作り方、「QTimer」の使い方をマスターしましょう。
§1. なぜ「while True」はダメなのか?
#2で解説した通り、GUIアプリは常に「イベントループ(待機状態)」の中にいます。もし自分で while True: を書いてしまうと、プログラムがそこで全力疾走を始めてしまい、ウィンドウの描画やクリックを受け付ける余裕がなくなります。結果、アプリは「応答なし」になります。
§2. 正解は「QTimer(キッチンタイマー)」
そこで使うのが QTimer です。 これは、「指定した時間ごとに、ベル(合図)を鳴らす」機能です。
設定: 「0.016秒(約16ミリ秒)ごとに合図して!」
動作:0.016秒経つ。
合図が鳴る → 「キャラの座標を+1する」
合図が鳴る → 「画面を書き直す(再描画)」
(待機)
また0.016秒経つ...
この隙間があるおかげで、アプリはフリーズせずに動き続けることができます。 ちなみに 1秒 ÷ 60回 ≒ 0.016秒 なので、これで滑らかな60FPSが実現できます。
§3. 実践コード:四角形を走らせろ!
四角形が左から右へ自動で動くコードです。 コピーして実行してみてください。
pythonコード
はじまり---------------------------------------------
import sys
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QBrush, QColor
from PySide6.QtCore import QTimer, Qt
class GameLoopWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("動け!四角形")
self.resize(500, 300)
# ★ 変数の準備
self.rect_x = 0 # 四角形のX座標(最初は0)
# ★ 1. タイマーの準備
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_game) # 時間が来たら呼ぶ関数を指定
self.timer.start(16) # 16ミリ秒ごとにスタート!
# ★ 2. 定期的に実行される「ゲームの更新処理」
def update_game(self):
# 座標を少し右にずらす
self.rect_x += 2
# 画面の端まで行ったら左に戻す(ループ)
if self.rect_x > 500:
self.rect_x = -50
# 重要:「画面を書き直して!」とOSに依頼する
self.update()
# ★ 3. 描画処理(update()されると呼ばれます)
def paintEvent(self, event):
painter = QPainter(self)
# 背景を塗りつぶす(これがないと残像が残る!)
painter.fillRect(self.rect(), Qt.white)
# 変数(self.rect_x)の位置に描く
painter.setBrush(QBrush(Qt.green))
painter.drawRect(self.rect_x, 100, 50, 50)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = GameLoopWindow()
window.show()
sys.exit(app.exec())
おわり---------------------------------------------
§4. コードの仕組み(リスト解説)
今回追加された「動き」の仕組みを表にまとめました。
| ブロック | 役割 | コードの要点 | 解説 |
| 準備 | タイマー設置 | self.timer = QTimer() self.timer.start(16) | 「16ミリ秒ごとに update_game を実行せよ」とセットします。 これがゲームの心臓の鼓動になります。 |
| 計算 | 座標の更新 | def update_game(self): self.rect_x += 2 | 変数の数字だけを変化させます。 ※ここでは描画はしません。 |
| 通知 | 再描画の依頼 | self.update() | 「データが変わったから、画面を描き直して!」という命令です。 これを呼ぶと、自動的に paintEvent が実行されます。 |
| 描画 | 表示 | def paintEvent... drawRect(self.rect_x...) | 変化した新しい self.rect_x を使って、四角形を描きます。 |
今日のまとめ
「変数」を変える。
「QTimer」で定期的に変える。
「update()」で画面に反映する。
この3ステップの繰り返しが、どんな複雑なゲームでも共通する「メインループ」の正体です。
次回予告
勝手に動く四角形は作れましたが、まだ操作できません。 次回は、あなたのキーボード操作でキャラを動かす「入力処理(Input)」を実装します。
Next Step: 【Vol.5】WASDで自由自在!キー入力でキャラを動かそう
