אנימציה ותמונות בעזרת ImageLoader

לשיעור הקודם – שימוש ב Sprite


בשיעור זה נלמד כיצד לטעון תמונות ולנגן אנימציה ב HTML5 בעזרת ImageLoader.

לחץ כאן להרצת הדוגמא.

ה ImageLoader הוא הרחבה של Shape. האמת שהתלבטתי, מכיוון שב AS3 הוא יורש מ Sprite. אבל בסופו של דבר לא רציתי להכביד על ה JS מבחינת הביצועים ולכן בחרתי לרשת מ Shape.

נסתכל בקוד הבא:

     var image1 = new DisplayObject.ImageLoader("assets/Sprites/beholder.png");
    stage.addChild(image1);
    image1.x = 50;
    image1.y = 50
    var image2 = image1.clone();
    image2.currentframe = 3;
    image2.setFps(45)
    stage.addChild(image2);
    image2.x = 150;

ננסה להבין אותו:
השורה הראשונה יוצרת ImageLoader ומעבירה לו את הכתובת של התמונה, המכילה את האנימציה.
בהמשך מוסיפים אותו לבמה במיקום 50 על 50.
השורות הבאות יוצרות עוד Image, שמשתמש באותו מקור כמו הראשון, ולכן בשביל לחסוך בזיכרון חשוב מאוד להשתמש ב clone ( זו הסיבה שכתבתי אותו ).
אני מכוון את ה currentframe שלו ל 3 בשביל שכל אחת מהאנימציות תתחיל בנקודה שונה.
לאחר מכן אני משנה את הפריימים לשניה בעזרת setFps.
ומוסיף אותו לבמה.
שימו לב ששיניתי רק את מיקום ה X שלו. כל שאר הערכים של image2 שווים לערכים של image1 ולכן הם מופעים באותו Y.

תמונה 1 - אנימציה על Canvas

תמונה 1 - אנימציה על Canvas



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



















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

     var explo = new DisplayObject.ImageLoader("assets/Sprites/explosion.png");
    explo.cols = 4;
    explo.totalframes =8;
    explo.width = 71;
    explo.height = 100;
    stage.addChild(explo)

והנה הקוד המלא:

    <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>ImageLoader - JavaScript AS3 Sample 3 </title>
    <script type="text/javascript" src="DisplayObject/Shape.js"></script>
    <script type="text/javascript" src="DisplayObject/Sprite.js"></script>
    <script type="text/javascript" src="DisplayObject/ImageLoader.js"></script>
    <script type="text/javascript" src="InitStage.js"></script>
</head>
<body>
<script type="text/javascript">

    CreateStage(700,500,45);
    var image1 = new DisplayObject.ImageLoader("assets/Sprites/beholder.png");
    stage.addChild(image1);
    image1.x = 50;
    image1.y = 50
    var image2 = image1.clone();
    image2.currentframe = 3;
    image2.setFps(45)
    stage.addChild(image2);
    image2.x = 150;

    var explo = new DisplayObject.ImageLoader("assets/Sprites/explosion.png");
    explo.cols = 4;
    explo.totalframes =8;
    explo.width = 71;
    explo.height = 100;
    stage.addChild(explo)

</script>
</body>
</html>

לסיכום
מקווה שהקלתי במשהוא על המעבר של מפתחי Flash ל HTML5.

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

התנגשות עם קו משופע.

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

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

נסתכל על הדוגמא הבאה:

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

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

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

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

public function CheckCollision(iLine:DisplayObject):Boolean
{          
    // נבדוק אם בכלל יש טעם לחשב פגיעה
    if(!iLine.hitTestObject(this)) 
        return false;                      
    // נחשב את אורך הוקטור בין הכדור לראשית הקו               
    var aLength:Point = new Point(x - iLine.x, y - iLine.y);
    // נחשב את זווית הקו ברדינים              
    var aRadSlope:Number = iLine.rotation * Math.PI / 180; 
    //  נחשב את הסינוס והקוסינוס של זווית הקו               
    var aCos:Number = Math.cos(aRadSlope);             
    var aSin:Number = Math.sin(aRadSlope);             
    // נסובב את הוקטור כך שנקבל את הגובה אם המערכת היתה מיושרת
    var aTurnY:Number = aCos * aLength.y - aSin * aLength.x;
    // נסובב את וקטור המהירות כך שנקבל את הערך האנכי שלו במצב של מערכת מיושרת     
    var aTempVy:Number = -(aCos * mVelocity.y - aSin * mVelocity.x);
    // בדיקה האם יש פגיעה בין הקו לכדור              
    if((aTurnY > -mRadius)&&(aTurnY > aTempVy))                        
    {                  
        // נסובב את כוון וקטור המהירות של הכדור בשביל לקבל החזרה נכונה
        // יחסית למצב המיושר                
        var aTempVx:Number = aCos * mVelocity.x + aSin * mVelocity.y;  
        // נסובב חזרה את וקטור המהירות למצב הנכון                  
        mVelocity.x = aCos * aTempVx - aSin * aTempVy;         
        mVelocity.y = aCos * aTempVy + aSin * aTempVx;         
        return true;               
    }          
       
}

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

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