תכנות לילדים באמצעות Game Maker/טטריס/צעד 6: קוד


שפת תכנות עריכה

מחשבים לא מבינים עברית. בתוך נבכי המחשב מתרוצצים להם אותות חשמליים שהם השפה היחידה שהמחשב באמת מבין. בני אדם נוהגים לייצג את האותות האלה בסימנים 1 (כשעובר זרם חשמלי) ו-0 (כשלא עובר זרם) ולקרוא להם שפת מכונה. כדי לתכנת את המחשבים הראשונים, המתכנתים היו צריכים ללמוד שפת מכונה ולהכניס למחשב סימנים של 0 ו-1 (בדרך כלל באמצעות ניקובים בכרטיסי קרטון, שגרמו למתגים במחשב לזוז). זה היה כרוך בהרבה מאוד עבודה.

עם הזמן מצאו פתרון נוח יותר: במקום לכתוב 0 ו-1 (או לנקב כרטיסים), המתכנתים כתבו מלים באנגלית וסימני חשבון, והשתמשו בתוכנה מיוחדת שהפכה את מה שהם כתבו לשפת מכונה. כמובן שהתוכנה הזאת לא הבינה את כל המלים באנגלית ואת כל הסימנים שיש; היא הבינה רק דברים מסוימים, והמתכנתים למדו לכתוב רק מה שהתוכנה יודעת להפוך לשפת מכונה. ככה נוצרו מעין שפות דומות קצת לאנגלית וקצת לחשבון, שנקראות שפות תכנות. לדברים שכותבים בשפת תכנות נהוג לקרוא קוד - אולי כי התוכנה מפענחת את הקוד לשפת מכונה, ואולי כי זה נראה כמו קוד סתרים למי שלא מכיר את שפת התכנות...

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

ועדיין, לא לכל דבר יש פעולה מתאימה ב-Game Maker. יש דברים שאפשר לתכנת רק באמצעות שפת תכנות. לכן יש ב-Game Maker אפשרות לתכנת גם בשפת תכנות. שפת התכנות של Game Maker נקראת GML, שזה ראשי תיבות של Game Maker Language - שפת Game Maker. התחביר שלה דומה לתחביר של שפות תכנות אחרות כמו C, C++, Java, JavaScript, Perl ואחרות. ככה שאם מכירים את GML מקבלים בסיס שעוזר ללמוד שפות תכנות אחרות בעתיד.

פעולת קוד עריכה

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

נתחיל במשהו פשוט: הפעולה לקביעת הערך של משתנה  . נלך לארוע היצירה של אובייקט הערימה, לפעולה שנותנת למשתנה sprite_index את הערך pile_red. נמחק אותה, במקומה נשים פעולת קוד  .

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

sprite_index = pile_red;

מה זה אומר?

  • הסימן = אומר שזו פעולת קביעת ערך של משתנה, או הצבה, כי "מציבים" ערך אל תוך משתנה.
  • משמאל לסימן = כותבים את שם המשתנה שמציבים אליו. במקרה שלנו זה המשתנה sprite_index.
  • מימין לסימן = כותבים את הערך שמציבים למשתנה. במקרה שלנו זה pile_red.
  • בסוף הפעולה כותבים את הסימן נקודה-פסיק (;) כדי לסמן איפה הפעולה נגמרת. בקוד אפשר לכתוב הרבה פעולות אחת אחרי השניה, ולכן צריך לסמן איפה כל פעולה נגמרת. לכל פעולה כזאת (שנגמרת בנקודה-פסיק) קוראים "פקודה" או "הוראה", כי היא אומרת למחשב מה לעשות.

בין החלקים השונים בקוד מותר לכתוב רווחים, אם רוצים. (כדאי לרצות לכתוב רווחים - זה מקל על הקריאה.)

 

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


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




 

עכשיו תורכם:

להחליף לפעולות קוד גם את שאר הפעולות של קביעת ערך משתנה.

פעולות אם-אז בקוד עריכה

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

 

בקוד, נכתוב את הפעולות האלה ככה:

if (shape.sprite_index == I)
{
    sprite_index = pile_red;
}

נעבור על הקוד לאט לאט כדי להבין מה כתוב בו:

  • if היא מילת מפתח - מילה שמסמנת פקודה. כמו שהסימן = מסמן פקודת הצבה, ככה המילה if מסמנת את הפקודה המקבילה לפעולת הבדיקה. משמעות המילה if באנגלית היא פשוט "אם". הפקודה שהיא מסמנת היא פקודת אם-אז.
  • (shape.sprite_index == I) הוא הביטוי שבודקים בפקודה. בפקודת if, מה שבודקים תמיד מופיע בתוך סוגריים אחרי המילה if. אפשר לכתוב כל מיני ביטויים, כמו למשל: 1 < 2. פקודת if בודקת אם הביטוי נכון או לא, ואם כן אז הבלוק שאחריה יתבצע. לגבי הביטוי שבתוך הסוגריים:
    • == מסמן השוואה בין שני דברים. ראינו כבר שסימן = אחד מסמן פעולת הצבה. אם רוצים לכתוב ביטוי שאומר אם שני דברים שווים זה לזה, משתמשים בסימן == (בלי רווח בין שני סימני השוויון).
    • shape.sprite_index הוא הערך של המשתנה sprite_index של אובייקט shape, בדיוק כמו בפעולות הרגילות.
    • I מסמן את הדמות של הקו הארוך, בדיוק כמו בפעולות הרגילות.
  • סימני הצומדיים { ו-} הם פשוט תחילת הבלוק וסוף הבלוק.
  • sprite_index = pile_red; היא פקודת הצבה, כמו שראינו קודם. שימו לב ששמתי לפניה רווחים - זה מסמן שהיא בתוך הבלוק. למחשב לא אכפת אם נשים רווחים או לא, אבל בכל זאת כדאי להקפיד לשים רווחים לפני פקודות בתוך בלוק כדי שיהיה קל לראות איפה הבלוק מתחיל ואיפה הוא נגמר. זה חשוב במיוחד במקרה של בלוק בתוך בלוק (למשל אם עושים לולאה כפולה).

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

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


  צריך לבדוק שהנחיתה עדיין עובדת, גם עם הקו וגם עם צורות אחרות.




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

if (shape.sprite_index == I)
{
    sprite_index = pile_red;
}
if (shape.sprite_index == T)
{
    sprite_index = pile_gray;
}
if (shape.sprite_index == L)
{
    sprite_index = pile_yellow;
}
if (shape.sprite_index == J)
{
    sprite_index = pile_purple;
}
if (shape.sprite_index == S)
{
    sprite_index = pile_blue;
}
if (shape.sprite_index == Z)
{
    sprite_index = pile_green;
}

אבל גם בזה אין צורך. את כל הפקודות if האלה אפשר להחליף בפקודה אחת.

פקודת הבחירה עריכה

פקודת הבחירה switch היא פקודת בקרה: היא קובעת אם פקודות אחרות יתבצעו או לא, בדומה לפקודת if. אבל היא קובעת את זה בצורה שונה: היא בודקת מה הערך של ביטוי, ולפי זה בוחרת לבצע פקודה אחת מתוך רשימה של פקודות. ככה נוכל לבדוק את הערך של המשתנה shape.sprite_index, ולפיו לבחור איזו פקודת הצבה לבצע.

הקוד של פקודת הבחירה נראה ככה:

switch (shape.sprite_index)
{
case I:
    sprite_index = pile_red;
    break;
case T:
    sprite_index = pile_gray;
    break;
case L:
    sprite_index = pile_yellow;
    break;
case J:
    sprite_index = pile_purple;
    break;
case S:
    sprite_index = pile_blue;
    break;
case Z:
    sprite_index = pile_green;
    break;
default:
    sprite_index = pile_aqua;
}

נעבור על הקוד כדי להבין אותו:

  • switch היא מילת מפתח שמסמנת פקודת בחירה: היא קובעת איזה פקודות לבצע לפי הערך שבודקים. הפקדות שהיא תבחר מופיעות בבלוק שאחריה.
  • (shape.sprite_index) הביטוי בסוגריים שמופיע אחרי המילה switch הוא הערך שבודקים אותו. במקרה שלנו, בודקים את הערך של shape.sprite_index ולפיו בוחרים איזה פקודות לבצע.
  • case I: היא תווית שמסמנת "כאן הפקודות שצריך לבצע במקרה שהערך שבודקים הוא I". המילה case היא מילת מפתח שמסמנת לבדוק אם מה שכתוב אחריה שווה לביטוי בסוגריים שאחרי המילה switch. אם הם שווים, יבוצעו כל הפקודות שאחרי הנקודותיים.
  • sprite_index = pile_red; היא פקודת הצבה. היא תתבצע אם הביטוי שבודקים (shape.sprite_index) שווה לתווית שמעליה (I). אמנם כתבנו רק פקודה אחת לביצוע בתווית הזו, אבל אפשר לכתוב כמה פקודות, ואז כל הפקודות האלה יבוצעו אם הביטוי של ה-switch שווה לתווית.
  • break; היא פקודת בקרה מיוחדת: היא גורמת להפסיק את ביצוע הפקודות שאחריה, עד לסוף הבלוק. זה דומה קצת לפעולת היציאה מהארוע  , אבל break לא מוציאה מהארוע כולו אלא רק מהבלוק של פקודת switch. אם לא היינו כותבים break, המחשב היה ממשיך לבצע את הפעולות הבאות (למרות שהן מופיעות בתוויות אחרות).
  • default: היא התווית האחרונה, שמסמנת מה לעשות אם אף אחת מהתוויות האחרות לא מתאימה. לא חייבים לכתוב את התווית default, אבל בדרך כלל כדאי - יכול להיות שיקרה משהו בלתי צפוי ואז כדאי שנטפל גם במקרה הזה.
 

כדאי לדעת:

קצת מסובך? לא לדאוג - רוב הדברים שנכתוב בקוד יהיו יותר פשוטים מזה. ובמשך הזמן דברים שנראים עכשיו מסובכים ייראו פתאום מובנים וברורים.(למרות שמדובר בקוד פשוט מאוד)

עכשיו נעתיק לפעולת קוד את הקוד שלמעלה עם פקודת ה-switch, ונמחק את כל פעולות הבדיקה וההצבה שהשתמשנו בהן קודם:

 

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



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




 

כדאי לדעת:

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

המשך העבודה עריכה

התקדמנו הרבה בידע, אבל השלמנו רק סעיף אחד ברשימת העבודה:

  • אובייקט לצורת הריבוע
  • נפילה
  • תנועה ימינה ושמאלה כשלוחצים על החצים
  • להערם בסוף הנפילה
  • לתכנת את שאר הצורות
  • לבחור את צבע הערימה לפי הצורה
  • לבחור צורה באופן אקראי
  • לסובב את הצורות כשלוחצים על חץ למעלה
  • להעלים שורות שלמות

אל תחששו להתקדם לסעיפים הבאים גם אם לא הכל ברור - רוב מה שנעשה בהמשך יהיה פשוט יותר.


מספיק לשנות את דמות הצורה באופן ידני - צעד 7: צורה אקראית