ב.4 — משטחים, שכבות וצבעים

עד כה החלון שלנו נשאר ריק. כדי שמשחק ייראה כמו משחק צריך לצייר בו: רקע, לוח ניקוד בחלק העליון, דמויות שזזות. בפרקים הקודמים הזכרנו שכל ציור נעשה על "משטח התצוגה" — הגיע הזמן להסביר מהו משטח — Surface, מושג היסוד של הגרפיקה ב־Pygame.

אפשר לחשוב על משטח כעל דף ציור מלבני בזיכרון. מציירים עליו, צובעים אותו או מעתיקים אליו תוכן ממשטח אחר. החלון עצמו מציג משטח מיוחד — משטח התצוגה. משטחים נוספים מאפשרים להרכיב תמונה מכמה חלקים, למשל אזור כותרת ואזור תוכן. במשחק טיפוסי, כל תמונה של דמות היא משטח בפני עצמו, ובכל פריים מעתיקים אותה למקומה הנוכחי על משטח התצוגה — כמו הדבקת גזירי נייר על דף גדול.

בפרק זה ניצור משטחים, נמלא אותם בצבע ונרכיב מהם תצוגה. בפרקים הבאים נצייר על המשטחים צורות ונטען אליהם תמונות.

המצגת: מבוא ל־Pygame (עותק מקומי)

משטח התצוגה ומשטחים נוספים

נתחיל בהבחנה בין המשטח שמוצג בחלון לבין משטחים שאנחנו יוצרים בעצמנו. screen הוא המשטח שמתקבל מ־pygame.display.set_mode(). כדי ליצור משטח נוסף משתמשים ב־pygame.Surface((width, height)). יצירת משטח בזיכרון אינה פותחת חלון חדש ואינה מציגה אותו אוטומטית; המשטח יופיע על המסך רק כשנעתיק אותו אל screen. בדוגמה ניצור שני משטחים — אזור כותרת ואזור תוכן — שיחד ממלאים בדיוק את גובה החלון:

header = pygame.Surface((640, 80))
main = pygame.Surface((640, 320))

מערכת הצירים מתחילה בפינה השמאלית העליונה: x גדל ימינה ו־y גדל כלפי מטה. לכל משטח מערכת צירים מקומית משלו. המיקום (0, 0) בתוך main הוא הפינה שלו, גם כאשר מציבים את המשטח מתחת לכותרת בחלון.

צבעים ומילוי

משטח חדש נוצר ללא תוכן משמעותי, ולכן נצבע אותו. מסך מחשב מרכיב כל צבע משלושה מקורות אור — אדום, ירוק וכחול — וכך גם Pygame: צבע RGB הוא שלשה של עוצמות אדום, ירוק וכחול, כל אחת בטווח 0–255. למשל, (0, 0, 255) הוא כחול ו־(211, 211, 211) הוא אפור בהיר. הפעולה fill() ממלאת משטח שלם בצבע אחד. נהוג לשמור צבעים בקבועים בעלי שמות, כדי שהקוד יהיה קריא:

BLUE = (0, 0, 255)
LIGHTGRAY = (211, 211, 211)
header.fill(BLUE)
main.fill(LIGHTGRAY)

מציבים משטחים באמצעות blit

כדי להרכיב תצוגה מכמה משטחים, מעתיקים את תוכנו של משטח אחד אל אחר. קוראים ל־blit() על משטח היעד, ומעבירים את משטח המקור ואת מיקום הפינה השמאלית העליונה שלו ביעד.

screen.blit(header, (0, 0))
screen.blit(main, (0, 80))

כך אזור הכותרת תופס את 80 השורות העליונות, והמשטח הראשי מתחיל מיד מתחתיו. סדר הקריאות חשוב: תוכן שמצויר מאוחר יותר יכול להסתיר תוכן שכבר צויר. השכבות כאן הן תוצאה של סדר הציור, ולא אוסף שמוצג מעצמו.

שני משטחים: כותרת כחולה ואזור תוכן אפור בהיר.
שני משטחים: כותרת כחולה ואזור תוכן אפור בהיר.

דוגמה מלאה

נחבר את יצירת המשטחים, צביעתם והצבתם בחלון לתוכנית אחת.

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 400))
header = pygame.Surface((640, 80))
main = pygame.Surface((640, 320))
header.fill((0, 0, 255))
main.fill((211, 211, 211))
running = True

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

    screen.blit(header, (0, 0))
    screen.blit(main, (0, 80))
    pygame.display.update()

pygame.quit()

היכרות עם שקיפות

לעיתים רוצים להציג שכבה שדרכה עדיין רואים את מה שמתחת — למשל חלונית "משחק מושהה" מעומעמת מעל המסך, או צל של דמות. משטח רגיל מסתיר את מה שמתחתיו. משטח עם pygame.SRCALPHA מאפשר להגדיר שקיפות — Alpha לכל פיקסל. לצבע מצרפים רכיב רביעי, Alpha: אפס הוא שקוף לגמרי ו־255 אטום לגמרי, וערך ביניים כמו 128 נותן שקיפות למחצה.

overlay = pygame.Surface((180, 100), pygame.SRCALPHA)
overlay.fill((255, 180, 40, 128))
screen.blit(overlay, (230, 150))

את יצירת overlay והמילוי מבצעים לפני הלולאה. את ה־blit מוסיפים אחרי ציור main ולפני הרענון. האזור הכתום השקוף למחצה יתמזג עם הרקע. תיעוד משטחים

קוד להורדה: הדוגמה המלאה.