ב.3 — אירועים וסגירת החלון

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

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

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

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

קוראים את תור האירועים

קריאת התור מאפשרת לתוכנית להגיב למה שקרה מאז הקריאה הקודמת. הפעולה pygame.event.get() מחזירה רשימה של האירועים הממתינים ומסירה אותם מהתור. לולאת for עוברת על הרשימה, והמאפיין event.type מציין את סוג האירוע. אם אין אירועים, הרשימה ריקה והתוכנית ממשיכה לפעולות הבאות.

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

הקבוע pygame.QUIT מזהה אירוע של בקשת סגירה. אנחנו משנים את running ל־False, כדי שלא יתחיל סיבוב נוסף של הלולאה הראשית. זהו תור אירועים — Event Queue: האירועים נשמרים לפי סדר התרחשותם, והראשון שנכנס הוא הראשון שנקרא — ולא מחסנית שבה שולפים תחילה את הפריט האחרון שנכנס. כך התוכנית מטפלת בלחיצות בסדר שבו השחקן ביצע אותן.

תוכנית שאפשר לסגור

נשלב את הטיפול בבקשת הסגירה בלולאה הראשית. שמרו את הקוד בקובץ main.py והריצו אותו. ייפתח חלון ריק; לחיצה על כפתור הסגירה תסיים את הלולאה ואת השימוש ב־Pygame.

import pygame

pygame.init()
screen = pygame.display.set_mode((640, 400))
pygame.display.set_caption("Close the window")
running = True

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

    if not running:
        break

    pygame.display.update()

pygame.quit()
חלון Pygame שחור עם הכותרת Close the window; כפתור הסגירה פעיל.
החלון שנפתח: עדיין שחור, אבל הפעם הכותרת רגילה ולחיצה על כפתור הסגירה סוגרת אותו.

שימו לב להזחות: לולאת האירועים נמצאת בתוך הלולאה הראשית. הקריאה pygame.quit() נמצאת אחרי הלולאה הראשית, משום שהיא משחררת את רכיבי Pygame בסיום. הבדיקה if not running מונעת ציור נוסף אחרי בקשת הסגירה.

אירוע סגירה ופעולת סיום

בקשת סגירה והפסקת השימוש בספרייה הן שני שלבים נפרדים. pygame.QUIT הוא ערך שמזהה סוג של אירוע. לעומתו, pygame.quit() היא פעולה שמסיימת את השימוש ברכיבי הספרייה. היא אינה משנה בעצמה את המשתנה running ואינה מסיימת בהכרח את כל תוכנית Python. בדוגמה התוכנית מסתיימת מפני שהלולאה נעצרה ואין אחריה פעולות נוספות.

באותה דרך נטפל בהמשך גם באירועים אחרים: לחיצות מקשים ותנועות עכבר מגיעות לאותו תור, ורק הערך של event.type מבדיל ביניהם.

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

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