کار با تصاویر و صداها در Pygame

Working with Images and Sounds in Pygame

InShot_۲۰۲۱۱۰۲۱_۱۵۵۲۲۴۱۲۹[1]

پیش گفتار

در این قسمت با تصاویر و صداها آشنا می شویم و یاد می گیریم که چگونه از آن ها در برنامه استفاده کنیم. هم چنین یاد می گیریم که چگونه تصویر را با موس حرکت دهیم و آن را کوچک و بزرگ بکنیم. همه این کارها را با متدهای pygame انجام می دهیم. پس بیاید زودتر کار را شروع کنیم.

بارگذاری (load) کردن عکس

با استفاده از ماژول pyagme. image می توان تصاویر را بارگذاری و ذخیره کرد. متد load تصویری را از سیستم فایل بارگیری می کند و یک شی Surface را برمی گرداند. متد convert فرمت تصویر را بهینه می کند و کشیدن تصویر را سریع تر می کند:

img = pygame. image. load('bird. png')
img. convert()

تصویری که از آن استفاده می کنیم باید در همان پوشه ای باشد که برنامه در آن قرار دارد. متد ()get_rect  یک شی Rect را از یک تصویر برمی گرداند. در مثال زیر فقط اندازه تنظیم می شود و موقعیت تصویر در (0 ، 0) قرار می گیرد. در خط دوم مرکز Rect را به مرکز صفحه تنظیم می کنیم:

rect = img. get_rect()
rect. center = w//2, h//2

برای کار با تصاویر از 3 شی استفاده می کنیم:
شی screen :این شی یک شی Surface است که نمایان گر پنجره برنامه است.
شی img : یک شی Surfaceاست  که برای نمایش تصویر به کار می رود.
شی rect : یک شی Rect است. این شی یک مستطیل دربرگیرنده تصویر است. (چون تصاویر ممکن است دارای گوشه های صاف نباشند و درواقع اشکال پیچیده ای داشته باشند آن را درون یک مستطیل محاط یا دربرگیرنده قرار می دهیم.)

پشت زمینه را خاکستری رنگ می کنیم. سپس تصویر را در پنجره می کشیم ، و یک مستطیل قرمز دور آن رسم می کنیم و در نهایت صفحه را با update به روز می کنیم تا همه تغییر ها نمایش داده شوند :

screen. fill(GRAY)
screen. blit(img, rect)
pygame. draw. rect(screen, RED, rect, 1)
pygame. display. update()

کد کامل برای نمایش تصویر در زیر آمده است :

import pygame
from pygame. locals import *

RED = (255, 0, 0)
GRAY = (150, 150, 150)

pygame. init()
w, h = 640, 300
screen = pygame. display. set_mode((w, h))
running = True

img = pygame. image. load('bird. png')
img. convert()
rect = img. get_rect()
rect. center = w//2, h//2

while running:
    for event in pygame. event. get():
        if event. type == QUIT:
            running = False
    
    screen. fill(GRAY)
    screen. blit(img, rect)
    pygame. draw. rect(screen, RED, rect, 1)
    pygame. display. update()

pygame. quit()


با اجرای کد بالا تصویر زیر نمایش داده می شود:

تصویر بالا را می توانید از لینک دانلود کنید.

حرکت تصویر با موس

در ابتدای برنامه یک متغیر بولین را با نام moving تعریف می کنیم. اگر دکمه موس فشار داده شود و موس در داخل تصویر قرار بگیرد، آن را True می کنیم:

elif event. type == MOUSEBUTTONDOWN:
    if rect. collidepoint(event. pos):
moving = True

اگر دکمه موس رها شود ، دوباره moving را False می کنیم:

elif event. type == MOUSEBUTTONUP:
    moving = False

هنگامی که موس حرکت می کند ، و moving درست(True) است ، آن گاه تصویر را با توجه به میزان حرکت نسبی (event. rel) حرکت می دهیم:

elif event. type == MOUSEMOTION and moving:
    rect. move_ip(event. rel)

تصویر زیر را حرکت می دهیم:

کد کامل در زیر آمده است:

"""Move an image with the mouse. """

import pygame
from pygame. locals import *

RED = (255, 0, 0)
GRAY = (150, 150, 150)

pygame. init()
w, h = 640, 240
screen = pygame. display. set_mode((w, h))
running = True

img = pygame. image. load('bird. png')
img. convert()
rect = img. get_rect()
rect. center = w//2, h//2
moving = False

while running:
    for event in pygame. event. get():
        if event. type == QUIT:
            running = False

        elif event. type == MOUSEBUTTONDOWN:
            if rect. collidepoint(event. pos):
                moving = True

        elif event. type == MOUSEBUTTONUP:
            moving = False

        elif event. type == MOUSEMOTION and moving:
            rect. move_ip(event. rel)
    
    screen. fill(GRAY)
    screen. blit(img, rect)
    pygame. draw. rect(screen, RED, rect, 1)
    pygame. display. update()

pygame. quit()


چرخاندن و تغییر اندازه تصویر

ماژول pygame. transform روش هایی را برای تغییر اندازه ، چرخش تصاویر فراهم می کند. برای اصلاح تصویر img ، تصویر اصلی را در متغیری به نام img0 ذخیره می کنیم:

img0 = pygame. image. load(path)
img0. convert()

برای نشان دادن تصویر مستطیل ، یک حاشیه(border) سبز به تصویر اصلی اضافه می کنیم:

rect0 = img0. get_rect()
pygame. draw. rect(img0, GREEN, rect0, 1)

سپس تصویر را در مرکز صفحه نمایش قرار می دهیم:

center = w//2, h//2
img = img0
rect = img. get_rect()
rect. center = center

در نخست متغییرهای global(سراسری) scale و angle را تعریف می کنیم:

angle = 0
scale = 1

از کلید R برای افزایش 10 درجه ای چرخش تصویر استفاده می کنیم. در صورت فشار دادن کلید SHIFT درجه چرخش کاهش می یابد. با تابع ()rotozoom می توان از چرخش و تغییر اندازه با هم استفاده کرد. ما همیشه تصویر اصلی را تغییر می دهیم (img0). چرخش یا تغییر اندازه زیاد تصویر کیفیت آن را پایین می آورد:

if event. type == KEYDOWN:
    if event. key == K_r:
        if event. mod & KMOD_SHIFT:
            angle -= 10
        else:
            angle += 10
        img = pygame. transform. rotozoom(img0, angle, scale)

از کلید S برای افزایش میزان تغییر اندازه استفاده می کنیم. با هر بار فشار دادن کلید S ده درصد افزایش اندازه خواهیم داشت. در صورت فشار دادن کلید SHIFT میزان تغییر اندازه کاهش می یابد.

elif event. key == K_s:
    if event. mod & KMOD_SHIFT:
        scale /= 1. 1
    else:
        scale *= 1. 1
    img = pygame. transform. rotozoom(img0, angle, scale)

همان طور که تصویر تغییر شکل می دهد ، مستطیل دربرگیرنده(محاط کننده) نیز اندازه اش تغییر می کند. تصویر دوباره در مرکز قرار می گیرد:

rect = img. get_rect()
rect. center = center

برگرداندن تصویر به حالت اولیه

برای برگرداندن تصویر به حالت اولیه خود از کلید O استفاده می کنیم:

elif event. key == K_o:
    img = img0
    angle = 0
    scale = 1

چرخاندن تصویر

برای چرخاندن تصویر به طور افقی از کلید H استفاده می کنیم:

elif event. key == K_h:
    img = pygame. transform. flip(img, True, False)

و از کلید H برای چرخاندن تصویر به طور عمودی استفاده می کنیم:

elif event. key == K_v:
    img = pygame. transform. flip(img, False, True)

تشخیص لبه های تصویر با Laplacian

تابع laplacian به ما کمک می کند تا لبه های یک تصویر را شناسایی بکنیم:

elif event. key == K_l:
    img = pygame. transform. laplacian(img)

تصویر در زیر آمده است :

تابع scale2x اندازه یک پیکسل را دو برابر می کند:

elif event. key == K_2:
    img = pygame. transform. scale2x(img)

تغییر شکل تصویر با موس

در این بخش روش استفاده از موس برای تغییر اندازه و چرخش یک تصویر را نشان می دهیم. در ابتدا ماژول math را وارد می کنیم:

import math

در آغاز موقعیت اولیه موس را ذخیره می کنیم:

mouse = pygame. mouse. get_pos()

هنگامی که موس حرکت می کند موقعیت موس را update می کنیم و مختصات x، y را نسبت به مرکز تصویر محاسبه می کنیم. ما همچنین فاصله موس تا مرکز یعنی d را به دست می آوریم:

elif event. type == MOUSEMOTION:
    mouse = event. pos
    x = mouse[0] - center[0]
    y = mouse[1] - center[1]
    d = math. sqrt(x ** 2 + y ** 2)

تابع ریاضی atan2(y ، x) اجازه می دهد تا زاویه چرخش را به دست آوریم. برای استفاده از این تابع باید رادیان را به درجه تبدیل کنیم. با استفاده از d  اندازه scale را محاسبه می کنیم:

angle = math. degrees(-math. atan2(y, x))
scale = abs(5 * d / w)
img = pygame. transform. rotozoom(img0, angle, scale)
rect = img. get_rect()
rect. center = center

در نهایت برای رسم تصویر تغییر شکل یافته ، ابتدا پس زمینه را با رنگ دلخواه(خاکستری) رنگ می کنیم،سپس تصویر تغییر شکل یافته را در پنجره می کشیم و دور آن با یک مستطیل قرمز رنگ می کشیم. برای ایجاد جلوه های دیداری در هنگام برای تغییر شکل تصویر با موس دو کار زیر را انجام می دهیم:
• یک خط سبز بین مرکز تصویر و موقعیت موس می کشیم.
• دو دایره یکی در مرکز تصویر و دیگری را در موقعیت موس قرار می دهیم.

به تصویری که در زیر آمده است به دقت نگاه کنید.

screen. fill(GRAY)
screen. blit(img, rect)
pygame. draw. rect(screen, RED, rect, 1)
pygame. draw. line(screen, GREEN, center, mouse, 1)
pygame. draw. circle(screen, RED, center, 6, 1)
pygame. draw. circle(screen, RED, mouse, 6, 1)
pygame. display. update()

کد کامل آموزش های بالا در زیر آمده است.

"""Rotate, scale and flip an image. """

import pygame
import math, sys, os
from pygame. locals import *

RED = (255, 0, 0)
GREEN = (0, 255, 0)
GRAY = (150, 150, 150)

pygame. init()
w, h = 640, 240
screen = pygame. display. set_mode((w, h))
running = True

module = sys. modules['__main__']
path, name = os. path. split(module. __file__)
path = os. path. join(path, 'bird. png')

img0 = pygame. image. load(path)
img0. convert()

# draw a green border around img0
rect0 = img0. get_rect()
pygame. draw. rect(img0, GREEN, rect0, 1)

center = w//2, h//2
img = img0
rect = img. get_rect()
rect. center = center

angle = 0
scale = 1

mouse = pygame. mouse. get_pos()

while running:
    for event in pygame. event. get():
        if event. type == QUIT:
            running = False

        if event. type == KEYDOWN:
            if event. key == K_r:
                if event. mod & KMOD_SHIFT:
                    angle -= 10
                else:
                    angle += 10
                img = pygame. transform. rotozoom(img0, angle, scale)

            elif event. key == K_s:
                if event. mod & KMOD_SHIFT:
                    scale /= 1. 1
                else:
                    scale *= 1. 1
                img = pygame. transform. rotozoom(img0, angle, scale)

            elif event. key == K_o:
                img = img0
                angle = 0
                scale = 1

            elif event. key == K_h:
                img = pygame. transform. flip(img, True, False)
            
            elif event. key == K_v:
                img = pygame. transform. flip(img, False, True)

            elif event. key == K_l:
                img = pygame. transform. laplacian(img)

            elif event. key == K_2:
                img = pygame. transform. scale2x(img)

            rect = img. get_rect()
            rect. center = center

        elif event. type == MOUSEMOTION:
            mouse = event. pos
            x = mouse[0] - center[0]
            y = mouse[1] - center[1]
            d = math. sqrt(x ** 2 + y ** 2)

            angle = math. degrees(-math. atan2(y, x))
            scale = abs(5 * d / w)
            img = pygame. transform. rotozoom(img0, angle, scale)
            rect = img. get_rect()
            rect. center = center
    
    screen. fill(GRAY)
    screen. blit(img, rect)
    pygame. draw. rect(screen, RED, rect, 1)
    pygame. draw. line(screen, GREEN, center, mouse, 1)
    pygame. draw. circle(screen, RED, center, 6, 1)
    pygame. draw. circle(screen, RED, mouse, 6, 1)
    pygame. display. update()

pygame. quit()

کد بالا را می توانید از لینک دانلود کنید.

کار کردن با صداها

پخش فایل های صوتی حتی ساده تر از نمایش تصاویر است. ابتدا باید با فراخوانی تابع pygame. mixer. Sound یک شی pygame. mixer. Sound ایجاد کنیم. ماژول pygame. mixer امکان پخش فایل های OGG فشرده یا فایل های WAV فشرده نشده را فراهم می کند. این ماژول پارامترهای initialization را بررسی می کند و تعداد کانال های موجود را نمایش می دهد. این ماژول یک شی sound را باز می کند:

 

print('init =', pygame. mixer. get_init())
print('channels =', pygame. mixer. get_num_channels())
App. snd = pygame. mixer. Sound('5_app/rpgaudio. ogg')
App. snd. play()
print('length =', App. snd. get_length())

کد زیر را در کنسول بنویسید:

init = (22050, -16, 2)
channels = 8
length = 28. 437868118286133

کد کامل در زیر آمده است:

"""Play a sound. """
from app import *

class Demo(App):
    def __init__(self):
        super(). __init__()
        
        print('init =', pygame. mixer. get_init())
        print('channels =', pygame. mixer. get_num_channels())
        App. snd = pygame. mixer. Sound('5_app/rpgaudio. ogg')
        App. snd. play()
        print('length =', App. snd. get_length())

        Scene(caption='Sound mixer')
        Button('Stop', cmd='pygame. mixer. stop()')
        Button('Pause', cmd='pygame. mixer. pause()')
        Button('Unpause', cmd='pygame. mixer. unpause()')
        Button('Fadeout', cmd='pygame. mixer. fadeout(5000)')
        Button('Play', cmd='App. snd. play()')
        Button('Volume 0. 1', cmd='App. snd. set_volume(0. 1)', pos=(200, 20))
        Button('Volume 0. 3', cmd='App. snd. set_volume(0. 3)')
        Button('Volume 1. 0', cmd='App. snd. set_volume(1. 0)')

if __name__ == '__main__':
    Demo(). run()

برای پخش صدا ، از متد  play و برای توقف آن از متد stop استفاده کنید. متد stop هیچ پارامتری نمی گیرد. در اینجا کد نمونه ای وجود دارد :

soundObj = pygame. mixer. Sound('beeps. wav')

soundObj. play()

import time

time. sleep(1) # wait and let the sound play for 1 second

soundObj. stop()

فایل beeps. wav را می توانید از سایت http://invpy. com/beeps. wav  بارگیری کنید. اشیا Sound برای پخش جلوه های صوتی مانند وقتی که بازیکن آسیب می بیند ، شمشیر را می کشد، یا سکه جمع می کند و کارهای دیگر مناسب هستند. Pygame فقط می تواند یک فایل موسیقی را در هر زمان استفاده کند. برای استفاده از یک فایل موسیقی که در پس زمینه بازی اجرا می شود، تابع pygame. mixer. music. load را فراخوانی کنید و نام فایل صوتی را به آن بفرستید. این فایل می تواند با فرمت WAV ، MP3 یا MIDI باشد. برای شروع پخش فایل صوتی بارگذاری شده به عنوان موسیقی پس زمینه ، تابع pygame. mixer. music. play(-1, 0. 0)  را فراخوانی کنید. آرگومان 1- باعث می شود که موسیقی پس زمینه برای همیشه اجرا شود. اگر آن را 0 یا بیش تر بدهیم ، آن وقت موسیقی به جای اجرای شدن به صورت حلقه ای ، به تعداد دفعات تنظیم شده اجرا می شود.

0. 0 به معنای پخش فایل صوتی از ابتدا است. اگر از یک عدد صحیح بزرگتر از صفر یا یک عدد اعشاری استفاده کنیم ،موسیقی به اندازه عدد داده شده پخش می شود و سپس دوباره از اول پخش می شود. مثلا اگر پارامتر دوم 13. 5 باشد، فایل صوتی پس از 13. 5 ثانیه پخش شدن ، دوباره از اول پخش می شودبرای متوقف کردن فوری موسیقی که در پس زمینه بازی اجرا می شود، تابع pygame. mixer. music. stop را فراخوانی کنید. این تابع هیچ آرگومانی ندارد. در این جا نمونه ای از کد متد ها و تابع های صوتی آورده شده است :

# Loading and playing a sound effect:

soundObj = pygame. mixer. Sound('beepingsound. wav')

soundObj. play()

# Loading and playing background music:

pygame. mixer. music. load(backgroundmusic. mp3')

pygame. mixer. music. play(-1, 0. 0)

# . . . some more of your code goes here. . . 

pygame. mixer. music. stop()
تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری بازی‌سازی با پایتون توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.