آشنایی با رنگ‌ها و تغییر رنگ پنجره در Pygame

Colors and Changing the Color of the Window in Pygame

Colors-and-Changing-the-Color-of-the-Window-in-Pygame

در این قسمت با رنگ ها آشنا می شویم. تمرکز این بخش بیشتر بر یاد گرفتن مفهوم رنگ ها است. در قسمت های بعدی سعی می کنیم که آموخته های خود در زمینه رنگ ها را با رسم اشکال و نوشتن کد آن ها کامل کنیم.

رنگ ها

رنگ های اصلی و ترکیب آن ها - توجه کنید که چگونه با ترکیب شدن رنگ های اصلی رنگ های جدید به وجود آمده اند.

سه رنگ اصلی در نور وجود دارد: قرمز، سبز و آبی یا RED BLUE GREEN. اگر اول نام این سه رنگ را کنار هم بگذاریم کلمه RGB را خواهیم داشت. قرمز، آبی و زرد سه رنگ اصلی هستند، ولی مانیتور از نور استفاده می کند، نه رنگ. برای حل این مشکل از مدل RGB استفاده می کنیم. این مدل برای نمایش رنگ ها در تلویزیون و مانیتور است. با ترکیب مقادیر مختلفی از این سه رنگ می توان هر رنگ دیگری را به وجود آورد.

در pygame، رنگ ها را با تاپل های سه تایی از اعداد صحیح نشان می دهیم. مقدار اول در تاپل مقداری عددی برای رنگ قرمز است. مقدار 0 به این معنی است که هیچ رنگی قرمزی وجود ندارد و مقدار 255 به معنی حداکثر رنگ قرمز است. مقدار دوم مربوط به سبز و مقدار سوم برای آبی است. به این سه عدد که برای نشان دادن یک رنگ استفاده می شوند، مقادیر RGB می گوییم.اگر سه مقدار صفر باشند رنگ سیاه به دست می آید. بالاتر از سیاهی رنگی نیست!

هر رنگی به عنوان عددی بین 0 (حداقل) و 255 (حداکثر) نشان داده می شود که 1 بایت را در حافظه اشغال می کند.بنابراین یک رنگ RGB به عنوان یک مقدار 3 بایت نشان داده می شود. از آن جا که می توان برای هر یک از سه رنگ اصلی از هر ترکیب 0 تا 255 استفاده کرد، این معنی را می دهد که Pygame می تواند 16,777,216 رنگ مختلف را تولید کند (یعنی 256*256*256 رنگ). با این حال، اگر از عددی بزرگ تر از 255 یا یک عدد منفی استفاده کنید، خطایی به صورت زیر دریافت خواهید کرد:

تاپل (0، 0 ، 0) که بدون هیچ مقدار قرمز، سبز یا آبی است، رنگ سیاه را نشان می دهد. رنگ سیاه یعنی وجود نداشتن رنگ های دیگر. تاپل (255 ، 255 ، 255) برای حداکثر مقدار قرمز، سبز و آبی است که رنگ سفید را تولید می کند. رنگ سفید ترکیب کاملی از قرمز، سبز و آبی است. تاپل (0 ، 0 ، 255) حداکثر مقدار قرمز، و حداقل مقدار سبز و آبی است، بنابراین رنگ حاصل از آن قرمز است. به همین ترتیب (0 ، 255 ، 0) به رنگ سبز و (255، 0 ، 0) آبی است.

می توانید مقدار رنگ قرمز، سبز و آبی را مخلوط کنید تا رنگ های دیگر را به وجود آورید. در این جا مقادیر RGB برای چند رنگ رایج آورده شده است:

مقادیر RGB برای رنگ ها

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

رنگ های RGB

تغییر رنگ پنجره

تغییر رنگ پنجره شاید ساده ترین کار با pyagme باشد.به برنامه قسمت قبل تنها دو خط کد جدید اضافه می کنیم تا بتوانیم رنگ پنجره را تغییر دهیم.

import pygame,sys
from pygame.locals import *
pygame.init()

# COLORS
RED=(255,0,0)

DISPLAYSURF=pygame.display.set_mode((400,300))
pygame.display.set_caption('Hello World!')

while True: # main game loop
    for event in pygame.event.get():
        if event.type==QUIT:
            pygame.quit()
            sys.exit()  
    DISPLAYSURF.fill(RED)
    pygame.display.update()


در برنامه بالا رنگ قرمز را با مقدار (255,0,0) تعریف کرده ایم و در ثابت RED قرار داده ایم. سپس برای نشان رنگ از متد fill استفاده کرده ایم. این متد در پایان هر تکرار حلقه، رنگ مورد نظر را روی پنجره رسم می کند. در واقع این متد همان طور که از نامش پیداست پنجره را با رنگ  تعریف شده پر می کند. با اجرای کد بالا پنجره ای قرمز رنگ به شکل زیر خواهیم داشت.

رنگ های شفاف

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

شیشه مات قرمز رنگ

در pygame برای داشتن رنگ شفاف یا transparent مانند تصویر بالا، باید به تاپل سه تایی RGB یک عدد چهارم که بین 0 تا 255 است، بیفزاییم. به این عدد چهارم مقدار آلفا می گویند. مقدار آلفا معیاری از میزان شفاف بودن یک رنگ است. اگر پیکسلی را با یک رنگ جدید معمولی رسم کنیم، این رنگ جدید رنگی را که قبلا در آن جا بوده است، کاملا جایگزین می کند. اما با رنگ های شفاف یعنی رنگ هایی که مقدار آلفا دارند، می توان یک رنگ پس زمینه ای را به رنگی که از قبل وجود داشته است اضافه کرد. مانند زیر:

تصویر با آلفای 127

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

import pygame

def draw_rect_alpha(surface, color, rect):
    shape_surf = pygame.Surface(pygame.Rect(rect).size, pygame.SRCALPHA)
    pygame.draw.rect(shape_surf, color, shape_surf.get_rect())
    surface.blit(shape_surf, rect)

def draw_circle_alpha(surface, color, center, radius):
    target_rect = pygame.Rect(center, (0, 0)).inflate((radius * 2, radius * 2))
    shape_surf = pygame.Surface(target_rect.size, pygame.SRCALPHA)
    pygame.draw.circle(shape_surf, color, (radius, radius), radius)
    surface.blit(shape_surf, target_rect)

def draw_polygon_alpha(surface, color, points):
    lx, ly = zip(*points)
    min_x, min_y, max_x, max_y = min(lx), min(ly), max(lx), max(ly)
    target_rect = pygame.Rect(min_x, min_y, max_x - min_x, max_y - min_y)
    shape_surf = pygame.Surface(target_rect.size, pygame.SRCALPHA)
    pygame.draw.polygon(shape_surf, color, [(x - min_x, y - min_y) for x, y in points])
    surface.blit(shape_surf, target_rect)

pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()

background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 50, *window.get_size(), (160, 160, 160), (192, 192, 192)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
for rect, color in tiles:
    pygame.draw.rect(background, color, rect)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.blit(background, (0, 0))

    draw_rect_alpha(window, (0, 0, 255, 127), (55, 90, 140, 140))
    draw_circle_alpha(window, (255, 0, 0, 127), (150, 100), 80)
    draw_polygon_alpha(window, (255, 255, 0, 127), 
        [(100, 10), (100 + 0.8660 * 90, 145), (100 - 0.8660 * 90, 145)])

    pygame.display.flip()

pygame.quit()
exit()

در تصویر بالا، رنگ قرمز دارای مقدار (255,0,0,127) است. با اضافه کردن مقدار آلفا توانسته ایم آن را به یک رنگ قرمز نیمه شفاف تبدیل کنیم. این کار را برای رنگ زرد و آبی هم کرده ایم.

اگر مقدار آلفا 255 باشد آنگاه رنگی که خواهیم داشت کاملا تیره خواهد بود (یعنی اصلا شفاف نیست). رنگ های (0 ، 255 ، 0) و (255, 0, 255, 0) کاملا یکسان هستند و یک میزان از تیرگی رنگ را نشان می دهند (آموزش رسم تصویر بالا بالا با رنگ های شفاف را در قسمت رسم اشکال آموزش خواهم داد، در این قسمت فعلا با رنگ ها و مفهوم آن ها آشنا می شویم).

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

تصویر با آلفای 255

اگر مقدار آلفا 0 باشد یعنی رنگ کاملا شفاف است. اگر هر رنگی را که مقدار آلفای آن 0 است رسم کنید، هیچ رنگی نمایش داده نخواهد شد، زیرا این رنگ کاملا شفاف و نامرئی است.

اگر تصویر بالا را با آلفای 0 بکشیم خواهیم داشت:

تصویر با آلفای 0

استفاده از رنگ های شفاف

pygame برای استفاده از رنگ های شفاف سه روش دارد:

  1. کلیدهای رنگی (colorkeys)
  2. آلفای سطح (surface's alphas)
  3. آلفا به ازای هر پیکسل (per-pixel alphas)

colorkey (کلیدهای رنگی)

این روش رنگ را کاملا شفاف یا به عبارت دقیق تر ناپدید می سازد. به عنوان نمونه در تصویر زیر یک مربع مشکی با حاشیه قرمز رنگ داریم. با colorkey می توانیم کاری کنیم که قسمت سیاه مربع نشان داده نشود و فقط حاشیه قرمز را رنگ داشته باشیم.

BLACK = (0, 0, 0)
square.set_colorkey(BLACK)  # Black colors will not be blit.

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

آلفای سطح (surface's alphas)

این روش کل سطح را با مقدار آلفا شفاف می کند. با استفاده از این روش می توانیم مقادیر مختلف آلفا داشته باشیم. باید توجه داشته باشیم که این روش روی کل سطح تاثیر می گذارد.

my_image.set_alpha(100)  # 0 is fully transparent and 255 fully opaque.

آلفا به ازای هر پیکسل (per-pixel alphas)

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

size = width 
height = (32, 32)
my_image = pygame.Surface(size, pygame.SRCALPHA)  # Creates an empty per-pixel alpha Surface.

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

BLUE = (0, 0, 255, 255)
pygame.draw.rect(my_image, BLUE, my_image.get_rect(), 10)

برخلاف دو روش پیشین ، رنگ پیش فرض سطح سیاه نیست و شفاف خواهد بود. به همین دلیل مستطیل سیاه ناپدید می شود.

روش های colorkey و آلفای سطح می توانند با هم ترکیب شوند ولی روش آلفا به ازای هر پیکسل باید به تنهایی به کار برده شود.

کد کامل استفاده از هر سه روش بالا در زیر آمده است (در قسمت رسم اشکال توضیح داده خواهد شد.)

import pygame
pygame.init()

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255, 50)  # This color contains an extra integer. It's the alpha value.
PURPLE = (255, 0, 255)

screen = pygame.display.set_mode((200, 325))
screen.fill(WHITE)  # Make the background white. Remember that the screen is a Surface!
clock = pygame.time.Clock()

size = (50, 50)
red_image = pygame.Surface(size)
green_image = pygame.Surface(size)
blue_image = pygame.Surface(size, pygame.SRCALPHA)  # Contains a flag telling pygame that the Surface is per-pixel alpha
purple_image = pygame.Surface(size)

red_image.set_colorkey(BLACK)
green_image.set_alpha(50)
# For the 'blue_image' it's the alpha value of the color that's been drawn to each pixel that determines transparency.
purple_image.set_colorkey(BLACK)
purple_image.set_alpha(50)

pygame.draw.rect(red_image, RED, red_image.get_rect(), 10)
pygame.draw.rect(green_image, GREEN, green_image.get_rect(), 10)
pygame.draw.rect(blue_image, BLUE, blue_image.get_rect(), 10)
pygame.draw.rect(purple_image, PURPLE, purple_image.get_rect(), 10)

while True:
    clock.tick(60)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_1:
                screen.blit(red_image, (75, 25))
            elif event.key == pygame.K_2:
                screen.blit(green_image, (75, 100))
            elif event.key == pygame.K_3:
                screen.blit(blue_image, (75, 175))
            elif event.key == pygame.K_4:
                screen.blit(purple_image, (75, 250))

    pygame.display.update()

پس از اجرای کد بالا با زدن دکمه های 1 ,2, 3 و 4 مربع ها رسم خواهند شد.

شی های pygame.Color

باید بدانید که چگونه یک رنگ را نشان دهید زیرا توابع رسم pygame برای رسم کردن به رنگ نیاز دارند. راه اول یک تاپل از سه یا چهار عدد است. راه دیگر استفاده از یک شی pygame.Color است. می توانید با فراخوانی تابع سازنده pygame.Color  و فرستادن دادن سه یا چهار عدد به آن اشیا color را بسازید. می توانید شی Color را در متغیرها ذخیره کنید. کدهای زیر را در پوسته پایتون یا در خط فرمان پایتون تایپ کنید تا بهتر با متوجه نوشته شوید:

>>> import pygame
>>> pygame.Color(255, 0, 0)
(255, 0, 0, 255)
>>> myColor = pygame.Color(255, 0, 0, 128)
>>> myColor == (255, 0, 0, 128)
True
>>>

در برنامه های خود از روش اول یعنی استفاده از تاپل ها استفاده می کنیم.


هدف از آوردن دو قسمت زیر هیجان زده کردن شما برای ادامه آموزش است! کار با کیبورد و موس را در قسمت های بعدی به طور مفصل یاد می گیریم.

تغییر رنگ پشت زمینه با زدن دکمه ها

کد زیر را در ویرایشگر کد خود بنویسید و اجرا کنید. پس از اجرا شدن اگر دکمه R را بزنید پشت زمینه قرمز و اگر دکمه G را بزنید پشت زمینه سبز می شود.

import pygame
from pygame.locals import *

BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

YELLOW = (255, 255, 0)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
GRAY = (127, 127, 127)
WHITE = (255, 255, 255)

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

running = True
background = GRAY
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_r:
                background = RED
            elif event.key == pygame.K_g:
                background = GREEN

    screen.fill(background)
    pygame.display.flip()

pygame.quit()

تغییر نام پنجره و رنگ آن با زدن دکمه ها

کد زیر را در ویرایشگر کد خود بنویسید و اجرا کنید. در این برنامه علاوه تغییر رنگ پشت زمینه نام پنجره هم تغییر می کند. پس از اجرا شدن اگر دکمه R را بزنید پشت زمینه قرمز و اگر دکمه G را بزنید پشت زمینه سبز و اگر دکمه B را بزنید پشت زمینه آبی و بالاخره  اگر دکمه K را بزنید پشت زمینه سیاه می شود.

import pygame
from pygame.locals import *

BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

YELLOW = (255, 255, 0)
CYAN = (0, 255, 255)
MAGENTA = (255, 0, 255)
GRAY = (127, 127, 127)
WHITE = (255, 255, 255)

key_dict = {K_k:BLACK, K_r:RED, K_g:GREEN, K_b:BLUE, 
    K_y:YELLOW, K_c:CYAN, K_m:MAGENTA, K_w:WHITE}

print(key_dict)

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

running = True
background = GRAY
while running:
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        if event.type == KEYDOWN:
            if event.key in key_dict:
                background = key_dict[event.key]
                
                caption = 'background color = ' + str(background)
                pygame.display.set_caption(caption)

    screen.fill(background)
    pygame.display.update()

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

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