דוא"ל:
תפריט משתמש




JavaCC++C#Design Patternsמבחני ראיוןVisual C++
שתף |

מדריך ליצירת אנימציה: שלום דגיג!

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

שלום דגיג - שלב 1

בתכנית זו נבצע אנימציה של דג הנע במעמקי הים לצד אחד, בהגיעו לקצה המסך מסתובב וחוזר חזרה.
  • הרץ את מאמא, פתח עולם חדש עם רקע ים
  • לחץ על הסימן "+" שבתחתית חלון התלת ממד בכדי לעבור למצב עריכת במה
  • בחלון התחתון, מופיעה ספריית העצמים: בחר בתת הספריה אוקיינוס, ואחר כך בחר במעמקי_אוקיינוס. זהו רקע של מעמקי הים, ובתוכו נבצע את אנימציית הדג.
  • כעת הוסף גם את הדג שבגלריה, דגיג
  • מקם את הדג בצד השמאלי של חלון העולם, כשפניו מופנות אל הצד השני (צד ימין של העולם)
  • כעת, ברצוננו לבצע תנועה של הדג עד לקצה השני:
    • הוסף למתודה הנוכחית - מתודת העולם מתודה_ראשית - הוראת הזזה של הדג קדימה מרחק של 1 מטר. כדי לבצע זאת, גרור מעץ העצמים את הדג אל שטח עורך התכנית, ומתוך התפריט הצץ בחר במתודה זוז, ואחר כך בפרמטר קדימה. לחץ על עוד... ובחר במשך, ומהתפריט בחר ב- 4 שניות.
    • הרץ את העולם. הדג נע לצד ימין של המסך ולבסוף נעצר.
  • כעת הוסף הוראת פניה לדג בהגיעו לצד ימין של החלון: גרור שוב את הדג אל איזור העריכה, לשורה שלאחר השורה שזה עתה הוספת, ובחר מהתפריט פנה, לאחר מכן בחר בשמאל, ומהתפריט הנפתח בחר חצי סיבוב. גם כאן הגדר את משך הפעולה להיות 4 שניות.
  • הקלק עם מקש ימין של העכבר על השורה הראשונה, ומהתפריט הצץ בחר ב- שכפל - נוצר העתק של השורה הראשונה בשורה שלאחריה. גרור את השורה המועתקת לסוף העורך (כלומר לשורה שלאחר הוראת הפניה). הוראה זו למעשה מחזירה את הדג אל מקומו בצד שמאל.
  • הרץ את התכנית וצפה בדג נע ימינה, פונה ואחר כך נע שמאלה.
קוד התכנית:

  מתודה_ראשית ( )
    
       דגיג .זוז( קדימה , 1 מטר ); משך = 4 שניות
  דגיג .פנה( שמאלה , 0.5 סיבובים ); משך = 4 שניות
  דגיג .זוז( קדימה , 1 מטר ); משך = 4 שניות


שלום דגיג: שלב 2

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

  מתודה_ראשית ( )
    
    
  כלעוד( אמת )
       דגיג .זוז( קדימה , 1 מטר ); משך = 4 שניות
  דגיג .פנה( שמאלה , 0.5 סיבובים ); משך = 4 שניות


שלום דגיג: שלב 3

כעת נרצה להוסיף את תנועת סנפיר הזנב של הדג. אלגוריתם התכנית הכולל את תנועת הזנב הינו כעת:
  • הפנה את הזנב שמאלה שמינית סיבוב
  • כלעוד (אמת)
    • הפנה את הזנב ימינה רבע סיבוב
    • הפנה את הזנב שמאלה רבע סיבוב
    • התקדם מטר קדימה
    • פנה שמאלה חצי סיבוב
למימוש האלגוריתם בצע:
  • בעץ העצמים, בחר בדג, אחר כך בחר בגזע_הזנב, ולאחר מכן בחר בזנב.
  • גרור את הזנב והשלך על השורה הראשונה בתכנית (לפני הוראת הלולאה). מהתפריט בחר בפנה, אחר כך בחר בפניה שמאלה, ומתוך האפשרויות המוצגות בחר באחר...", והקלד 0.125, כלומר שמינית סיבוב.
  • שכפל את השורה שזה עתה הכנסת וגרור את השורה המשוכפלת לתחילת הלולאה, תוך הפיכת הכיוון לימינה, ושינוי ערך הפניה משמינית סיבוב לרבע סיבוב.
  • שכפל את השורה שזה עתה יצרת והפוך שוב את ערך הכיוון לשמאל.
  • הרץ את התכנית. האם היא מבוצעת כצפוי? נסה להגדיר את הבעיה לפני מעבר לסעיף הבא.


כפי שניתן לראות, הביצוע של גוף הלולאה מבוצע באופן סידרתי, כלומר, ראשית מבוצעת הפניה של הזנב ימינה, אחר כך שמאלה, לאחר מכן מבוצעת התקדמות ולבסוף פניה. אולם מה שהיינו רוצים הוא תנועה רציפה של הזנב שמאלה וימינה במהלך תנועת ההתקדמות ותנועת הפניה. כיצד נשיג זאת? אם נחזור שוב להוראות הבקרה שבתחתית המסך, נגלה את ההוראה בצע_במקביל. הוראה זו מאפשרת לבצע מספר פעולות במקביל, בניגוד לביצוע סדרתי. אנו נעשה בה שימוש בכדי לממש תנועה רציפה של הזנב תוך כדי תנועת הדג. אלגוריתם התכנית:
  • הגדר מונה: מונה=1
  • הפנה את הזנב שמאלה שמינית סיבוב
  • כלעוד (אמת)
    • בצע במקביל
      • הפנה את הזנב ימינה רבע סיבוב
      • התקדם 0.1 מטר קדימה
    • בצע במקביל
      • הפנה את הזנב שמאלה רבע סיבוב
      • התקדם 0.1 מטר קדימה
    • אם המונה==5
      • פנה שמאלה חצי סיבוב
      • אתחל את המונה: מונה=1
    • אחרת
      • קדם את המונה ב- 1


מימוש האלגוריתם:
  • הוסף לתכנית הקיימת הגדרת מונה: הקלק על הכפתור צור משתנה חדש ליצירת משתנה, בחר טיפוס מספר ותן לו את השם מונה. השאר את ערך ברירת המחדל באתחול 1.
  • גרור את הוראת הבקרה בצע_במקביל והשלך אל תחילת הלולאה.
  • גרור לתוך גוף ההוראה בצע_במקביל את הוראת הפנית הזנב שמאלה ואת הוראת ההתקדמות. שנה את ערך ההתקדמות ל- 0.1 מטר, ואת משך ההתקדמות ל 0.4 שניות (בכדי לשמור על המהירות המקורית חילקנו הן את מקטע ההתקדמות והן את משכה ב- 10).
  • שכפל את ההוראה בצע_במקביל. בבלוק החדש שיצרת הפוך את הכיוון בהוראת הפניה מימינה לשמאלה.
  • גרור את הוראת הבקרה אם והשלך אל השורה שלאחר הבלוק האחרון שיצרת. מהתפריט הצץ בחר אמת. גרור את המשתנה שהגדרת קודם מאיזור המשתנים של המתודה והשלך אותו אל תוך הסוגריים של ההוראה אם, כלומר על הערך הקיים אמת. מהתפריט הצץ בחר ב- "==" ומהתפריט החדש צור את הערך 5.
  • גרור את הוראת הפניה לתוך השורה שלאחר שורת התנאי אם.
  • גרור שוב את משתנה המונה שיצרת מאיזור המשתנים של המתודה, והפעם השלך אותו לתוך גוף ההוראה אחרת. מהתפריט הצץ בחר "++" - אופרטור הקידום.
  • הרץ את התכנית. האם כעת התכנית מבוצעת כצפוי? אם לא, נסה לתאר את הבעיה באופן מדוייק לפני מעבר לסעיף הבא.
קוד התכנית:

  מתודה_ראשית ( )
    מספר מונה = 1 ;
       דגיג.גזע_הזנב.זנב .פנה( שמאלה , 0.125 סיבובים );
  כלעוד( אמת )
    
  בצע_במקביל
       דגיג.גזע_הזנב.זנב .פנה( ימינה , 0.25 סיבובים );
  דגיג .זוז( קדימה , 0.1 מטרים ); משך = 0.4 שניות
  בצע_במקביל
       דגיג.גזע_הזנב.זנב .פנה( שמאלה , 0.25 סיבובים );
  דגיג .זוז( קדימה , 0.1 מטרים ); משך = 0.4 שניות
  אם( ( מונה == 5 ) )
       דגיג .פנה( שמאלה , 0.5 סיבובים ); משך = 4 שניות
  מונה = 1
  אחרת
    מונה ++


שלום דגיג: שלב 4

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


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

קוד התכנית:

  מתודה_ראשית ( )
    מספר מונה = 1 ;
       דגיג.גזע_הזנב.זנב .פנה( שמאלה , 0.125 סיבובים );
  כלעוד( אמת )
    
  בצע_במקביל
       דגיג.גזע_הזנב.זנב .פנה( ימינה , 0.25 סיבובים );
  דגיג .זוז_במהירות( קדימה , מהירות = 0.1 מטרים לשנייה );
  בצע_במקביל
       דגיג.גזע_הזנב.זנב .פנה( שמאלה , 0.25 סיבובים );
  דגיג .זוז_במהירות( קדימה , מהירות = 0.1 מטרים לשנייה );
  אם( ( מונה == 5 ) )
    
  בצע_במקביל
       דגיג .פנה_במהירות( שמאלה , מהירות = 0.25 מטרים לשנייה );
  דגיג.גזע_הזנב.זנב .פנה( ימינה , 0.25 סיבובים );
  בצע_במקביל
       דגיג .פנה_במהירות( שמאלה , מהירות = 0.25 מטרים לשנייה );
  דגיג.גזע_הזנב.זנב .פנה( שמאלה , 0.25 סיבובים );
  מונה = 1
  אחרת
    מונה ++


שלום דגיג: שלב 5

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

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

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

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

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

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


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

קוד התכנית:

  מתודה_ראשית ( )
    
    
  בצע_במקביל
       דגיג.טייל ( );
  דגיג.כשכש ( );