GameActivity – מסך המשחק
זוכרים את הגרפיקות שגררנו לאחר שייצרנו את הפרוייקט? חלק מן הגרפיקות היו הגרפיקות אשר מתארות את כפתור ה-Push שהמשתמש ילחץ עליו:
כעת מה שעלינו לעשות זה ליצור מצב שהכפתור שלנו ידע לעבור בין שני התמונות כאשר הוא לחוץ וכאשר הוא אינו לחוץ, בדיוק כמו שעשינו עם כפתור ה-Start.
נעתיק את מסמך ה-startbutton_selector ונשנה את שמו ל-pushbutton_selector. במסמך נשנה את השורות המצביעות על תמונות כפתור ה-Start לתמונות כפתור ה-Push שיראה כך:
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/pushbutton_down" /> <!– pressed –> <item android:drawable="@drawable/pushbutton" /> <!– default –> </selector>
נעצב קודם כל את מסך המשחק. במסמך ה-game.xml נרשום את הקוד הבא:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/main_background" android:orientation="vertical"> <LinearLayout android:id="@+id/infoLayout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:orientation="vertical"> <TextView android:id="@+id/scoreTextView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" android:text="Score: 0" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#fcff1c" android:textSize="25dp"/> <TextView android:id="@+id/timeTextView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="00:00" android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center_horizontal" android:textSize="60dp" android:layout_marginBottom="3dp"/> </LinearLayout> <RelativeLayout android:id="@+id/gameZoneLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentTop="true" android:layout_above="@+id/infoLayout"> <ImageButton android:id="@+id/pushButton" android:layout_width="wrap_content" android:src="@drawable/pushbutton_selector" android:adjustViewBounds="true" android:scaleType="center" android:background="@android:color/transparent" android:layout_height="wrap_content"/> </RelativeLayout> </RelativeLayout>
הקוד הבא יוצר לנו חלון הנראה כמו החלון הבא:
לא נעבור על קטע קוד זה בצורה עמוקה. בתיעוד הרשמי של גוגל ניתן לחפש כל רכיב ולקרוא על תכונותיו בכדי להבין טוב יותר את קטע הקוד.
אם נסתכל על קטע הקוד ניראה כי בתחתית מופיע לנו אלמנט בשם RelativeLayout שה-id שלו הוא gameZoneLayout. שימו לב – באיזור זה הכפתור שלנו ירוץ ולכן נמצא בתוכו את אלמנט ה-ImageButton בעל ה-idpushButton. כפתור ה-pushButton הוא הכפתור שיקפוץ במקומות אקראיים על המסך.
בכדי שנגרום לכפתור שלנו להתרוצץ עלינו לשנות את ערכי ה-Margin שלנו. ערכי ה-Margin מאפשרים לנו לקבוע כמה רחוק הכפתור יהיה מצדיו של האזור שהוא מקיף. למשל כאשר ה-Margin השמאלי יהיה שווה ל-10 פיקסלים, אנו נדע כי הכפתור שלנו יהיה רחוק ב-10px מן הצד השמאלי אזור ההתרוצצות.
ממשיכים עם Java
כעת נעבור ללב המשחק – הקוד, נפתח את מסמך ה-GameActivity ונוסיף את המשתנים הבאים לחלק העליון של המחלקה:
/* Views on game.xml */ TextView scoreTextView; TextView timeTextView; ImageButton pushButton; RelativeLayout gameZoneLayout; /* Game time and updater variables */ Handler uiHandler; //Allows us to dispatch messages to the UI Timer gameTimer; //Our main game timer used to schedule button placement Timer stopperTimer; //Our stopper update timer int updatePeriod = 500; //The time button will appear /* Game Variables */ boolean isPlaying = false; int score = 0; //Current game score long startTime; //Game start time (in milliseconds) MediaPlayer mediaPlayer; //Used to play push button sounds
נעבור על המשתנים שהוספנו:
- 4 המשתנים העליונים מתארים את הרכיבים המופיעים ב-game.xml. כאשר pushButton מתאר את הכפתור שהמשתמש יצטרך ללחוץ, scoreTextView יציג את התוצאה של המשתמש, timeTextView יציג את זמן המשחק ו-gameZoneLayout מכיל את האזור שבו הכפתור שלנו יתרוצץ.
- 4 המשתנים האמצעים מאפשרים לנו ליצור את תהליך המשחק. המשתנה ה-2 (gameTimer) הוא ה-Timer המרכזי של המשחק. Timer היא מחלקה המאפשרת לנו לבצע פעולה מסוימת במחזוריות מסוימת. ניתן לקרוא עלייה בעמוד הבא. משתנה ה-gameTimer אחראי להזיז את הכפתור שלנו כל 500 אלפיות השנייה (חצי שנייה). המשתנה האחראי לקצב התזוזה של הכפתור הוא המשתנה ה-4 (updatePeriod) וערכו הוא 500. המשתנה ה-3 (stopperTimer) אחראי לעדכן את שעון המשחק כל פרק זמן מסוים. מפני ש-Timers עובדים בהליך נפרד מן הליך ה-UI עלינו לדאוג שכל הפעולות יבוצעו מן ההליך הראשי (הליך ה-UI). עקב כך, אנו משתמשים במשתנה ה-1 (uiHandler). משתנה זה מאפשר לנו "לזרוק" פקודות להליך הראשי שיבצע. ניתן לקרוא על Handlers בעמוד הבא. בנוסף ניתן לקרוא על שילוב של Timer עם Handler בעמוד הבא.
- 3 המשתנים התחתונים מתארים את משתני המשחק כמו תוצאה, זמן שעבר וכו' . משתנה ה-isPlaying יהיה "אמת" אם כרגע אנו משחקים. משתנה ה-score מכיל את התוצאה של המשתמש. משתנה ה-startTime מכיל את הזמן שבו המשחק התחיל באלפיות השנייה. בהמשך נבין מה השימוש שלו.
- המשתנה האחרון mediaPlayer מאפשר לנו להפעיל סאונד כאשר הכפתור שלנו נלחץ. בהמשך המדריך ניראה איך משתמשים בו.
הגבה ללחיצה על כפתור ה-Push
כפי שעשינו ב-MainActivity בכדי שנוכל להגיב לאירועי הלחיצה על כפתור ה-Push עלינו לממש את ממשק ה-onClickListener. ב-MainActivity הקודם יצרנו ממשק חדש – אך הפעם נעשה את זה בצורה קצת שונה.
מחלקת ה-GameActivity שלנו תממש את הממשק באמצעות הוספת החלק הבא להכרזת המחלקה:
public class GameActivity extends Activity implements View.OnClickListener
מה שבעצם עשינו זה הרחבנו את מחלקת ה-GameActivity ואפשרנו לה לממש את ממשק ה-OnClickListener. כעת כל מה שעלינו לעשות זה ליצור את המתודה הבאה:
@Override
public void onClick(View v) {}
כעת מימשנו את ממשק ה-OnClickListener, ועלינו לממש גם את ממשק ה-OnKeyListener . את הסיבה לכך נסביר בהמשך. לכן נוסיף גם את החלק הבא להכרזה של המחלקה:
public class GameActivity extends Activity implements View.OnClickListener, View.OnKeyListener
ונממש את הממשק:
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {}
נוסיף את השורות הבאות לפונקציית ה-onCreate:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game);/* Setting variables pointing to their XML views */
scoreTextView = (TextView) findViewById(R.id.scoreTextView);
timeTextView = (TextView) findViewById(R.id.timeTextView);
pushButton = (ImageButton) findViewById(R.id.pushButton);
gameZoneLayout = (RelativeLayout) findViewById(R.id.gameZoneLayout);
uiHandler = new Handler();
gameTimer = new Timer();
stopperTimer = new Timer();
//Allows us to handle push button
pushButton.setOnClickListener(this);
pushButton.setOnKeyListener(this);
//Preparing our push button media player to be ready
mediaPlayer = MediaPlayer.create(this, R.raw.pushbutton_sound);
try { mediaPlayer.prepare(); }
catch (Exception ex) {}
//Allows us to control the media volume using volume controls
setVolumeControlStream(AudioManager.STREAM_MUSIC);
}
כפי שניתן ליראות בקטע קוד זה ביצענו את הדברים הבאים:
- נתנו לכל משתני הרכיבים את הרכיבים הנמצאים במסמך ה-game.xml. כעת נוכל להתייחס אליהם. בדיוק כמו שעשינו בתחילת מסמך ה-MainActivity.
- ביצענו אתחול ראשוני למשתני תהליך המשחק (uiHandler, gameTimer ו-stoppperTimer).
- הוספנו Callbacks למשתנה ה-pushButton כך שנוכל לזהות לחיצות עליו.
- השתמשנו במשתנה ה-mediaPlayer בכדי לייבא את סאונד הלחיצה. את קובץ ה-pushbutton_sound.wav עלינו לשים בתיקיית ה-raw אשר נמצאת תחת תיקיית ה-res. ניתן לקרוא על מחלקת ה-MediaPlayer בעמוד הבא. בקצרה: מחלקה זו מאפשרת לנו לנגן קבצי מדיה. מתודה ה-MediaPlayer.create מאפשרת לנו ליצור אובייקט נגן חדש ממשאב הקיים באפליקציה. פונקציית ה-mediaPlayer.prepare() מכינה את הנגן לקראת נגינה.
- הפקודה האחרונה setVolumeControlStream מאפשרת לנו לומר לאנדרואיד שה-Activity שלנו מפעיל סאונד ואנו מעוניינים לשלוט עליו באמצעות כפתורי ה-Volume.
ניקוי משאבים לא נחוצים
כעת נוסיף את המתודה הבאה האחראית לניקוי המשאבים כאשר החלון נסגר:
@Override
protected void onDestroy() {
super.onDestroy();//Final clean up
mediaPlayer.release();
mediaPlayer = null;
}
זוכרים את מחזור החיים של Activity? כאשר Activity נהרס הוא קורא למתודת ה-onDestroy. מה שעשינו בקטע קוד הבא זה לנקות את משאבי נגן המדיה על ידי שימוש בפונקציית ה-MediaPlayer.release().
לאחר שהבנו את מתודה זו נוסיף את המתודה הבאה האחראית לעדכן את תצוגת התוצאה:
void updateScore() { scoreTextView.setText("Score: " + score); }
כאשר אנו רוצים לעדכן את הרכיב האחראי להציג את התוצאה עלינו לקרוא למתודה זו. מה שהיא תעשה זה פשוט לעדכן את התצוגה עם התוצאה הנוכחית.
זוכרים את מתודת ה-onClick שמימשנו? כאשר המשתמש ילחץ על כפתור ה-pushButton האפליקציה שלנו תקפוץ לשורה זו. כל מה שעלינו לעשות זה לבדוק אם כרגע המשתמש משחק על ידי בדיקת המשתנה isPlaying. אם המשתמש כרגע משחק, נעלה את משתנה התוצאה (score) באחד, נעדכן את התוצאה על המסך ונפעיל את הסאונד המתאים:
@Override
public void onClick(View v) {
if (isPlaying) {
score += 1;
updateScore();
mediaPlayer.start();
}
}
התעלמות מלחיצות מקשים בעייתיותזוכרים את מתודת ה-onKey שמימשנו? כעת נבין למה היינו צריכים אותו. מפני שמערכת האנדרואיד רצה על מכשירים בתצורות שונות עלינו לחשוב כיצד המשתמש יוכל לבצע אינטראקציה עמה. מלבד מסכי מגע חלק מהמכשירים מאפשרים לבצע אינטראקציה עם מקשים פיזיים. מערכת האנדרואיד יודעת להגיב גם ללחיצות פיזיות והיא מאפשרת למשתמש לעבור וללחוץ על כפתורים במערכת באמצעות מקשים אלו. מפני שבמשחק שלנו אנו רוצים שהמשתמש יבצע אינטראקציה רק באמצעות לחיצה על מסך המגע עלינו לזהות את לחיצות המקשים ולהגיד למערכת האנדרואיד להתעלם מהן. כך המשתמש לא ירוויח נקודות מפני שלחץ על הכפתור באמצעות המקשים הפיזיים.
נממש את מתודת ה-
onKey באופן הבא:
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
//Letting the user use the BACK button normally while avoiding other user input (preventing user from click on the "PUSH" button using keys)
if (keyCode == KeyEvent.KEYCODE_BACK)
return false;return true;
}
עלינו להבין כיצד מערכת האנדרואיד עובדת לפני שנוכל להבין את הקוד. כאשר המשתמש נמצא בפוקוס על הכפתור שלנו, כל פעם שהוא לוחץ על מקש כלשהו במכשיר הכפתור שלנו קורא למתודת ה-onKey הנ"ל. אם המתודה מחזירה אמת – הוא אומר לאנדרואיד שתפסיק להגיב לאירוע הלחיצה כי כבר הגבנו אליהם. אם המתודה מחזירה שקר – אנו מאשרים לאנדרואיד לבדוק מה לעשות אם אותה לחיצת מקש.
הקונספט הוא דיי פשוט: כאשר אנו רוצים לחזור אחורה אנו משתמשים בכפתור ה-Back של המערכת. לכן אנו רוצים שזה יהיה הכפתור היחיד שנגיב אליו בכדי לאפשר למשתמש לחזור לתפריט הראשי. אנו בודקים אם המשתמש לחץ על כפתור ה-Back אם כן – אנו מחזירים שקר ונותנים למערכת האנדרואיד להגיב כרגיל. אם לא – אנו מחזירים אמת או במילים אחרות אומרים למערכת האנדרואיד להתעלם מאותה הלחיצה.
הקוד האחראי לפעילות המשחקניצור את מתודת ה-startGame אשר אחראית להתחיל את המשחק:
void startGame() {
score = 0;
updateScore();
startTime = System.currentTimeMillis();
gameTimer.scheduleAtFixedRate(new GameTimerTask(), 0, updatePeriod);
stopperTimer.scheduleAtFixedRate(new StopperTimerTask(), 0, 50);
isPlaying = true;
}
מתודה זו מבצעת את הדברים הבאים:
- מאפסת את תוצאת המשחק ומעדכנת אותה.
- בודקת את הזמן הנוכחי ומכניסה אותו למשתנה startTime.
- מתחילה את שעון ה-gameTimer האחראי להזיז את הכפתור למיקומים שונים על המסך. הפרמטר הראשון הוא מחלקה שאנחנו יצרנו אשר אחראית לפעולה שיש לבצע ונסקור אותה בהמשך. הפרמטר השני אומר בעצם לשעון שאנו רוצים להתחיל את לבצע את הפעולה מעכשיו. הפרמטר השלישי מתאר את הקצב שבו הפעולה תחזור. כפי שראינו בהכרזת המשתנה פונקציה זו בעלת ערך של 500 אלפיות השנייה. או במילים אחרות חצי שניה. ניתן לקרוא על פונקצית ה-Timer.scheduleAtFixedRate שבה השתמשנו בעמוד הבא.
- מתחילה את שעון העצר (סטופר). הפרמטר הראשון מתאר את מחלקה המבצעת את פעולת בדיקת ועדכון הזמן. הפרמטר השני אומר שיש להתחיל את הפעולה מיד. הפרמטר השלישי אומר שיש לבצע עדכון לשעון העצר כל 50 אלפיות השנייה.
- משנה את ערך משתנה ה-isPlaying ל"אמת". כך כל פעם שנלחץ על כפתור ה-pushButton המשתמש יקבל נקודות מפני שהמשחק התחיל.
כפי שניתן לראות ה-gameTimer משתמש במחלקת ה-GameTimerTask. מחלקה זו אחראית לבצע את פעולת ההזזה של הכפתור למקומות אקראיים על המסך:
class GameTimerTask extends TimerTask {@Override
public void run() {
uiHandler.post(new Runnable() {
@Override
public void run() {
placePushButtonRandomly();
}
});
}
}
נוסיף את המחלקה הבאה לתוך מחלקת ה-GameActivity שלנו. משתנה ה-gameTimer שלנו קורא למחלקה זו לרוץ כל פרק זמן מסוים. מפני שהיא עובדת בהליך נפרד מהליך ה-UI נשתמש במשתנה ה-uiHandler שלנו בכדי "לזרוק" את ההודעה להליך הראשי לשים את הכפתור במקום אקראי על המסך. ההודעה שהיא זורקת להליך הראשי זה לקרוא למתודת ה-placePushButtonRandomly. אנו "זורקים" הודעות להליך הראשי מפני שאנו רוצים לעדכן רכיבים שהוא אחראי להציג אותם. אם נעדכן את רכיבים אלו דרך הליך שאינו ההליך הראשי שגיאה תתרחש.
נוסיף את מתודת ה-placePushButtonRandomly למחלקת ה-GameActivity שלנו:
void placePushButtonRandomly() {
Random rnd = new Random();int left = rnd.nextInt(gameZoneLayout.getWidth() – pushButton.getWidth());
int top = rnd.nextInt(gameZoneLayout.getHeight() – pushButton.getHeight());
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) pushButton.getLayoutParams();
layoutParams.setMargins(left, top, 0, 0);
pushButton.setLayoutParams(layoutParams);
}
מתודה זו מבצעת את הדברים הבאים:
- מחשבת את הערכים האקראיים של המיקום השמאלי והעליון של הכפתור. היא עושה זאת על ידי שימוש במחלקת ה-Random. מחלקה זו נותנת לנו מספר אקראי מ-0 ועד מספר מסוים. המיקום המקסימלי שנרצה למשל שהכפתור שלנו ינוע בציר ה-X יהיה עד הדופן הימני. לכן יהיה עלינו להסיר את רוחב הכפתור עם רוחב איזור המשחק. ניתן להסתכל באיור הבא ולהבין למה:
- לאחר החישוב המשתנים left ו-top מכילים את המיקום על ציר ה-X וה-Y שהכפתור שלנו יוצב. כעת כל מה שעלינו לעשות זה לשנות את תכונות ה-Margin הקיימות עם המשתנים האלו. לכן נשיג את הפרמטרים הנוכחיים של כפתור ה-pushButton על ידי שימוש בפונקציית ה-getLayoutParams, נשנה את תכונות ה-Margins על ידי שימוש בפונקציית ה-setMargins וניתן לרכיב ה-pushButton את הפרמטרים עם השינויים. מחלקת ה-LayoutParams מכילה בתוכה מידע על איך הרכיב שלנו יראה תחת ה-Layout שבו הוא נמצא. ניתן לקרוא על מחלקה זו בעמוד הבא.
כעת נעבור ל-stopperTimer. השתמשנו במחלקת ה-StopperTimerTask אשר אחראית לבצע את בדיקת ועדכון הזמן הנוכחי. נוסיף את מחלקת ה-StopperTimerTask למחלקת ה-GameActivity:
class StopperTimerTask extends TimerTask {@Override
public void run() {
uiHandler.post(new Runnable() {
@Override
public void run() {
long timePassed = System.currentTimeMillis() – startTime; //Calculating time passed from the game start
timeTextView.setText(getTimeString(System.currentTimeMillis() – startTime)); //Updating the stopper
//If the game time passed 30 seconds
if ((timePassed / 1000) >= 30)
stopGame(true);
}
});
}
}
כפי שניתן ליראות הדבר הראשון שאנו עושים זה "לזרוק" את פעולת הבדיקה והעדכון להליך הראשי זאת מפני שאנו רוצים לעדכן את תצוגת שעון העצר. ההליך הראשי מבצע את הפעולות הבאות:
- בודק את הזמן שעבר מתחילת הזמן באמצעות חיסור הזמן הנוכחי עם הזמן ההתחלתי. זוכרים את משתנה ה-startTime? בדיוק לכך השתמשנו בו! הזמן המוחזר לנו הוא באלפיות השניה.
- מעדכנים את התצוגה עם הזמן הנוכחי. משתנה ה-timeTextView הוא בעצם הרכיב שאחראי לתצוגת שעון העצר. כפי שניתן ליראות אנו משתמשים במתודת ה-getTimeString. זו מתודה שאנו יצרנו ומיד ניראה מה היא מכילה בתוכה. כל מה שעלינו לדעת זה שהיא ממירה זמן באלפיות השנייה למחרוזת שתציג את הזמן בשניות.
- בודקים אם הזמן עבר את מגבלת ה-30 שניות. אם כן אנו עוצרים את המשחק באמצעות מתודת ה-stopGame. זו היא מתודה שאנו כתבנו ומיד ניראה כיצד היא עובדת. הפרמטר היחיד שהמתודה מקבלת זה האם להציג את הדיאלוג עם תוצאות המשתמש או להפסיק את המשחק מבלי להציג כלום. אנו רוצים שלאחר שעבר זמן המשחק המשתמש יראה את התוצאה שלו ולכן הפרמטר מכיל פסוק אמת.
כעת ניראה מה מתודת ה-getTimeString עושה. נוסיף את שני המתודות הבאות למחלקת ה-GameActivity:
String getTimeString(long milliTime) {
int seconds = (int) milliTime / 1000;
int milli = (int) (milliTime % 1000) / 10;return getClockString(seconds) + ":" + getClockString(milli);
}
String getClockString(int digit) {
if (digit < 10)
return "0" + digit;
return String.valueOf(digit);
}
המתודה העליונה היא המתודה שלה אנו קוראים כאשר אנו רוצים להציג את הזמן הנוכחי ברכיב תצוגת הזמן (timeTextView). אלו הדברים שהמתודה עושה:
- ממירה את הזמן שסיפקנו לה באלפיות השניות וממירה אותו לשניות. היא עושה זאת על ידי חילוק אלפיות השנייה ב-1000 וכך היא משיגה את מספר השניות שעברו.
- משיגה את מאיות השנייה של אותה השנייה על ידי השגת שארית החלקית ב-1000 וחילוק שלה ב-10. על ההסבר המתמטיקאי לא נעבור.
- לבסוף הפונקציה מחזירה מחרוזת בפורמט של שניות : מאיות. היא עושה זו על ידי שימוש בפונקציית ה-getClockString אשר עושה את הדבר הפשוט הבא: אם המספר שהיא מקבלת קטן מ-10 היא מוסיפה לו 0 בצדו השמאלי ומחזירה אותו בתור מחרוזת. אם המספר גדול מ-10 היא מחזירה אותו כמו שהוא רק בתור מחרוזת.
כעת נעבור על המתודה האחראית להפסקת המשחק. נוסיף את מתודת ה-stopGame למחלקת ה-GameActivity:
void stopGame(boolean showGameOver) {
isPlaying = false;gameTimer.cancel();
gameTimer = new Timer();
stopperTimer.cancel();
stopperTimer = new Timer();
if (showGameOver)
showDialog(Dialogs.DIALOG_GAMEOVER);
}
מתודה זו מקבלת פרמטר אחת (אמת/שקר). אם הפסוק הוא פסוק אמת המתודה עוצרת את המשחק ומציגה דיאלוג Game Over עם מספר הנקודות שהמשתמש צבר. אם הפסוק הוא פסוק שקר המתודה עוצרת את המשחק אך לא מציגה שום דבר. מתודה זו מבצעת את הדברים הבאים:
- משנה את משתנה ה-isPlaying לשקר. המשחק נגמר ועלינו לחסום את המשתמש מלקבל נקודות נוספות.
- מפסיקה את שעון ה-gameTimer ושעון ה-stopperTimer. היא מאתחלת אותן מחדש בכדי שלא תתרחש שגיאה כאשר נרצה להשתמש בהם שוב.
- בודקת את הפרמטר שסיפקנו לה – אם הוא פסוק אמת נציג את דיאלוג ה-Game Over.
הצגת דיאלוג למשתמש בתום המשחקבכדי שנוכל להבין כיצד האפליקציה שלנו מציגה דיאלוג עלינו להבין איך נוצרים דיאלוגים וכיצד אנו קוראים להם. ניתן לקרוא על דיאלוגים
בעמוד הבא. כעת לאחר שהבנו כיצד דיאלוגים עובדים נוסיף את שורות הקוד הבאות למחלקת ה-
GameActivity:
class Dialogs {
public final static int DIALOG_GAMEOVER = 0;
}@Override
protected Dialog onCreateDialog(int id) {
Dialog diag = null;
switch (id) {
case Dialogs.DIALOG_GAMEOVER:
return new AlertDialog.Builder(this)
.setTitle("Game Over!")
.setMessage("Your score is: " + score + "!")
.setPositiveButton("Accept", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { dialog.cancel(); }
})
.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) { finish(); }
})
.create();
}
return diag;
}
יצרנו מחלקה בשם Dialogs אשר מכילה ערכים קבועים של כל דיאלוג. במילים אחרות – לכל דיאלוג שאנו רוצים להציג נתנו מספר. כך יותר קל להתייחס לדיאלוגים כאשר אנו משתמשים במתודת ה-showDialog. במתודת ה-stopGame מופיעה השורה הבאה:
showDialog(Dialogs.DIALOG_GAMEOVER);
השורה הנ"ל אומרת לאנדרואיד את הדבר הבא: תקרא למתודת ה-onCreateDialog עם הפרמטר המסופק. פונקציית ה-onCreateDialog בודקת את הפרמטר ומחזירה אובייקט Dialog לפי המספר שסופק. לאחר מכן מערכת האנדרואיד אחראית להציג את הדיאלוג שחזר ממתודת ה-onCreateDialog.
את הדיאלוג אנו יוצרים באמצעות מחלקת ה-
AlertDialog.Builder. ניתן לקרוא על השימוש במחלקה זו
בעמוד הבא. הדיאלוג שיצרנו מציג למשתמש הודעה שהכותרת שלה הוא "
Game Over". ההודעה המופיעה בתוך הדיאלוג אומרת למשתמש מה התוצאה שלו. הדיאלוג בנוסף מכיל כפתור
Accept. כאשר הדיאלוג נסגר האפליקציה חוזרת למסך הראשי (
GameActivity) באמצעות קריאה למתודה
finish() אשר סוגרת את החלון הנוכחי ומציגה את החלון הקודם שניראה.
קריאה למתודות בסדר הנכון
כאשר ה-GameActivity שלנו עלה ומוכן להתחלת המשחק עלינו להשתמש במתודת ה-startGame. כאשר ה-GameActivity שלנו כבר לא ניראה עלינו לעצור את המשחק על ידי שימוש במתודת ה-stopGame.
נוסיף את המתודה הבאה למחלקת ה-GameActivity:
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);if (hasFocus)
startGame();
else
stopGame(false);
}
מתודה זו נקראת כאשר החלון שלנו עבר בין אחד מן המצבים הבאים:
- עלה לגמרי והמשתמש כרגע נמצא בפוקוס עליו.
- החלון אינו ניראה למשתמש ואיבד פוקוס. יש לכך סיבות רבות כמו: המשתמש נעל את המכשיר, חזר לתפריט הראשי או לחץ על כפתור הבית שהביא אותו למסך הבית של המכשיר. ניתן להבחין באיזה מצב אנו נמצאים על ידי הפרמטר ה-hasFocus. פרמטר זה יהיה פסוק אמת אם המשתמש כרגע נמצא במצב הראשון ויכיל פסוק שקר אם המשתמש נמצא במצב השני.
כאשר המשתמש נמצא במצב הראשון נתחיל את המשחק. אם המשתמש נמצא במצב השני נעצור את המשחק. שימו לב כי אנו לא מציגים דיאלוג Game Over זאת מפני שזמן המשחק לא עבר.
מדריך איכותי בטירוף
תודה רבה!!
כל הכבוד
סוף סוף מדריך מ- א ועד ת.
מדריך מעולה !
ממש מדריך טוב ! תודה !
תודה@
נהדר תודה לך
איזה מקצוענות…כל הכבוד !
מדריך מעולה!
קצר וקולע, כל הכבוד!
הורדה של הכתבה ?
אפשר להוריד את הכתבה בפורמט pdf ?
כל הכבוד.
דרך אגב מישהו פעם ניסה לפתח עם flex?
זה מומלץ?
שי, יש אפשרות ליצור איתך קשר במייל?
אם כן, אשמח אם תשלח לי מייל לכתובת הבאה: [email protected]
אני זקוק לעזרה קטנה, שאני מאמין שלא תיהיה לך בעיה מיוחדת לעזור בה, תודה.
פששש
אחלה, כל הכבוד על ההשקעה.
hwzone – תמשיכו להביא כאלו כתבות !
מדריך מצויין אך
רק דבר אחד חסר לי וזה הסבר על google adsense ואיך משתמשים ומשלבים באפליקציה.
תותחים!!
כל הכבוד לhwzone תמשיכו להפציץ במדריכים מעולים!!
שאלה
לא הבנתי מאיפה מחלצים את resources.rar
קישור
איפה הקישור למדריך ?
מדריך מושקע לפיתוח אפליקציות
כל הכבוד על המדריך
רעיון לאפליקציה
שלום יש לי רעיון.
אפליקציה בשם המשמרת שלי . האפליקציה חיונית כיום בכל מפעל שמכבד את עצמו.כולנו בעלי סמארטפונים , אנחנו רוצים כל יום לדעת את המשמרת שלנו בעבודה . האפליקציה שאני בונה תסונכרן מול מחשבי החברה ותתריע על כל משמרת שאתה עושה. באיזה שעה מתחילה ובאיזה מסתיימת . שעת איסוף ועוד .. איזה משכורת אתה מקבל , כמה שעות אתה עובד. כמה % יש תוספת , מי שמעוניין לבנות איתי את האפילקציה ולהתחלק ברווחים שייצור קשר.
מדריך מצויין !!יש אפשרות ליצור איתך קשר?
שי אשמח אם תיצור איתי קשר במייל יש לי כמה שאלות ואשמח אם תוכל לעזור לי
[email protected]
בעניין תוכנת הeclipse
מלבד החלון הראשי שנוצר עם הפרויקט שלנו (MainActivity) אשר יכיל את התפריט הראשי של המשחק, ניצור חלון נוסף אשר יכיל את המשחק עצמו.
נעשה זאת על ידי העתקת קובץ ה-MainActivity ושינוי שמו ל-GameActivity. כעת נעשה את אותו הדבר לקובץ ה-main.xml שבתיקיית ה-reslayout ונקרא לו game.xml.
אני חייב עזרה בזה לא הבנתי איזה קובץ בדיוק להעתיק מאיפה ולאיפה אשמח למי שיעזור לי . המייל שלי [email protected] תודה
כל הכבוד!!!! מאמר מעולה.
מדריך טוב,
אבל הקבצים להורדה לא עובדים.
אם אפשר לסדר/יש למישהו ויכול להעלות שוב…
תודה!