אנימציה בסיסית


פורסם ב 05/06/2010 ע"י האקדמיה לפיתוח לאנדרואיד

אנדישלום חברים יקרים!

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

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

על ההצלחה שלך במבחן אני רוצה להגיד לך, "ori", אתה תותח, אין אין עליך, מתה עליך, אתה הגדול מכולם.

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

אז בואו נחזור לנושא השיעור שלנו, אנימציה בסיסית.

קדימה לעבודה

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

אנדי, נראה שאתה מדבר על "ריבוי תהליכים"! זה נושא כל כך מרתק! אני יכול לדבר שעות על תקשורת בין תהליכים, Deadlock-ים, Critical Sections, שלא לדבר על Semaphor-ים ו- Mutex-ים.

אנדיפרופסור, אתה תבריח לנו את כל הקוראים!
בוא נסתפק בהסבר בסיסי על Process-ים ו- Thread-ים, ונמליץ לקוראינו הנאמנים לחפש ברחבי הרשת עוד על נושאים מתקדמים אלו.

רוב מערכות ההפעלה המודרניות, ובכלל זה אנדרואיד, מאפשרת לנו להריץ קטעי קוד במקביל באמצעות Process-ים ו- Thread-ים.

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

Thread – זהו קטע קוד הבסיסי ביותר שמערכת ההפעלה מסוגלת להריץ כיחידת קוד עצמאית. כל Process יכול להכיל Thread אחד או יותר.

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

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

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

אני פשוט לא מאמינה! אני יוצאת להשתלמות קצרה באקדמיה ללשון העברית, וכל ההשקעה בחינוך שלכם יורדת לטימיון! כל כך הרבה מילים לועזיות נופלות עלי כמבול! ואני לא מדברת עליך, פרופסור - אתה כבר מקרה אבוד למערכת החינוך, אבל אנדי?! אתה??? למה Thread? מדוע אינך יכול להשתמש במונח שהוטבע ע"י האקדמיה רק בשנת תשס"ז?? תהליכון

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

טוב, נחזור לשיעור.
בואו ונפתח את תַּהֲלִיכוֹן הראשון שלנו.

שלב א – הרחבת מחלקת הכדור

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

כיוון תזוזת הכדור על ציר המסך

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

להלן הקוד החדש (והמורחב) של מחלקת הכדור

[sourcecode language="java"]
package iAndroid.pingPong;

public class Ball {
private int x;
private int y;

private int maxWidth;
private int maxHeight;

private boolean movingRight;
private boolean movingBottom;

// Receive the start position of the ball and screen dimensions
public Ball (int startX, int startY, int screenWidth, int screenHight)
{
this.x = startX;
this.y = startY;

this.maxWidth = screenWidth;
this.maxHeight = screenHight;

this.movingBottom = false;
this.movingRight = false;
}

// Return the ball horizontal position
public int getX()
{
return this.x;
}

// Return the ball vertical position
public int getY()
{
return this.y;
}

// Moving the ball one step.
public void moveBall()
{
// Moving the ball
if (movingRight)
this.x++;
else
this.x–;

if (movingBottom)
this.y++;
else
this.y–;

// Check if we need to change the ball direction horizontally
if (this.x >= this.maxWidth)
this.movingRight = false;

else if(this.x <= 1)
this.movingRight = true;

// Check if we need to change the ball direction vertically
if (this.y >= this.maxHeight)
this.movingBottom = false;
else if (this.y <= 1)
this.movingBottom = true;
}
}
[/sourcecode]

בואו נעבור על הקוד החדש שלנו:
שורות 7-8: הגדרה של משתנים פרטיים maxWidth ו maxHeight אשר יחזיקו את הרוחב והגובה המקסימליים בהם הכדור יכול לזוז.
שורה 10: הגדרה של משתנה פרטי בשם movingRight מסוג boolean, אשר אם יהיה true הוא יציין שהכדור זז ימינה ואם false, אז שהכדור זז שמאלה.
שורה 10: הגדרה של משתנה פרטי בשם movingRight מסוג boolean, אשר אם יהיה true הוא יציין שהכדור זז ימינה ואם false, אז שהכדור זז שמאלה .
שורה 11: הגדרה של משתנה פרטי בשם movingBottom מסוג boolean, אשר אם יהיה true הוא יציין שהכדור זז למטה ואם false, אז שהכדור זז למעלה.
שורה 14: הגדרת הבנאי של מחלקת הכדור, אשר מקבל 2 פרמטרים נוספים והם screenWidth המגדיר את אורך המסך, ואת screenHeight המגדיר את גובה המסך.
שורות 19-20: הכנסת אורך וגובה המסך, שהתקבלו כפרמטרים לבנאי, לתוך maxWidth ו maxHeight.
שורות 22-23: הגדרת הכיוון הראשוני אליו יזוז הכדור, והוא  למעלה (movingBottom = false) שמאלה (movingRight = false).
שורה 39: הגדרה של מתודה חדשה בשם moveBall אשר אחראית על הזזת הכדור.
שורה 42-43: אנו בודקים אם הכדור זז ימינה, ואם כן, אנו מוסיפים למיקום האופקי של הכדור 1.
שורות  44-45: אחרת, אנו מחסירים  מהמיקום האופקי 1.
שורות 47-48: אנו בודקים אם הכדור זז למטה, ואם כן, אנו מוסיפים למיקום האנכי של הכדור 1.
שורה 49-50: אחרת, אנו מחסירים  מהמיקום האנכי 1.
שורות 53-54: אנו בודקים האם הכדור נמצא בצידו הימני ביותר (המקסימלי) של המרחב, ואם כן אנו משנים את כיוונו.
שורות 56-57: אחרת, אנו בודקים האם הכדור נמצא בצידו השמאלי ביותר של המרחב, ואם כן אנו משנים את כיוונו.
שורות 60-61: אנו בודקים האם הכדור נמצא בחלקו התחתון ביותר (המקסימלי) של המרחב, ואם כן אנו משנים את כיוונו.
שורות 62-63: אנו בודקים האם הכדור נמצא בחלקו העליון ביותר של המרחב, ואם כן אנו משנים את כיוונו.

שלב ב – יצירת תהליך שמזיז את הכדור

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

אז מה צריך כדי ליצור Thread חדש?
פשוט מאד! כל מה שצריך זה ליצור מחלקה חדשה ולרשת את מחלקת Thread של ג'אווה.
צרו מחלקה חדשה (אתם כבר צריכים לדעת איך) בשם PingPongGame היורשת ממחלקת Thread

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

למחלקת האב, java.lang.Thread ישנה מתודה בשם run שאם אנחנו נממש אותה (כלומר, נרחיב אותה), נוכל לקרוא לה כדי "להפעיל" את ה Thread שלנו.
בנוסף, עלינו ליצור בנאי שמקבל את הכדור ואת ה View המרכזי של המשחק.
להלן קוד המחלקה PingPongGame:

[sourcecode language="java"]
package iAndroid.pingPong;

public class PingPongGame extends Thread {
private Ball gameBall;
private PingPongView gameView;

public PingPongGame(Ball theBall, PingPongView mainView)
{
this.gameBall = theBall;
this.gameView = mainView;
}

@Override
public void run()
{
while (1 < 2){
this.gameBall.moveBall();
this.gameView.postInvalidate();

try
{
PingPongGame.sleep(5);

}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

}
[/sourcecode]

כמו תמיד, בואו נעבור על קוד המחלקה:
שורות 4-5: הגדרת המשתנים הפרטיים gameBall ו gameView שיחזיקו את הכדור ואת ה View המרכזי.
שורות 7-11: הגדרת בנאי המחלקה שמיישב את המשתנים gameBall ו gameView.
שורה 14: מימוש של המתודה run אשר מוגדרת במקור בתוך מחלקת האב, Thread.
שורה 16: הגדרה של לולאת המשחק המרכזית, שאמורה (בשלב זה) לפעול כל עוד 1 קטן מ 2 (כלומר, לולאה אין-סופית).
שורה 17: קריאה ל moveBall כדי להזיז את הכדור.
שורה 18: קריאה למתודה postInvalidation בתוך ה View המרכזי, כדי להודיע שמשהו השתנה וצריך לצייר את המסך מחדש (בעזרת onDraw כמובן).
שורה 22: קריאה למתודה הסטטית sleep, כדי לגרום לה Thread שלנו "ללכת לישון" למשך 5 אלפיות השניה.

כמה הסברים נדרשים לגבי קטע הקוד הזה:

postInvalidation

בכך שיצרנו Thread נוסף שרץ במקביל לתוכנית המקורית, יצרנו בעצם מצב בו פיצלנו את התוכנה שלנו למספר חלקים (או מספר תהליכונים).
התהליכון PingPongGame, שאחראי לעדכן את מצב המשחק, רץ באופן עצמאי ומנותק מהתהליכון הראשי, אשר אחראי לציור המסך בפועל.
הקריאה למתודה postInvalidation היא דרך לתקשר בין התהליכונים ולהעביר מסר לתהליכון הראשי שה- View שלו דורש עדכון.

sleep

המעבד של המכשיר שלכם הוא יחסית מהיר. ככל הנראה הוא כל כך מהיר, שאם תריצו את התוכנית, הכדור פשוט יעוף לכל עבר מבלי שיהיה אפילו אפשר לעקוב אחריו.
למחלקת האב Thread ישנה מתודה סטטית בשם sleep, המאפשרת להכניס את התהליך למצב של "שינה" למשך זמן מסויים, לפני שהתהליך ממשיך לרוץ.
בצורה כזאת ניתן לווסת את מהירות המשחק. המתודה sleep מקבלת כפרמטר מספר, אשר מייצג את משך הזמן שהתהליך "ישן", באלפיות השניה (כלומר 1,000 = שניה אחת).

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

מחברים את כל החלקים, ומריצים!

כעת, נותר רק לחבר את השימוש במחלקת Ball המשודרגת שלנו ומחלקת PingPongGame החדשה לתוך התוכנית הראשית שלנו.
היכנסו למחלקה PingPong.java ועדכנו את הקוד שיראה כך:

[sourcecode language="java"]
package iAndroid.pingPong;

import android.app.Activity;
import android.os.Bundle;

public class PingPong extends Activity {
private PingPongView gameView;
private Ball gameBall;
private PingPongGame gameThread;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Getting the screen width & height
int screenWidth = this.getWindowManager().getDefaultDisplay().getWidth();
int screenHeight = this.getWindowManager().getDefaultDisplay().getHeight();

// Creating the ball
gameBall = new Ball(screenWidth / 2, screenHeight / 2, screenWidth, screenHeight);

// Creating the ball view, and giving it the gameBall as a parameter
BallView ballView = new BallView(this, gameBall);

// Creating the game view
this.gameView = new PingPongView(this);

// Give the gameView our ballView.
gameView.setBallView(ballView);

// Setting the gameView as the main view for the PingPong activity.
setContentView(gameView);

gameThread = new PingPongGame(gameBall, gameView);

// Starting the thread !
gameThread.start();

}

}
[/sourcecode]

ושוב, הסבר:
שורות 7-9: יצירת משתנים פרטיים אשר יחזיקו לנו את ה- View של המסך, את הכדור ואת ה Thread של המשחק.
שורות 17-18: שמירת גודל המסך של המכשיר או האמולטור בו אנו מריצים את התוכנה בתוך המשתנים (ותודה למשתמש ididid שסיפק הסבר על כך בפורום)
שורה 21: יצירת עצם חדש מסוג Ball, אשר נקודת ההתחלה שלו היא אמצע המסך ובנוסף אנו מעבירים לו את גבולות המסך עצמו.
שורות 23-33: יצירת ה- View-ים השונים של המשחק, באופן זהה למה שעשינו בשיעור שעבר.
שורה 35: יצירת אובייקט gameThread מסוג PingPongGame שיפעל כתהליכון שירוץ ברקע.
שורה 38: הפעלה של PingPongGame בתהליכון, שרץ ברקע.

זה הכל!
כעת הריצו את המשחק ותראו במו עיניכם את הכדור מקפץ לו מצד לצד.
נסו לשנות את מהירות הכדור ע"י שינוי המספר במתודה sleep (או בטלו אותה כליל) ותראו כיצד הכדור מתנהג.

ועכשיו תלמידים יקרים, מספר אתגרים, עד לשיעור הבא: 1. הוסיפו לקוד את המחלקה של המחבט/ים ודאגו לכך שהמחשב "ישחק" פינג פונג עם עצמו. כלומר, שהמחבט/ים יכה/ו בכדור בכל פעם שהוא מגיע לצד שלו. 2. הוסיפו "אינטיליגנציה מלאכותית" אשר גורמת למחבטים לזוז בצורה כזאת, שהכדור יפגע בכל פעם בחלק אחר של המחבט לדוגמא, פעם הוא יפגע ממש באמצע המחבט, פעם בפינה הימנית ופעם בפינה השמאלית. 3. לבסוף, הוסיפו לוגיקה שמשנה את זווית התזוזה של הכדור, בהתאם לאיפה שהוא פגע במחבט. לדוגמא אם הכדור פגע בפינה הימנית או השמאלית, אז הכדור יזוז בזווית חדה יותר לצדדים, בעוד שאם הוא פגע באמצע, הזווית תהיה חדה יותר לאמצע. נסו ליצור מגוון זוויות שונות ולא רק שלוש. כל אתגר הוא ברמת קושי שונה, כאשר הראשון הוא אתגר בסיסי, השני בינוני/קשה והשלישי קשה. טיפ! לשם ביצוע אתגר מספר 2, נסו להישתמש במחלקה Random, היוצרת מספרים אקראיים.

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

בין הפותרים נכונה נגריל תמונה אישית של הפרופסור בבקיני!

עד לשיעור הבא חברים, להית'!

Share

האקדמיה לפיתוח לאנדרואיד

בואו ללמוד לפתח לאנדרואיד! אתם בטח זוכרים אותי בתור Andy מהבלוג הישן!

11 Comments

  1. Tweets that mention שיעור ז’ – אנימציה בסיסית - האקדמיה ללימודי פיתוח באנדרואיד -- Topsy.com
    07/06/2010 בשעה 00:50

    […] This post was mentioned on Twitter by ben amsallem, iAndroid.co.il. iAndroid.co.il said: שיעור ז' – אנימציה בסיסית | בלוג האקדמיה http://iandroid.co.il/academy/2010/06/05/course1-lesson7/ […]

  2. יואב
    21/06/2010 בשעה 06:25

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

    1. אנדי
      21/06/2010 בשעה 06:44

      תודה רבה.
      מקווים לראות אותך משתתף פה ובפורום הפיתוח של הפורטל

  3. ערן
    10/08/2010 בשעה 15:56

    המחלקה של הBall לא משהו האמת..
    יש סיבה לעשות getX ו getY במקום להפוך את המשתנים x ו-y לpublic?
    חוץ מזה שהכדור לא נוגע בקצוות המסך תמיד, לפעמים הוא יוצא ממנו..
    פתרתי את זה כמובן אבל לדעתי כדאי להוסיף את זה למאמר.

    הינה הפתרון שלי:

    //check if touching the bounds
    if (this.x = this.screenWidth-this.SIZE) moveRight = false;
    if(this.y = this.screenHeight-this.SIZE*4) moveDown = false;

    דרך אגב, איפה נמצא הXY של העיגול? במרכז שלו? מימין לו? כי אם זה היה כמו ב Graphics הרגיל של JAVA לא הייתי נדרש לעשות this.x <= this.SIZE אלא פשוט הייתי עושה this.x <= 0 וזה היה בסדר..

  4. אנדי
    10/08/2010 בשעה 17:37

    היי ערן!

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

    לשאתך השניה, ה- xy של העיגול נמצא במרכז שלו + הרדיוס של הכדור. אם לא תשתמש בהם אז הכדור יצא מגבולות המסך, עד למרכזו, טרם שינוי כיוון התזוזה.

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

    תודה ! 🙂

  5. חיים
    13/08/2010 בשעה 04:16

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

    בברכה,
    חיים.

  6. ערן
    21/08/2010 בשעה 12:16

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

  7. אנדי
    21/08/2010 בשעה 16:28

    לא תוכנה חיצונית אלה מחלקה חיצונית וזה לא תקין מבחינת הנדסת תוכנה.
    קבל 2 דוגמאות לבעיות שיכולות להיווצר:
    1. תחשוב שאתה עובד על תוכנה עם עוד צוות של 5 אנשים וכל אחד אחראי לפתח חלק אחר של התוכנה.
    אתה אמור לפתח את המחלקה של הכדור ולהעביר אותה למישהו אחר.
    המישהו האחר הזה מחליט "לקצר את הדרך" ובמקום להשתמש במתודות setX ו- setY, הוא ישר משנה את X ואת Y אבל הוא לא יודע שאתה שב- setX אתה עושה עוד מספר דברים אחרים, ולא רק מעדכן את X. אין לו דרך לדעת את זה לכאורה ומכאן שיכול לקרות נזק.

    2. הדבר יכול לקרות גם לך, כאשר אתה מפתח פרויקט גדול ופשוט שוכח את הלוגיקה ששמת מאחורי setX ו- setY ואתה "מתפתה" פשוט לשנות את הערים X ו- Y.

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

  8. ניב
    23/02/2011 בשעה 09:14

    שלום שלום
    במחלקת Ball מוגדר גודל שולחן הפינג פונג. אני חושב שזהו מידע שמגיע מחוץ למחלקה.
    יכול להיות שנכון יותר להגדיר אותו במחלקת pingpong?
    המחלקה שקובעת את "עולם המשחק" – מספר הכדורים, צבעם וגם גודל השולחן..
    הבעיה היא שבצורה כזו, נכון יותר יהיה גם להגדיר מחלקה שאחראית על תנועת הכדור (כמו מחלקה שאחראית על מראה הכדור)
    נראה לי שהסתבכתי כאן יותר מדי..

  9. רמי
    15/06/2011 בשעה 12:39

    תגובתאהבתי!
    משיעור חשיעור הרמה עולה וגם ההומור
    אהבתי את ההתפרצות של המורה ללשון:)

  10. viva_d
    18/08/2011 בשעה 03:55

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

השאר תגובה