رسم اشکال در Pygame - قسمت دوم

How to Draw Shapes in Pygame? Part 2

How-to-Draw-Shapes-in-Pygame-Part-2

پیش گفتار

در این قسمت از آموزش می خواهیم یاد بگیریم که چگونه با موس شکل های گوناگون بکشیم. در ابتدا بیایید با آشکاری سازی موس آشنا شویم. (در قسمت کار با موس به طور کامل با موس و کارهایی که می تواند بکند آشنا می شویم. )

آشکاری سازی موس

فشار دادن دکمه های موس، رویدادهای MOUSEBUTTONDOWN و MOUSEBUTTONUP را تولید می شود. کد زیر آن ها را در حلقه رویداد شناسایی کرده و نام رویدادها را در کنسول می نویسد:

for event in pygame. event. get():
    if event. type == QUIT:
        running = False
    elif event. type == MOUSEBUTTONDOWN:
        print(event)
    elif event. type == MOUSEBUTTONUP:
        print(event)

با فشار دادن دکمه های موس رویدادهای زیر ایجاد می شوند:

<Event(5-MouseButtonDown {'pos': (123, 88), 'button': 1, 'window': None})>
<Event(6-MouseButtonUp {'pos': (402, 128), 'button': 1, 'window': None})>
<Event(5-MouseButtonDown {'pos': (402, 128), 'button': 3, 'window': None})>
<Event(6-MouseButtonUp {'pos': (189, 62), 'button': 3, 'window': None})>

حرکت موس باعث ایجاد یک رویداد MOUSEMOTION می شود. کد زیر آن ها را تشخیص می دهد و نام رویداد را در کنسول می نویسد:

elif event. type == MOUSEMOTION:
    print(event)

رسم مستطیل با حرکت موس

می توانیم از رویدادهای موس برای رسم مستطیل روی صفحه استفاده کنیم. برای رسم مستطیل دو نقطه برای آن در نظر می گیریم. نقطه ای که موس را روی صفحه گذاشته و رسم با موس را از آن شروع می کنیم و نقطه پایان رسم مستطیل. برای این که بفهمیم دکمه موس در حال فشار داده شدن است یا نه به یک فلگ (پرچم) نیاز داریم. این فلگ هم چنین نشان دهنده این است که آیا در حال رسم هستیم یا نه. (با هر سه دکمه موس می توانیم رسم کنیم).

start = (0, 0)
size = (0, 0)
drawing = False

هنگامی که موس فشرده می شود، start و end را با موقعیت فعلی موس تنظیم می کنیم و با True کردن فلگ drawing نشان می دهیم که موس در حال کشیدن شکل است:

elif event. type == MOUSEBUTTONDOWN:
    start = event. pos
    size = 0, 0
    drawing = True

وقتی دکمه موس آزاد شد، نقطه پایان را تنظیم می کنیم و با فلگ نشان می دهیم که رسم کردن به پایان رسیده است:

elif event. type == MOUSEBUTTONUP:
    end = event. pos
    size = end[0] - start[0], end[1] - start[1]
    drawing = False

وقتی که موس در حال حرکت است، باید بررسی کنیم که آیا در حالت رسم یا drawing هستیم یا نه. اگر این طور بود، آخرین جایی که موس در آن بوده است را با موقعیت فعلی موس مقداردهی می کنیم:

elif event. type == MOUSEMOTION and drawing:
    end = event. pos
    size = end[0] - start[0], end[1] - start[1]

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

screen. fill(GRAY)
pygame. draw. rect(screen, RED, (start, size), 2)
pygame. display. update()

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

"""Place a rectangle with the mouse. """

import pygame
from pygame. locals import *

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

pygame. init()
screen = pygame. display. set_mode((640, 240))

start = (0, 0)
size = (0, 0)
drawing = False
running = True

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

        elif event. type == MOUSEBUTTONDOWN:
            start = event. pos
            size = 0, 0
            drawing = True
            
        elif event. type == MOUSEBUTTONUP:
            end = event. pos
            size = end[0] - start[0], end[1] - start[1]
            drawing = False

        elif event. type == MOUSEMOTION and drawing:
            end = event. pos
            size = end[0] - start[0], end[1] - start[1]

    screen. fill(GRAY)
    pygame. draw. rect(screen, RED, (start, size), 2)
    pygame. display. update()

pygame. quit()

اگر کد بالا را اجرا کنید و سعی کنید با فشردن و حرکت دادن موس مستطیل را رسم کنید، شکل زیر را خواهید داشت:

رسم چندین مستطیل با موس

برای ترسیم چندین شکل، باید شکل ها را در یک آرایه(لیست) قرار دهیم. علاوه بر متغیرهای start ،end و drawing که در گذشته داشتیم، آرایه rect_list را نیز تعریف می کنیم:

start = (0, 0)
size = (0, 0)
drawing = False
rect_list = []

وقتی کشیدن یک شی (مستطیل، دایره و غیره) انجام می شود، یک شی rect ایجاد می کنیم و آن را به لیست rect_list اضافه می کنیم:

elif event. type == MOUSEBUTTONUP:
    end = event. pos
    size = end[0]-start[0], end[1]-start[1]
    rect = pygame. Rect(start, size)
    rect_list. append(rect)
    drawing = False

در کد زیر، ابتدا پشت زمینه را رنگ می کنیم، سپس با اجرای حلقه در آرایه rect_list اشیا را ترسیم کنیم (قرمز، ضخامت = 3). در آخر مستطیل فعلی را که در مرحله کشیده شدن است، رسم می کنیم (آبی، ضخامت = 1):

screen. fill(GRAY)
for rect in rect_list:
    pygame. draw. rect(screen, RED, rect, 3)
pygame. draw. rect(screen, BLUE, (start, size), 1)
pygame. display. update()

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

"""Place multiple rectangles with the mouse. """

import pygame
from pygame. locals import *

RED = (255, 0, 0)
BLUE = (0, 0, 255)
GRAY = (127, 127, 127)

pygame. init()
screen = pygame. display. set_mode((640, 240))

start = (0, 0)
size = (0, 0)
drawing = False
rect_list = []

running = True

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

        elif event. type == MOUSEBUTTONDOWN:
            start = event. pos
            size = 0, 0
            drawing = True
            
        elif event. type == MOUSEBUTTONUP:
            end = event. pos
            size = end[0]-start[0], end[1]-start[1]
            rect = pygame. Rect(start, size)
            rect_list. append(rect)
            drawing = False

        elif event. type == MOUSEMOTION and drawing:
            end = event. pos
            size = end[0]-start[0], end[1]-start[1]

    screen. fill(GRAY)
    for rect in rect_list:
        pygame. draw. rect(screen, RED, rect, 3)
    pygame. draw. rect(screen, BLUE, (start, size), 1)
    pygame. display. update()

pygame. quit()

اگر کد بالا را اجرا کنید و سعی کنید با فشردن و حرکت موس مستطیل را رسم کنید شکل زیر را خواهید داشت:

رسم چندضلعی با موس

برای کشیدن چند ضلعی باید همه نقطه ها را به آرایه ای از نقاط اضافه کنیم. ابتدا یک آرایه به نام points و یک فلگ(پرچم) drawing تعریف می کنیم:

drawing = False
points = []

در کد زیر که برای مدیریت رویداد MOUSEBUTTONDOWN است نقطه فعلی را به آرایه اضافه می کنیم و فلگ drawing را روی True تنظیم می کنیم:

elif event. type == MOUSEBUTTONDOWN:
    points. append(event. pos)
    drawing = True

در هنگام رخ دادن رویداد MOUSEBUTTONUP  فلگ drawing را غیرفعال می کنیم:

elif event. type == MOUSEBUTTONUP:
    drawing = False

اگر فلگ تنظیم شده باشد، و رویداد MOUSEMOTION رخ داده باشد، آخرین نقطه را از لیست چند ضلعی حرکت می دهیم:

elif event. type == MOUSEMOTION and drawing:
    points[-1] = event. pos

اگر بیش از 2 نقطه در آرایه points وجود داشته باشد، یک خط حاشیه ای سبز رنگ برای چند ضلعی رسم می کنیم. چند ضلعی درون این خط رسم می شود. فراخوانی تابع pygame. draw یک Rect یا مستطیل محاط را برای چند ضلعی برمی گرداند. این مستطیل چند ضلعی را در بر می گیرد. این مستطیل را به رنگ سبز نمایش می دهیم.

screen. fill(GRAY)
if len(points)>1:
    rect = pygame. draw. lines(screen, RED, True, points, 3)
    pygame. draw. rect(screen, GREEN, rect, 1)
pygame. display. update()

با فشار دادن کلید ESCAPE آخرین نقطه در آرایه حذف می شود:

elif event. type == KEYDOWN:
    if event. key == K_ESCAPE:
        if len(points) > 0:
            points. pop()

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

"""Place a polygone line with the clicks of the mouse. """

import pygame
from pygame. locals import *

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

pygame. init()
screen = pygame. display. set_mode((640, 240))

drawing = False
points = []
running = True

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

        elif event. type == KEYDOWN:
            if event. key == K_ESCAPE:
                if len(points) > 0:
                    points. pop()

        elif event. type == MOUSEBUTTONDOWN:
            points. append(event. pos)
            drawing = True

        elif event. type == MOUSEBUTTONUP:
            drawing = False

        elif event. type == MOUSEMOTION and drawing:
            points[-1] = event. pos
    
    screen. fill(GRAY)
    if len(points)>1:
        rect = pygame. draw. lines(screen, RED, True, points, 3)
        pygame. draw. rect(screen, GREEN, rect, 1)
    pygame. display. update()

pygame. quit()

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

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری بازی‌سازی با پایتون توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

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