libGDX Scene2d tutorial – Part 2 – Splash Screen

libGDX Scene2d tutorial – Part 2 – Splash Screen

(חלק 1 נמצא כאן)

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

משהו כזה:

Splash Screen

כדי לעשות זאת, נשתמש (לראשונה) בספריית Scene2d.

העולם הוא במה

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

מסובך.

ספריית Scene2d באה בנוסף לכל מה שהכרנו, לא במקום. היא באה להקל עלינו לנהל את ה- rendering. הרעיון הוא כזה: אנחנו יוצרים ״במה״ (Stage). על גבי הבמה ממקמים ״שחקנים״ (Actors). לכל שחקן נגדיר ״פעולות״ (Actions) אותן הוא עושה, וזהו. Scene2d מאחורי הקלעים עושה בשבילנו את החישובים של כמה פיקסלים להזיז בפריים ומתי.

נתחיל בקוד:

public class SplashScreen implements Screen {
    private Spacers app;
    private Stage stage;
 
    public SplashScreen(final Spacers app) {
        this.app = app;
        this.stage = new Stage(new FitViewport(app.SCREEN_WIDTH, app.SCREEN_HEIGHT, app.camera));
    }
@Override
    public void resize(int width, int height) {
        stage.getViewport().update(width, height, false);
    }
}

כדי ליצור במה צריך ViewPort.

אנחנו רוצים שהמשחק שלנו ירוץ על פלטפורמות שונות עם גדלי מסך שונים. אמנם הגדרנו גודל מסך של 800/480 – זה גודל וירטואלי. בפועל זה ירונדר בכל מסך ע״פ גודלו הפיזי. אם המסך הוא באותו היחס, זו התמודדות פשוטה, פשוט התמונה תגדל בהתאם. אבל אם היחס שונה – איך אנחנו רוצים להתמודד עם זה? אפשר למתוח את התמונה לאורך, אפשר לחתוך מעט את הקצוות, אפשר להכניס כמה שאפשר למסך ושבצדדים יהיו פסים שחורים – ישנן כל מיני גישות להתמודד עם זה, כל משחק לפי מה שמתאים לו.

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

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

שחקן

אחרי שיצרנו במה, נוסיף Actor. ישנם Widgets שימושיים רבים ב- Scene2d – אחד הנפוצים הוא Image. זהו Actor (עם התכונות אותן כבר נראה) שיודע להציג תמונה. צריך רק לתת לו Texture (אותו טענו כבר ב- Assets) – להגדיר לו גודל ומיקום, וזהו.

זה נכון אם אנחנו רוצים רק להציג את התמונה בצורה סטטית, אבל אנחנו רוצים לעשות את זה בצורה יותר מעניינת. כאן נכנס לתמונה (no pun intended) המושג ״פעולה״ – Action.

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

@Override
    public void show() {
        Runnable transitionRunnable = new Runnable() {
            @Override
            public void run() {
                app.setScreen(app.menuScreen);
            }
        };
 
        Texture splashTex = Assets.getTexture(Assets.LOGO);
        Image logo = new Image(splashTex);
        logo.setOrigin(logo.getWidth() / 2, logo.getHeight() / 2);
        logo.setPosition((stage.getWidth() - logo.getWidth()) / 2, (stage.getHeight() - logo.getHeight()) / 2);
        logo.addAction(sequence(alpha(0), scaleTo(.1f, .1f),
                parallel(fadeIn(2f, Interpolation.pow2),
                        scaleTo(2f, 2f, 1.5f, Interpolation.pow5),
                        scaleTo(1f, 1f, 1.5f, Interpolation.pow5)),
                fadeOut(1.25f), run(transitionRunnable)));
 
        stage.addActor(logo);
    }

יצרנו סדרה מעט מורכבת של פעולות שיוצרת את האנימציה המבוקשת: הלוגו ״מופיע״ מתוך אמצע המסך ונעלם. בסוף סדרת הפעולות ישנה פעולת run, שמקבלת runnable כפרמטר, שמשנה את המסך.

חשוב: כדי להשתמש ב- Actions, כדאי להוסיף את ה- import הבא:

import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;

סיימנו, לא?

עוד לא. צריך להוסיף את החלק הכי חשוב:

@Override
    public void render(float delta) {
        Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
 
        stage.act(delta);
        stage.draw();
    }

אם לא נפעיל את act ואחריה draw – לא יצוייר כלום!

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *