HWzoneHWzoneHWzone
  • ראשי
  • כתבות פופולריות
  • הגדרת התראות
  • מחשבים
    מחשבים
    הצג עוד
    כתבות מובילות
    משטח משלוח של כרטיסי מסך יוקרתיים במחסן מטענים בנמל תעופה, עם אריזות חסרות וניילון עטיפה קרוע
    חצי מיליון דולר נעלמו בשדה התעופה: שני משטחים של RTX 5090 אבדו
    20/10/2026
    הדרך להפסיק לשלם ולקחת בעלות: בנינו שרת AI מפלצתי מקומי
    22/08/2026
    מעבד שרתים גדול מועבר למגש בדיקה במפעל שבבים, כשמעבדי מחשבים ניידים ממתינים ברקע
    אינטל מעדיפה שרתים על מחשבים אישיים ומשנה את תוכניות הייצור
    02/11/2026
    כתבות אחרונות
    מתחרה חדשה ל-DLSS מבטיחה ביצועים מהירים עד פי 2.4
    13/11/2026
    מבצעי נובמבר 2026: שבעה דילים לעמדת הגיימינג, מעכבר Logitech ועד ROG Xbox Ally
    13/11/2026
    סיכום השבוע: NVIDIA, GTA 6 ועוד
    13/11/2026
    מבצעי נובמבר 2026: שבעה מסכי מחשב שבאמת ירדו במחיר
    12/11/2026
  • גאדגטים
    גאדגטים
    הצג עוד
    כתבות מובילות
    ניסיתי סמארטפון מתקפל בפעם הראשונה - התרשמויות משימוש Galaxy Z Fold8
    27/09/2026
    שחזור דיגיטלי של ה-iPod המקורי משנת 2001 מופיע בתוך דף אינטרנט במחשב נייד
    אפל מחזירה את ה-iPod המקורי לחיים, ומחביאה אותו באתר שלה
    25/10/2026
    הדמיה של מערכת הבית החכם החדשה של אפל עם מסך HomePad, רמקול HomePod mini ומזרים Apple TV 4K
    אפל חוזרת לסלון: שלושה מוצרים חדשים בדרך, כולל מסך חכם שיתחרה באמזון ובגוגל
    10/10/2026
    כתבות אחרונות
    גוגל משיקה משקפי Gemini ב-395 דולר, גם לבעלי אייפון
    14/11/2026
    וואטסאפ מוסיפה כפתור שימחק הודעות טקסט לאחר פתיחה אחת
    14/11/2026
    סיכום השבוע: NVIDIA, GTA 6 ועוד
    13/11/2026
    אחרי שש שנות עיכוב: אמזון משיקה רחפן אבטחה ביתי ב-250 דולר
    11/11/2026
  • גיימינג
    גיימינג
    הצג עוד
    כתבות מובילות
    קונסולת Xbox One ותיקה מחוברת לטלוויזיה המציגה משחק מודרני בעולם פתוח באמצעות הזרמה מהענן
    קונסולה מ-2013 תריץ את GTA 6, אבל מחשב גיימינג לא
    11/11/2026
    קונסולת PlayStation 5 לצד מסך המציג משחקי PC בתוך ממשק הקונסולה באמצעות Playden
    בלי מחשב ובלי סטרימינג: משחקי PC רצים ישירות על PlayStation 5
    27/10/2026
    המחשה של לוח אם בקונסולת משחקים עתידית עם שבבי זיכרון ואחסון חשופים
    ה-PlayStation 6 עשויה לעלות יותר מ-1,000 דולר
    20/10/2026
    כתבות אחרונות
    אחרי תשע שנים: Wolfenstein 3 הוכרז רשמית, ובלזקוביץ' חוזר
    13/11/2026
    21 משחקי Xbox מגיעים למחשב, כולל 11 כותרי Star Wars
    13/11/2026
    מבצעי נובמבר 2026: שבעה דילים לעמדת הגיימינג, מעכבר Logitech ועד ROG Xbox Ally
    13/11/2026
    סיכום השבוע: NVIDIA, GTA 6 ועוד
    13/11/2026
  • טכנולוגיה
    טכנולוגיה
    הצג עוד
    כתבות מובילות
    משאית הובלה מסחרית רגילה ועליה משטחים של חומרת מחשוב יקרה, להמחשת גניבת משלוח NVIDIA בשווי 11.4 מיליון דולר
    משאית אספה חומרה של NVIDIA ב-11.4 מיליון דולר ונעלמה
    07/11/2026
    מחשב נייד המריץ מערכת הפעלה ניסיונית שפותחה באמצעות סוכני בינה מלאכותית של Claude Fable 5.2
    אלף סוכני Claude בנו מערכת הפעלה בשמונה ימים
    10/11/2026
    Google's Gemini 4 Carbon Tops Every Other Model In All But Two Of Google's Benchmarks, Scoring 88.2 Percent On SEC-bench Pro Vulnerability Discovery
    גוגל מציגה את Gemini 4 Carbon: ראשון בדירוג, סגור לציבור
    29/10/2026
    כתבות אחרונות
    נתבים ישנים עצרו את ההמראות בכל ארה"ב: אלפי טיסות בוטלו
    14/11/2026
    ChatGPT מתחיל לשלם במקומכם: OpenAI משיקה ארנק לסוכני AI
    14/11/2026
    גוגל משיקה את Gemini 4 Hydrogen: מהיר פי 2.5 מהדור הקודם
    13/11/2026
    יותר מ-17 שעות של שיבושים: Microsoft 365 קורסת
    13/11/2026
  • ביקורות
    ביקורות
    הצג עוד
    כתבות מובילות
    הדרך להפסיק לשלם ולקחת בעלות: בנינו שרת AI מפלצתי מקומי
    22/08/2026
    ניסיתי סמארטפון מתקפל בפעם הראשונה - התרשמויות משימוש Galaxy Z Fold8
    27/09/2026
    מחשב ASUS Ascent GX10 מבוסס NVIDIA DGX Spark בסקירה: דמוקרטיזציה של מודלים מקומיים
    04/10/2026
    כתבות אחרונות
    ככה הגדרתי סביבת עבודה עבור שרת AI מפלצתי מקומי מבוסס Intel ARC
    03/11/2026
    מחשב ASUS Ascent GX10 מבוסס NVIDIA DGX Spark בסקירה: דמוקרטיזציה של מודלים מקומיים
    04/10/2026
    ניסיתי סמארטפון מתקפל בפעם הראשונה - התרשמויות משימוש Galaxy Z Fold8
    27/09/2026
    GIGABYTE GAMING A16 עם RTX 5060 - מה תקבלו בקטגוריה הזולה של מחשבי גיימינג ניידים?
    12/09/2026
  • ספיישלים
    • CES
      • CES 2026
      • CES 2025
      • CES 2024
      • CES 2023
      • CES 2022
      • CES 2020
      • CES 2019
      • CES 2018
      • CES 2017
      • CES 2016
      • CES 2015
      • CES 2013
      • CES 2012
      • CES 2011
      • CES 2009
    • Computex
      • Computex 2019
      • Computex 2018
      • Computex 2016
      • Computex 2014
      • Computex 2013
      • Computex 2012
      • Computex 2011
      • Computex 2010
      • Computex 2009
      • Computex 2008
      • Computex 2007
    • E3 2016
    • עשור לאתר המחשבים
    • CeBIT 2008
    • CeBIT 2007
  • פורומים
  • זכרונות
  • הפיד שלי
  • ניהול העדפות
  • ערוצים פרסומיים
עקבו אחרינו ברשתות
  • אודות האתר
  • צרו קשר
  • פרסם אצלנו
  • תנאי שימוש ומדיניות פרטיות
  • הצהרת נגישות
בקריאה עכשיו: מדריך: פיתוח אפליקציות לאנדרואיד
HWzoneHWzone
  • ראשי
  • כתבות פופולריות
  • הגדרת התראות
  • מחשבים
  • גאדגטים
  • גיימינג
  • טכנולוגיה
  • ביקורות
  • ספיישלים
    • CES
    • Computex
    • E3 2016
    • עשור לאתר המחשבים
    • CeBIT 2008
    • CeBIT 2007
  • פורומים
  • זכרונות
עקבו אחרינו
  • אודות האתר
  • צרו קשר
  • פרסם אצלנו
  • תנאי שימוש ומדיניות פרטיות
  • הצהרת נגישות
אפליקציותגאדגטיםמדריכים

מדריך: פיתוח אפליקציות לאנדרואיד

עדכון אחרון: 11/12/2015 בשעה 16:18
צוות האתר
25/05/2012
73 דקות קריאה
שיתוף
עקבו אחרינו ב-Googleהוסיפו את HWzone כמקור מועדףעקבו אחרינו בטלגרםכל הכתבות החדשות ישר לטלפון

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  בעמוד הבא.

 

 

 

עקבו אחרינו ב-Googleהוסיפו את HWzone כמקור מועדףעקבו אחרינו בטלגרםכל הכתבות החדשות ישר לטלפון
    • 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);

 

}

 

 

מתודה זו נקראת כאשר החלון שלנו עבר בין אחד מן המצבים הבאים:

 

    1. עלה לגמרי והמשתמש כרגע נמצא בפוקוס עליו.

 

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

 

 

 

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

העמוד הקודם1234567העמוד הבא

הצטרפו לערוץ הטלגרם שלנו!

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

הצטרפו עכשיו

גוגל משיקה משקפי Gemini ב-395 דולר, גם לבעלי אייפון
וואטסאפ מוסיפה כפתור שימחק הודעות טקסט לאחר פתיחה אחת
היום לפני 1-24 שנים ב-HWzone: Steam Machine, מחשב בתוך חרק ועוד
אחרי 28 שנה: אפל סוגרת את פורום התמיכה של המשתמשים
היום לפני 3-14 שנים ב-HWzone: Steam Deck OLED, חריץ המסך ועוד
תגיות:AndroidiPhoneYouTubeאינטרנטאנדרואידאפליקציותפיתוח
איך זה גורם לך להרגיש?
אהבתי!0
מצחיק!0
עצוב0
מופתע0
משועמם0
כועס0
טוען תגובות...

כתבות פופולריות

משאית הובלה מסחרית רגילה ועליה משטחים של חומרת מחשוב יקרה, להמחשת גניבת משלוח NVIDIA בשווי 11.4 מיליון דולר
משאית אספה חומרה של NVIDIA ב-11.4 מיליון דולר ונעלמה
07/11/2026
מחשב נייד המריץ מערכת הפעלה ניסיונית שפותחה באמצעות סוכני בינה מלאכותית של Claude Fable 5.2
אלף סוכני Claude בנו מערכת הפעלה בשמונה ימים
10/11/2026
משטח משלוח של כרטיסי מסך יוקרתיים במחסן מטענים בנמל תעופה, עם אריזות חסרות וניילון עטיפה קרוע
חצי מיליון דולר נעלמו בשדה התעופה: שני משטחים של RTX 5090 אבדו
20/10/2026
הדרך להפסיק לשלם ולקחת בעלות: בנינו שרת AI מפלצתי מקומי
22/08/2026
HWzoneHWzone
עקבו אחרינו
  • אודות האתר
  • צרו קשר
  • פרסם אצלנו
  • תנאי שימוש ומדיניות פרטיות
  • הצהרת נגישות