mieki256's diary



2021/10/02() [n年前の日記]

#2 [pygame] Pyagmeで画像を分割して描画

Python + Pygame で、スプライトシート画像を読み込んで、各パーツに分割してウインドウ内に描画したい。考えてみたら、今までそういう処理は試してなかったな…。さて、どうすれば…。

環境は、Windows10 x64 21H1 + Python 3.9.5 64bit + pygame 2.0.1。

使用画像は以下。

_spritesheet_number.png

blit()を使う方法。 :

Pygame は、Surface.blit() を使うことで、Surface から Surface へと画像を転送することができる。この blit() に pygame.Rect という矩形範囲を渡すことで、元画像の任意の範囲だけを転送、ということができるらしい。

これを使えばスプライトシート画像の一部だけを抜き出して描画できるんじゃないかな…。ということで、試してみた。

_02_blit_mn.py
import pygame
import sys

SCRW, SCRH = 320, 240

pygame.init()
screen = pygame.display.set_mode((SCRW, SCRH), pygame.DOUBLEBUF)

imgname = "spritesheet_number.png"
img = pygame.image.load(imgname).convert_alpha()

# make split area list
rects = []
w, h = 96, 96
for y in range(8):
    for x in range(8):
        rects.append(pygame.Rect(x * w, y * h, w, h))

index = 0
running = True

clock = pygame.time.Clock()

# Main loop
while running:

    # check event
    for ev in pygame.event.get():
        if ev.type == pygame.QUIT:
            running = False
        if ev.type == pygame.KEYDOWN:
            if ev.key == pygame.K_ESCAPE or ev.key == pygame.K_q:
                # Push ESC or Q key
                running = False
                
    screen.fill((40, 60, 200))   # clear screen

    # draw image
    x = 160 - 96 / 2
    y = 120 - 96 / 2
    screen.blit(img, (x, y), area=rects[index])

    index = (index + 1) % len(rects)

    pygame.display.flip()
    clock.tick_busy_loop(60)
    
    cap = "Image Split - %5.2f FPS" % (clock.get_fps())
    pygame.display.set_caption(cap)

pygame.quit()
sys.exit()

pygame.Rect(x, y, width, height) で矩形範囲を指定できる。それを配列 rects に蓄えておいて…。スクリーンに相当する Surface、を格納している screen に blit() で描画する際に、area=rects[index] という形で渡して、「元画像の、この範囲だけを抜き出して描画せよ」的な処理をしている。

実行したら、こうなった。

02_blit_mn_ss01.gif

元画像の一部だけを描画できている。

ということで、blit() に pygame.Rect を渡せば、目的は果たせると分かった。

ちなみに、上記のスクリプトでは pygame.Rect() を使ってるけど、その後ググってみたら、blit(img, (px, py), (x, y, w, h)) という書き方もできると知った。

# make split area list
rects = []
w, h = 96, 96
for y in range(8):
    for x in range(8):
        rects.append((x * w, y * h, w, h))
# ...

    # draw image
    x = 160 - 96 / 2
    y = 120 - 96 / 2
    screen.blit(img, (x, y), rects[index])

処理速度で違いはあったりするのかな…。どうなんだろう。

subsurface() を使う方法。 :

Pygame の Surface には、subsurface() というメソッドがあって、コレを使うと、元画像の一部を新たな Surface として得ることができるらしい。引数として、やはり pygame.Rect を渡す模様。

ということで試してみた。

_03_subsurface.py
import pygame
import sys

SCRW, SCRH = 320, 240

pygame.init()
screen = pygame.display.set_mode((SCRW, SCRH), pygame.DOUBLEBUF)

imgname = "spritesheet_number.png"
img = pygame.image.load(imgname).convert_alpha()

# make subsurface
imgs = []
w, h = 96, 96
for y in range(8):
    for x in range(8):
        _rect = pygame.Rect(x * w, y * h, w, h)
        imgs.append(img.subsurface(_rect))

index = 0
running = True

clock = pygame.time.Clock()

# Main loop
while running:

    # check event
    for ev in pygame.event.get():
        if ev.type == pygame.QUIT:
            running = False
        if ev.type == pygame.KEYDOWN:
            if ev.key == pygame.K_ESCAPE or ev.key == pygame.K_q:
                # Push ESC or Q key
                running = False
                
    screen.fill((40, 60, 200))   # clear screen

    # draw image
    x = 160 - 96 / 2
    y = 120 - 96 / 2
    screen.blit(imgs[index], (x, y))

    index = (index + 1) % len(imgs)

    pygame.display.flip()
    clock.tick_busy_loop(60)
    
    cap = "Image Split - %5.2f FPS" % (clock.get_fps())
    pygame.display.set_caption(cap)

pygame.quit()
sys.exit()

Rect を配列に蓄える代わりに、subsurface を配列 imgs に蓄えている。また、screen に blit() で描画する際、元画像として subsurface を渡している。

実行したら、こうなった。

03_subsurface_ss01.gif

ということで、subsurface を使っても、元画像の一部を切り出した感じで描画できると分かった。

ただ、Surface のドキュメントを読むと、ハードウェア描画がどうのこうの、みたいなことが書いてあるような…。

_pygame.Surface - pygame v2.0.1.dev1 documentation

ディスプレイモードがハードウェア描画じゃない場合は、表示に使ってる Surface から subsurface を作ることもできる、と言ってるのかな…。逆に言うと、ハードウェア描画の場合は表示に使ってる Surface から subsurface を作れませんよ、ということだろうな…。

以上です。

過去ログ表示

Prev - 2021/10 -
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project