בחזרה לעמוד הבית

קואורדינטות של פלאש ולולאות timeline

 

כללי

 

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

  1. הקוד אשר חוזר על עצמו וממקם מחדש את האובייקט .
  2. הקוד אשר מחשב היכן למקם את האובייקט .

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

 

קואורדינטות פלאש

 

בשביל למקם אובייקט על משטח דו מימדי אנחנו משתמשים בשיטה הקרטיזיאנית : מיקום אופקי (קואורדינטת ‘x’ ) ומיקום אנכי (קואורדינטת ‘y’ ) .

 

ברשת הדו מימדית הקרטיזיאנית :

-          המרכז הוא בנקודה 0,0 (המקור של מערכת הקואורדינטות) .

-          קואורדינטת y חיובית מתייחסת לנקודה מעל ציר ה-x .

-          קואורדינטת y שלילית מתייחסת לנקודה מתחת ציר ה-x .

-          קואורדינטת x חיובית מתייחסת לנקודה מימין ציר ה- y .

-          קואורדינטת x חיובית מתייחסת לנקודה משמאל ציר ה-y .

 

 

בפלאש , הפינה השמאלית העליונה היא המקור של מערכת הקואורדינטות .

אבל פלאש הפכה את ציר ה-y :

-          קואורדינטת y חיובית מתייחסת לנקודה מתחת לציר ה-x .

-          קואורדינטת y שלילית מתייחסת לנקודה מעל לציר ה-x .

 

 

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

 

הקצאת מיקום אובייקט

 

על מנת למקם movie clip בפלאש , נגדיר את המאפיינים _x ו-_y שלו .

לדוגמא , על מנת למקם movie clip בעל instance name – "ball" במרכז הבמה נשתמש ב-

Ball._x=225;

Ball._y=200;

 

הצורך בלולאת timeline

 

בשביל לשנות מיקום של movie clip אנחנו משנים את מיקום ה-_x וה-_y שלו בצורה חוזרת בכמויות קטנות .

תחשבו על לולאת הזמן הבאה – היא בצורה חוזרת משנה את המיקום של האובייקט , וזה צריך לתת אשליה של תנועה עם הזמן , לא ?

For (i=0 ; i<50 ; i++){

                Ball._x+=10;

}

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

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

 

העיקרון הבסיסי

 

על מנת לאפשר לבמה לעדכן לאחר כל ביצוע של – ball._x+=10; נצטרך לבצע לולאת timeline בצורה הבאה :

//פריים 1

ball._x+=10;

 

//פריים 2

GotoAndPlay(1);

 

הפיכת הלולאה לניידת

 

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

כך בונים לולאת timeline ניידת יותר , נתחיל עם סרט שכבר יש בו movie clip של ball :

  1. הנח מופע (instance) של ה-symbol ball ב-timeline הראשי .
  2. קרא ל-instance של ה-ball בשם "ball" .
  3. בחר ב-insert>>new symbol על מנת להכין movie clip ריק .
  4. קרא ל-movie clip החדש בשם "process" .
  5. בפריים 1 של process כתוב את הקוד הבא :

_root.ball._x +=10 ;

  1. בפריים 2 של process כתוב את הקוד הבא :

GotoAndPlay(1) ;

  1. חזור ל-timeline הראשי והוסף לו שכבה בשם processMove
  2. בשכבה processMove מקם מופע של ה-symbol process .

 

לולאות clip event

 

לולאות timeline אפקטיביות אך לא בהכרח אלגנטיות . מגרסא פלאש 5 ואילך אנחנו יכולים להשתמש בארוע enterFrame של כל movie clip על מנת להשיג את אותה התוצאה . ארוע ה-enterFrame גורם לבלוק של קוד מסויים להתרחש בכל פעם שעובר frame בסרט .

בואו וניצור מחדש את לולאת ה-timeline כארוע enterFrame . נתחיל בסרט הקודם שכבר קיים בו אובייקט ball עם השם "ball” ב-timeline הראשי .  (eventloop.fla)

  1. בחר ב-insert>>new Symbol ליצירת movie clip ריק .
  2. קרא לו בשם "process" .
  3. חזור אל ה-timeline הראשי וצור שכבה בשם processMove .
  4. בשכבה החדשה מקם מופע של ה-symbol process .
  5. בחר במופע של process וכתוב בו את הקוד הבא :

OnClipEvent (enterFrame){

        _root.ball._x += 10;

}

 

הפיכת לולאת ה-clip event לגמישה יותר

 

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

על מנת לעשות זאת ניתן ליצור movie clip ריק המכיל בתוכו עוד movie clip ריק עם ארוע enterFrame בתוכו . ואז בצורה דינמית אנחנו מוסיפים או מסירים את כל החבילה במקרה שנרצה להתחיל או לעצור את הלולאה .  בואו ונבנה לולאת event ניתנת לשליטה .

לסרט שלנו כבר יש symbol- ball . (event-loop-controllable.fla).

1.       בחר ב- insert >> new symbol  וצור שני movie clips ריקים .

2.       קרא לאחד process ולשני event loop .

3.       בספריה , בחר את process , ואז בחר ב-options>>linkage . תיבת ה-property של ה-linkage תופיע .

4.       בחר ב-export this symbol .

5.       בתוך תיבת הטקסט identifier  , הדפס processMoveBall , ולחץ על ok .

6.       בפריים הראשון של process , מקם מופע של eventloop.

7.       בחר במופע ששמת , וכתוב את הקוד הבא :

OnClipEvent (enterFrame){

        _root.ball._x += 10;

}

8. חזור אל ה-timeline המרכזי   וכתוב את הקוד לכפתור – "start move" :

       On(release){

                AttachMovie (“processMoveBall”,”processMoveBall”,5000);

      }

9. כתוב את הקוד לכפתור – "stop move" :

       On(release){

                RemoveMovieClip(processMoveBall);

       }

 

באיזו מהירות תרוץ לולאת event ?

 

מכיוון שלולאות של timeline ו-movieclips מתרחשים פעם בפריים , תדירות הביצוע שלהם תלוי ב-fps של הסרט  . כל דוגמאות הקוד עד עכשיו יוצאות בגישה שבכל פריים שיעבור , הכדור יזוז ב-10 פיקסלים לצד ימין . (ball._x+=10) ולכן הגדלת מהירות הסרט תגדיל את מהירות התנועה של הכדור . ככל שיותר פריימים מעובדים בשניה , כך הכדור ממוקם מחדש יותר מהר כוך נראה שהוא זז יותר מהר .

זה יכול להיות מפתה לחשב את המרחק שצריך לזוז ביחס ל-fps של הסרט . לדוגמא , נניח שאנחנו רוצים שאובייקט יזוז 100 פיקסלים בשניה וה-fps הוא 20 .

במקרה כזה נזיז את האובייקט 5 פיקסלים בפריים . (20 פריימים בשניה / 100 פיקסלים בשניה = 5 פיקסלים לפריים ) . לגישה הזאת יש שני פגמים עיקריים :

  1. אם נשנה את ה-fps נצטרך לחשב מחדש את מהירות התנועה של האובייקט ולשנות את הקוד בהתאם
  2. אם המחשב שמריץ את הסרט לא יכול לעבד במהירות מספיקה מספיק על מנת לעמוד בקצב המתוכנן , הסרט יאט והאובייקט יזוז פחות מ-100 פריימים בשניה .

 

אילוץ הסרט למהירות קבועה

 

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

התוכנית מחולקת לשתי פונקציות : init() ו- movieclip() :

Function init (){

AttachMovie(“processMoveBall”,”processMoveBall”,5000);

               DistancePerRound = 100;

                Now = getTimer();

}

 

function MoveClip (theclip){

                then = now;

                now = getTimer();

                elapsed = now – then;

                numSeconds = elapsed / 1000 ;

moveAmount = distancePerSecond * numSeconds ;

theclip._x += moveAmount ;

}

 

-          פונקציית init() מאתחלת את תנועת ה-movieclip .

-          היא מחוברת ל-processMoveBall , שקוראת לפונקציה moveclip() בכל פריים שחולף .

-          הפונקציה init() מוציאה שני משתנים :

o        distancePerSecond – מספר הפיקסלים שהסרט צריך לזוז בשניה .

o        now – הזמן העכשווי .

-          אנחנו קוראים ל-init() מכפתור ה-start :

On(release){

                Init();

}

-          הפונקציה moveclip() מזיזה את הכדור

-          בכל פעם שהפונקציה moveclip() נקראת , היא :

o        קובעת כמה זמן חלף

o        קובעת כמה להזיז את הכדור על סמך הזמן שחלף

o        מזיזה את הכדור

-          הפונקציה moveclip() מקבלת פרמטר אחד , קישור ל-movie clip

function moveclip (theclip){

-          בתוך moveclip() אנחנו מקליטים את הזמן האחרון שבה בוצע עיבוד של פריים

then = now ;

-          אחר כך אנחנו נותנים ל-now את הזמן העכשווי

Now = getTimer();

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

Elapsed = now – then ;

-          עד עכשיו elapsed מדד במילישניות , הפעולה הבאה ממירה אותו לשניות

numSeconds = elapsed / 1000 ;

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

-          נכפיל את המרחק לשניה בכמות השניות שחלפו

MoveAmount = distancePerSeconds * numSeconds ;

-          לדוגמא , אם נזיז את האובייקט 100 פיקסלים בשניה , ועברו 0.14 שניות מאז שעובד הפריים האחרון אז

MoveAmount = 100 * 0.14 ;

MoveAmount = 14 ;

-          אז נזיז את האובייקט 14 פיקסלים בפריים הזה .

Theclip._x += moveAmount ;

-          פונקציית moveclip() נקראת על ידי enterFrame של הקליפ eventLoop .

onClipEvent (enterFrame){

                _root.moveClip(_root.ball);

}

 

יתרונות של תנועה על פי זמן

 

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

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

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