Pygameのdraw.rect徹底解説!図形描画の基本から応用まで
基本的な使い方は以下のようになります。
pygame.draw.rect(surface, color, rect, width=0, border_radius=-1, border_top_left_radius=-1, border_top_right_radius=-1, border_bottom_left_radius=-1, border_bottom_right_radius=-1)
それぞれの引数の意味は次の通りです。
border_top_left_radius
,border_top_right_radius
,border_bottom_left_radius
,border_bottom_right_radius
(オプション): それぞれの角に個別に丸みを指定する場合に使用します。これらの値が設定されていない場合、border_radius
の値が使用されます。border_radius
(オプション): 四角形の角の丸みを指定します。すべての角に同じ丸みを適用します。width
(オプション):0
の場合(デフォルト):四角形を塗りつぶします。0
より大きい場合:四角形の線の太さを指定します。0
より小さい場合:何も描画されません。
rect
: 描画する四角形の位置とサイズを指定します。以下のいずれかの形式で指定できます。(left, top, width, height)
のタプル: 四角形の左上のx座標、左上のy座標、幅、高さを指定します。pygame.Rect
オブジェクト: PygameのRect
オブジェクトは、矩形の座標とサイズを管理するための便利なオブジェクトです。
color
: 四角形の色を指定します。RGB形式のタプル(R, G, B)
やRGBA形式のタプル(R, G, B, A)
、またはPygameのColor
オブジェクトで指定します。surface
: 四角形を描画する対象のSurfaceオブジェクトです。通常はpygame.display.set_mode()
で作成した画面のSurfaceを指定します。
例
画面の中央に赤い塗りつぶされた四角形を描画する例です。
import pygame
pygame.init()
# 画面のセットアップ
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("draw.rect の例")
# 色の定義
red = (255, 0, 0)
white = (255, 255, 255)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 画面を白で塗りつぶす
screen.fill(white)
# 四角形を描画
# (x, y, width, height) の形式で指定
# 画面の中央に200x100の四角形
rect_x = (screen_width / 2) - 100
rect_y = (screen_height / 2) - 50
pygame.draw.rect(screen, red, (rect_x, rect_y, 200, 100))
# 画面を更新
pygame.display.flip()
pygame.quit()
このコードでは、pygame.draw.rect(screen, red, (rect_x, rect_y, 200, 100))
の部分で、screen
上に red
(赤色) で (rect_x, rect_y, 200, 100)
で指定された位置とサイズの四角形を塗りつぶして描画しています。
width
引数を使用して、線の四角形を描画することもできます。
# 線だけの四角形 (太さ5ピクセル)
pygame.draw.rect(screen, red, (rect_x - 50, rect_y - 50, 200, 100), 5)
draw.rect
でよくあるエラーとトラブルシューティング
TypeError: rect argument is invalid (Rect引数が無効です)
これは最も頻繁に見られるエラーの一つです。rect
引数の指定方法に問題がある場合に発生します。
原因
- 引数の順番間違い
draw.rect(color, surface, rect)
のように引数の順番を間違えている。正しい順番は(surface, color, rect, ...)
です。 - 無効な pygame.Rect オブジェクト
pygame.Rect()
の引数が不正だったり、存在しないRect
オブジェクトを渡そうとしている。 - 無効なタプル形式
(left, top, width, height)
のタプルを正しく指定していない。例えば、要素が足りない、文字列が入っている、負の値が入っている(特にwidth
やheight
が負の場合)。
トラブルシューティング
- 引数の順番の確認
pygame.draw.rect(surface, color, rect, ...)
の順序を必ず守ってください。 - rect 引数の確認
- タプルで指定している場合、
print(rect_tuple)
のようにして、その内容が(数値, 数値, 数値, 数値)
の形式で、各数値が期待通りの値になっているか確認してください。特にwidth
やheight
が負になっていないか確認してください。 pygame.Rect
オブジェクトを使用している場合、print(my_rect)
のようにしてRect
オブジェクトが正しく作成され、そのx
,y
,width
,height
プロパティが正しいか確認してください。
- タプルで指定している場合、
四角形が描画されない / 画面に表示されない
コードにはエラーが出ていないのに、四角形が画面に表示されない場合があります。
原因
- surface 引数が間違っている
pygame.display.set_mode()
で作成したメインのscreen
以外のSurfaceに描画している場合、それがメイン画面にblittingされていないと表示されません。 - 色が背景色と同じ
四角形の色が背景色と全く同じ場合、見分けがつきません。 - 四角形のサイズが小さすぎる(0など)
width
やheight
が0または非常に小さい場合、見えません。 - 四角形の位置が画面外
四角形のleft
,top
座標が画面の範囲外にある場合、見えません。 - 背景色で上書きされている
四角形を描画した後に、別のscreen.fill()
などで画面全体を塗りつぶしている場合、四角形がすぐに消えてしまいます。 - pygame.display.update() または pygame.display.flip() の呼び忘れ
画面に変更を反映させるためには、これらの関数のいずれかをゲームループの最後に呼び出す必要があります。
トラブルシューティング
- 色の確認
四角形の色と背景色を一時的に全く異なる色にしてみてください。 - 座標とサイズの確認
print()
文を使って、draw.rect
に渡しているrect
のx
,y
,width
,height
が画面内に収まっており、かつ十分な大きさがあるか確認してください。 - 描画順序の確認
screen.fill()
などの背景描画処理の後にpygame.draw.rect()
を呼び出すようにしてください。 - 画面更新の確認
ゲームループの最後にpygame.display.flip()
またはpygame.display.update()
が呼び出されているか確認してください。
四角形の線が太すぎる / おかしい (width 引数関連)
width
引数を使用して線の四角形を描画する際に、予期せぬ表示になることがあります。
原因
- Pygameのバージョンによる挙動の違い
古いPygameのバージョンでは、線の太さや角の描画にバグや癖があった可能性があります。 - width が大きすぎる
指定したwidth
が四角形のwidth
やheight
よりも大きい場合、奇妙な表示になることがあります。Pygameの仕様上、線の描画は少し複雑な場合があります。 - width が負の値
width
が負の値の場合、何も描画されません。
トラブルシューティング
- Pygameのバージョンアップ
もし非常に古いPygameを使用している場合は、最新版にアップデートすることで問題が解決する可能性があります。 - 描画の確認
width
を0(塗りつぶし)にして正しく描画されるか確認し、そこから徐々にwidth
を増やして挙動を観察してください。 - width の値を確認
width
が0より大きい正の整数で、かつ四角形のサイズに比べて妥当な値であるか確認してください。
角の丸みが適用されない / おかしい (border_radius 関連)
border_radius
を使って角を丸める際に、期待通りにならないことがあります。
原因
- border_radius が大きすぎる
丸みが四角形のサイズに対して大きすぎると、うまく描画されません。特に、同じ辺の半径の合計が辺の長さを超える場合、Pygameは内部的に丸みを縮小して描画しようとしますが、見た目が不自然になることがあります。 - border_radius が負の値
負の値は無視されるか、角が丸められません。 - Pygameのバージョン
border_radius
引数はPygame 2.0.0以降で追加されました。古いバージョンを使用している場合、この引数は無視されるか、エラーになります。
- width 引数との兼ね合い
width
(線の太さ) を指定している場合、丸みの描画に影響を与えることがあります。塗りつぶし (width=0
) で試してみて、丸みが正しく適用されるか確認してください。 - border_radius の値を確認
border_radius
は0以上の整数である必要があります。また、四角形のwidth
やheight
の半分以下を目安にしてみてください。例えば、幅100の四角形で半径60にすると、うまく描画されないことがあります。 - Pygameのバージョン確認
print(pygame.version.ver)
で現在使用しているPygameのバージョンを確認してください。もし2.0.0未満であれば、border_radius
は使えません。
- Pygameドキュメントを参照する
公式ドキュメント (pygame.org/docs/
) は、関数の使い方や引数の詳細、バージョンごとの変更点などが記載されており、非常に役立ちます。 - エラーメッセージを読む
PythonやPygameが出力するエラーメッセージは、どこで何が間違っているかを示す非常に重要な情報源です。特にTypeError
,ValueError
などに注目してください。 - print() デバッグ
draw.rect
に渡す引数(特にrect
の値)をprint()
文で出力し、期待通りの値になっているか確認してください。 - 最小限の再現可能なコード (Minimal Reproducible Example) を作成する
問題が発生したコード全体ではなく、draw.rect
に関連する部分だけを抜き出して、最小限のコードで問題が再現するかどうか確認してください。これにより、問題の原因を特定しやすくなります。
例1: 基本的な四角形の描画(塗りつぶしと線)
最も基本的な draw.rect
の使い方です。
import pygame
# Pygameの初期化
pygame.init()
# 画面設定
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("基本的な四角形の描画")
# 色の定義 (R, G, B)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 画面を白で塗りつぶす (毎フレームクリア)
screen.fill(WHITE)
# 1. 塗りつぶされた赤い四角形
# (x, y, width, height) のタプルで位置とサイズを指定
pygame.draw.rect(screen, RED, (50, 50, 150, 100))
# 2. 緑色の枠線だけの四角形 (線の太さ: 5ピクセル)
# width引数に0より大きい値を指定
pygame.draw.rect(screen, GREEN, (250, 50, 150, 100), 5)
# 3. 青色の枠線と塗りつぶしを組み合わせた四角形 (幅0で塗りつぶし、その後線を描画)
# 同じ場所に塗りつぶしと線を重ねて描画する
pygame.draw.rect(screen, BLUE, (450, 50, 150, 100), 0) # 塗りつぶし
pygame.draw.rect(screen, (0, 0, 0), (450, 50, 150, 100), 2) # 黒い線
# 画面を更新
pygame.display.flip()
pygame.quit()
例2: pygame.Rect
オブジェクトの使用
pygame.Rect
オブジェクトは、矩形の管理に非常に便利です。位置やサイズをプロパティで操作でき、衝突判定などにも使われます。
import pygame
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Rect オブジェクトの使用")
WHITE = (255, 255, 255)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
# Rect オブジェクトの作成
# (left, top, width, height) で初期化
my_rect = pygame.Rect(100, 100, 200, 150)
# Rect オブジェクトのプロパティを利用
# my_rect.x, my_rect.y, my_rect.width, my_rect.height など
print(f"初期位置: ({my_rect.x}, {my_rect.y}), サイズ: ({my_rect.width}, {my_rect.height})")
print(f"中心座標: {my_rect.center}")
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# マウスイベントでRectを動かす
if event.type == pygame.MOUSEMOTION:
# Rectの中心をマウスの位置に設定
my_rect.center = event.pos
screen.fill(WHITE)
# Rect オブジェクトを draw.rect に渡す
pygame.draw.rect(screen, CYAN, my_rect)
# Rect の他のプロパティを使って、関連する図形を描画
pygame.draw.circle(screen, MAGENTA, my_rect.topleft, 5) # 左上に小さな円
pygame.draw.circle(screen, MAGENTA, my_rect.center, 5) # 中央に小さな円
pygame.display.flip()
pygame.quit()
例3: アニメーションする四角形
ゲームでよく使われる、動的な四角形(プレイヤーや敵など)の描画例です。
import pygame
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("アニメーションする四角形")
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
# 四角形の設定
player_rect = pygame.Rect(50, screen_height // 2 - 25, 50, 50) # 画面中央左寄りに配置
player_speed = 5
clock = pygame.time.Clock() # FPS制御用
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# キー入力による移動
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player_rect.x -= player_speed
if keys[pygame.K_RIGHT]:
player_rect.x += player_speed
if keys[pygame.K_UP]:
player_rect.y -= player_speed
if keys[pygame.K_DOWN]:
player_rect.y += player_speed
# 画面端での移動制限
if player_rect.left < 0:
player_rect.left = 0
if player_rect.right > screen_width:
player_rect.right = screen_width
if player_rect.top < 0:
player_rect.top = 0
if player_rect.bottom > screen_height:
player_rect.bottom = screen_height
screen.fill(WHITE)
# 四角形を描画
pygame.draw.rect(screen, BLUE, player_rect)
pygame.display.flip()
clock.tick(60) # 60 FPS に設定
pygame.quit()
例4: 角が丸い四角形 (border_radius
)
Pygame 2.0.0 以降で利用可能な border_radius
引数を使った例です。
import pygame
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("角が丸い四角形")
WHITE = (255, 255, 255)
ORANGE = (255, 165, 0)
PURPLE = (128, 0, 128)
BLACK = (0, 0, 0)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(WHITE)
# 1. すべての角に同じ丸みを適用
# 半径20の丸い角の四角形
pygame.draw.rect(screen, ORANGE, (50, 50, 200, 100), border_radius=20)
# 2. 角の丸みと線の太さを組み合わせる
# 線の太さ3ピクセル、半径15の丸い角の四角形
pygame.draw.rect(screen, PURPLE, (300, 50, 200, 100), 3, border_radius=15)
# 3. 各角に異なる丸みを適用 (Pygame 2.0.0以降)
# top-left, top-right, bottom-left, bottom-right の順に指定
# 注: -1 は border_radius の値が適用されることを意味します。
# この例では border_radius は指定していないので、-1の角は丸くなりません。
# 明示的に値を指定する場合:
pygame.draw.rect(screen, BLACK, (50, 200, 200, 100), 0,
border_top_left_radius=30,
border_top_right_radius=0, # 丸めない
border_bottom_left_radius=10,
border_bottom_right_radius=50)
# 4. 大きすぎる border_radius の例 (不自然になる可能性あり)
pygame.draw.rect(screen, RED, (300, 200, 100, 50), border_radius=40) # 幅50に対して半径40は大きい
pygame.display.flip()
pygame.quit()
ユーザーがマウスで四角形を描画できるようなインタラクティブな例です。
import pygame
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("マウスドラッグで四角形を描画")
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
drawing_rect = False
start_pos = (0, 0)
current_rect = None
drawn_rects = [] # 描画済みの四角形を保存するリスト
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # 左クリック
drawing_rect = True
start_pos = event.pos # ドラッグ開始位置を記録
current_rect = None # 新しい四角形の描画を開始
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # 左クリックを離す
drawing_rect = False
if current_rect:
drawn_rects.append(current_rect) # 描画された四角形を保存
elif event.type == pygame.MOUSEMOTION:
if drawing_rect:
end_pos = event.pos
# 開始位置と現在のマウス位置から矩形を計算
x = min(start_pos[0], end_pos[0])
y = min(start_pos[1], end_pos[1])
width = abs(start_pos[0] - end_pos[0])
height = abs(start_pos[1] - end_pos[1])
current_rect = pygame.Rect(x, y, width, height)
screen.fill(WHITE)
# 描画済みの四角形を描画
for rect in drawn_rects:
pygame.draw.rect(screen, BLUE, rect, 2) # 線の四角形として描画
# 現在ドラッグ中の四角形があれば描画
if drawing_rect and current_rect:
pygame.draw.rect(screen, (255, 0, 0), current_rect, 2) # 赤い線で描画
pygame.display.flip()
pygame.quit()
pygame.Surface オブジェクトを作成して Blit する
これは draw.rect
の最も一般的な代替手段であり、特に同じ四角形を繰り返し描画する場合や、四角形に透明度、回転、拡大縮小などの効果を適用したい場合に非常に強力です。
方法
- まず、四角形の形状を持つ
pygame.Surface
オブジェクトを作成します。 - そのSurfaceに
fill()
メソッドを使って色を塗るか、draw.rect()
を使って内側に描画します。 - 作成したSurfaceを
screen.blit()
を使ってメイン画面に描画します。
利点
- 再利用性
一度Surfaceを作成すれば、それを何度も効率的にblittingできます。特に、同じ画像を繰り返し描画する場合にパフォーマンスが向上します。 - 柔軟性
Surfaceに透明度 (set_alpha()
)、回転 (pygame.transform.rotate()
)、拡大縮小 (pygame.transform.scale()
) などの変換を適用できます。
欠点
- 単純な塗りつぶしの四角形を一度だけ描画するだけなら、
draw.rect
よりコード量が増え、わずかにオーバーヘッドがあります。
コード例
import pygame
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Surfaceを使って四角形をBlitする")
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
# 1. 青い四角形のSurfaceを作成
# サイズは (幅, 高さ)
blue_square_surface = pygame.Surface((100, 100))
blue_square_surface.fill(BLUE) # Surface全体を青で塗りつぶす
# 2. 緑色の透明な四角形のSurfaceを作成
# SRCALPHA フラグで透明度をサポート
green_rect_surface = pygame.Surface((150, 80), pygame.SRCALPHA)
# 塗りつぶし (RGBA形式で透明度を指定)
green_rect_surface.fill((0, 255, 0, 128)) # 半透明の緑
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(WHITE)
# 青い四角形のSurfaceを画面にblitting
screen.blit(blue_square_surface, (50, 50))
# 透明な緑の四角形のSurfaceをblitting
screen.blit(green_rect_surface, (200, 150))
# 回転した四角形(Surfaceを使うからこそ可能)
rotated_surface = pygame.transform.rotate(blue_square_surface, 45) # 45度回転
# 回転するとRectのサイズが変わるので、中心を合わせてblitting
rotated_rect = rotated_surface.get_rect(center=(400, 100))
screen.blit(rotated_surface, rotated_rect)
pygame.display.flip()
pygame.quit()
画像ファイルを使用する
四角形がテクスチャや複雑なデザインを持つ場合は、画像ファイル(PNG, JPGなど)を読み込んで描画する方法が適切です。
方法
pygame.image.load()
で画像ファイルを読み込みます。- 読み込んだ画像を
screen.blit()
で画面に描画します。
利点
- デザイナーとの連携
グラフィックデザイナーが作成したアセットを直接使用できます。 - 視覚的表現の豊かさ
ピクセルアート、写真、複雑なグラデーションなど、デザインの自由度が非常に高いです。
欠点
- サイズ変更や色変更などの動的な変更が、
draw.rect
やSurface.fill()
よりも複雑になる場合があります。 - 単純な色付きの四角形のためだけに画像ファイルを用意するのは過剰です。
コード例 (概念のみ)
# pygame.image.load("path/to/your_rectangle_image.png") を使う
# screen.blit(loaded_image, (x, y))
個々のピクセルを描画する (pygame.PixelArray)
非常に低レベルな制御が必要な場合、または特定のパターンを手動で作成したい場合に、pygame.PixelArray
を使用して直接ピクセルを操作できます。ただし、パフォーマンスは非常に悪いため、単純な四角形を描画する目的には推奨されません。デバッグや特定の特殊効果のために一時的に使用されることがあります。
方法
pygame.PixelArray(surface)
を作成します。- 配列のインデックスを使って個々のピクセルの色を設定します。
del pixel_array
でPixelArrayを解放し、変更をSurfaceに適用します。
利点
- ピクセル単位で完全に制御できます。
欠点
- コードが複雑になりがちです。
- 極めて遅いです。
import pygame
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("PixelArrayで四角形を描画 (非推奨)")
WHITE = (255, 255, 255)
RED = (255, 0, 0)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(WHITE)
# PixelArrayを使用して赤い四角形を描画
try:
pixels = pygame.PixelArray(screen)
for x in range(100, 200): # 矩形のX範囲
for y in range(100, 200): # 矩形のY範囲
pixels[x, y] = RED
finally:
del pixels # 変更を適用し、PixelArrayを解放
pygame.display.flip()
pygame.quit()
OpenGLなどの外部ライブラリを使用する
Pygameは2D描画ライブラリですが、より高度な3D描画やGPUアクセラレーションを必要とする場合は、PyOpenGLなどのライブラリをPygameと組み合わせて使用できます。この場合、四角形はOpenGLのプリミティブ(クアッドなど)として描画されます。これはPygameの draw
モジュールとは全く異なる描画パラダイムになります。
利点
- 3Dグラフィックス機能。
- GPUアクセラレーションによる高速描画。
- Pygameの他の描画機能との統合が複雑になる場合があります。
- 学習曲線が急です。
- 高度なパフォーマンスや3Dが必要ならOpenGLなどを検討します。
pygame.PixelArray
は特殊なケース以外では避けるべきです。- テクスチャやデザインの複雑な四角形なら画像ファイルを使用します。
- 透明度、回転、拡大縮小、複雑な内容を持つ四角形を扱うなら
pygame.Surface
を作成して Blit するのが最適です。 - 単純な色付き四角形を直接描画するなら
pygame.draw.rect
が最も効率的です。