יום רביעי, 30 בנובמבר 2011

לו רק היתה לי ציפור כועסת... (פיזיקה במשחקים חלק 1)


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


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


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


המנוע box2d הוא מנוע פופולארי למדי, הוא נבנה במקור ב C++, אבל יש לו המרות גם ל JAVA, גם ל objective C וגם לפלאש (actionscript). יש מן הסתם גם לשפות נוספות, לי אישית יצא לעבוד איתו בעיקר בפלאש, ובתכנות לאיפון. בתכנות לאיפון הוא מגיע בחבילה עם המנוע של cocos2d (שאולי גם עליו שווה לדבר בהזדמנות).


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


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


העולם הפיזיקאלי


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


לדוגמה בפלאש, אם יצרתם MovieClip שהוא סמל גרפי עם אפשרות לאנימציות, והצמדתם לו מחלקה (Class) אז המחלקה הזאת תחזיק את המידע ושליטה על האוביקט, וה MovieClip ייצג את הצד הויזואלי שלו, את ה Sprite שלו.


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


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


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

private function setupPhysicsWorld():void{
var gravity:b2Vec2 = new b2Vec2(0,30);
var allowSleep:Boolean=true;
PhysicsVars.world = new b2World(gravity, allowSleep);
PhysicsVars._contactListener = new MyContactListener()
PhysicsVars.world.SetContactListener(PhysicsVars._contactListener);
// debug draw
var debug_draw:b2DebugDraw = new b2DebugDraw();
var debug_sprite:Sprite = new Sprite();
this.addChild(debug_sprite);
debug_draw.SetSprite(debug_sprite);
debug_draw.SetDrawScale(PhysicsVars.RATIO);
debug_draw.SetFillAlpha(0.5);
debug_draw.SetLineThickness(3);
debug_draw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
PhysicsVars.world.SetDebugDraw(debug_draw);
PhysicsVars._debugDrawSprite = debug_sprite;
}

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




var gravity:b2Vec2 = new b2Vec2(0,30);
var allowSleep:Boolean=true;
PhysicsVars.world = new b2World(gravity, allowSleep);

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

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

PhysicsVars._contactListener = new MyContactListener()
PhysicsVars.world.SetContactListener(PhysicsVars._contactListener);

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

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

                       // debug draw
var debug_draw:b2DebugDraw = new b2DebugDraw();
var debug_sprite:Sprite = new Sprite();
this.addChild(debug_sprite);
debug_draw.SetSprite(debug_sprite);
debug_draw.SetDrawScale(PhysicsVars.RATIO);
debug_draw.SetFillAlpha(0.5);
debug_draw.SetLineThickness(3);
debug_draw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
PhysicsVars.world.SetDebugDraw(debug_draw);
PhysicsVars._debugDrawSprite = debug_sprite;

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

אנחנו מגדירים פה מה יצוייר, אייך יצוייר ואיפה. אני לא אכנס לעומק של הדברים, רק אני אנצל את ההזדמנות להסביר מושג ה RATIO. אצלי אני מחזיק אותו בתוך מחלקה PhysicsVars במקום שהוא נגיש בקלות לכל מחלקה בפרויקט. נהוג לכנות אותו PTM_RATIO כשהכוונה ל Points to Meter Ratio, יחס בין נקודות למטרים.

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

העולם של המשחק שלנו הוא קצת שונה מהעולם האמיתי יש לנו פיקסלים, שאנו נתיחס אליהם כנקודות, ויש את היחידות של העולם הפיזיקאלי. עכשיו נניח שגובה הדמות שאנחנו משחקים במשחק היא64 פיקסלים, אם נגדיר את ה PTM_RATIO כשווה ל 1, זה אומר שהפיזיקה תתיחס אל הדמות כאילו הגובה שלה הוא 64 מטר, והבהתאמה, לכל שאר האוביקטים במשחק. זה יכול לגרום לכל הפיזיקה במשחק להתנהג באופן מוזר מאוד. אבל אם ה PTM_RATIO שווה ל 30 למשל, אז גובה הדמות שלי הוא קצת מעל 2 מטר, זה אולי נשמע לכם עדיין גבוה, אבל ברמה פיזיקאלית, ההבדל בין זה לבין 1.80, או אפילו 1.50 מטר אינו כזה גדול. אז אפשר לצפות שהפיזיקה תתנהג פחות או יותר כפי שאנחנו נצפה.

במקרה של פלאש אני משתמש באמת ב PTM_RATIO ששווה ל 30. כשאני מתכנת לאיפון אני משתמש ב 32, מסיבות טכניות של נוחות  (וגם  כי זה ה default ב template של cocos2d עם box2d)


לולאת המשחק הפיזיקאלי

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


private function enterFrameHandler(e:Event):void{
. . .
// 10. handling the step and all the basics
var timeStep:Number = 1/60;
var velocityIter:int=4;
var positionIter:int=4;
// 20. doing step
PhysicsVars.world.Step(timeStep, velocityIter, positionIter);
// 30. update actors
for each (var tmpActore:Actor in _allActors){
tmpActore.updateNow();
}
PhysicsVars.world.ClearForces();
if(GameData.kSHOW_DEBUG_DATA){
PhysicsVars.world.DrawDebugData();
}
// 50.check and handle collisions
checkAndHandleCollisions();  
       

                           .  .  .

}

אוקי, אז אם כבר בניתם משחק או שניים בפלאש, אתם בטח מזהים את הפורמט של פונקציה. הפונקציה enterFrameHandler היא פונקציה שנקראת כל פעם שקורה event (אירוע) מסוג Event.EnterFrame. במילים אחרות היא נקראת כל פעם שהמחלקה נכנסת לפריים חדש... בקיצור, היא קורה כל הזמן, זה קוד שכל הזמן קוראים לו  כל הזמן בלולאה.

                        // 10. handling the step and all the basics
var timeStep:Number = 1/60;
var velocityIter:int=4;
var positionIter:int=4;
// 20. doing step
PhysicsVars.world.Step(timeStep, velocityIter, positionIter);


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

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

הזמן של הרגע הוא 1/60 למעשה 1/60 שניה, זאת בגלל שהמשחק שלי שואף לרוץ בקצב של 60 פריימים לשניה (FPS). 

ה  velocityIter, וה positionIter משמשים לקבוע כמה פעמים במהלך הצעד הזה, העולם הפיזיקלי יחשב מחדש את המהירות והמיקום של האוביקטים. מה זה אומר.... קצת קשה להסביר, אבל נניח שיש לי כדור, שנגע בקיר. הכדור נמצא חלקו "בתוך" הקיר, והעולם הפיזיקאלי למעשה צריך להזיז אותו, ולתת לו אנרגית תנועה (שתשפיע על ה velocity שלו - המהירות והכיוון שלו). עכשיו יתכן שברגע שנזיז אותו הוא יפגע בכדור אחר, שיחזיר אותו לכיוון הקיר, וכן הלאה. 
מובן שבאמצע צעד אחד במשחק, שאמור לקחת 1/60 שניה, אין לנו זמן לבדוק את כל האפשרויות האלה עבור כל האוביקטים בלי סוף.  לכן אנחנו מגבילים את החישובים האלה, על מנת שהמשחק "לא יתקע". בגדול זה אומר שככל שהמספרים האלה יותר גדולים, יש יותר סיכוי שהמשחק יתקע ויעשה לאגים בגלל חישובים, אבל שהתוצאות תהיינה יותר מדויקות. לעומת זאת ככל שהמספרים יותר קטנים, אנחנו נראה יותר אוביקטים "בתוך" אוביקטים אחרים, ויותר דברים שלא יראו הגיוניים. אז צריך לבחור במשהו באמצע שיתן ביצועים טובים גם מבחינת חישובים וגם מבחינת אייך שהמשחק נראה. 

                      // 30. update actors
for each (var tmpActore:Actor in _allActors){
tmpActore.updateNow();
}

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

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

                        PhysicsVars.world.ClearForces();
if(GameData.kSHOW_DEBUG_DATA){
PhysicsVars.world.DrawDebugData();
}

אני לא אכנס למה השורה הזאת חשובה: 


 PhysicsVars.world.ClearForces();

אתם יכולים ברוב המקרים להתייחס אליה כמשהו נתון.

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

יתכן שנחזור לזה בהמשך, ואני אראה לכם דוגמה לאיך משחק נראה עם debug draw ובלעדיו.

                        // 50.check and handle collisions
checkAndHandleCollisions();  

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

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

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

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

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


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




יום שלישי, 29 בנובמבר 2011

בעיות גדולות, פתרונות קטנים



בעיות גדולות, פתרונות קטנים




"פיצה ובירה הם רכיבים חיוניים בדיאטה המומלצת לרעיונות יצירתיים"








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


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


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




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


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


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


"הוא יכול לתת לכם לראות, אם הרעיון שהרגיש לכם הכי כיפי בעולם ברמת התיאוריה שווה משהו בפרקטיקה"


אם ניקח דוגמה מופרכת יכול להיות שאתם חושבים על איזה שהוא FPS עם tower defense ביקום של Framvile. רעיון מצויין ללא ספק, ועדיין יכול להיות שבשלב שהגיתם אותו,לא חשבתם עד הסוף על המעבר בין ירי מגוף ראשון לגידול עגבניות על גג המגדל. (כן, זו הנקודת תורפה העיקרית של הרעיון המבריק הזה). ונקודה זו יכולה להתגלות ככל כך בעייתית, שהיא תגרום לנטישת הפרויקט בהמשך הדרך, או לשינויים מהותיים באופן הבנייה שלו.


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


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



 "...הוא חיכה הרבה זמן ב"מגירה" וירטואליתֿֿ, עד שאני אלמד יותר על בניית משחקים פיזיקאלים עם Box2D."






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


לעומת זאת, היה משחק שחשבתי עליו בעבר, ששילב משחק פיזיקה עם משחקיות של שובר קירות. הדגם שלו, שהיה מוצלח בעיני ובעיני אחרים, ונעשה ב Game Maker, חיכה הרבה זמן ב"מגירה" וירטואליתֿֿ, עד שאני אלמד יותר על בניית משחקים פיזיקאלים עם Box2D. ולמעשה כיום אני עובד עם חברים ללימודים (יותר נכון חברות ללימודים) על משחק שמתבסס על המשחקיות של אותו פרוטוטיפ.




"...מה שהפך את הבחירה ללא משמעותית, ולמעשה הרס את הרעיון של מורכבות טקטית במשחק."


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


"היה לנו רעיון למשחק פלטפורמה שמבוסס על המשחקיות של The Lost Vikings, משחק שיצא מהחברה Silicon & Synapse, שלימים הפכה ל Blizzard".


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


לדוגמה, לפני כמה וכמה שנים הייתי חבר בצוות קטן של מפתחים בחברה בשם Koplay. למעשה היינו קבוצת חברים שכולם למדו מדעי המחשב בזמנו. היה לנו רעיון למשחק פלטפורמה שמבוסס על המשחקיות של The Lost Vikings, משחק שיצא מהחברה Silicon & Synapse, שלימים הפכה ל Blizzard. וחשבנו שזה יהיה נחמד לבנות את המשחק הזה כמשחק פרסומי, וכך לגייס תקציב לפיתוח שלו. אז אני יצרתי בזמנו אנימציות לדמות התינוק של במבה, ולדמויות של ביסלי, ויצרנו דגם קטן של המשחקיות בפלאש, ואיתו ניגשנו לאסם.
בסופו של דבר מסיבות שונות (בעיקר חוסר הצלחה של משחק פירסומי קודם של במבה) לא קיבלנו מהם מימון, אבל ראש הצוות לקח על עצמו אחריות גייס כסף, ובסופו של דבר הרמנו את המשחק The Dudes, שאפילו שווק בזמנו על ידי אטרי בארץ. (לצערנו ההשקעה לא חזרה, אבל אפשר להגיד שכולנו עשינו שם את הצעד הראשון והמשמעותי שלנו בפיתוח משחקים).


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


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






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


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


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


"עדיין יש מצב שעוד שבוע, שבועיים או חודש, תצטרכו לחזור על התהליך"




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


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


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


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


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


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



יום שישי, 18 בנובמבר 2011

עוד משחק?



עוד משחק?










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


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






"...האם אנחנו שוברים את התחושות האלה, או שאנחנו מעדיפים לשמר אותן..."










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


"אנחנו רוצים לשמר את תחושת ההנאה מהמשחק"








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


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


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


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


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


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




"סצינת מעבר, שמצד אחד נותנת לו לנוח קצת, אבל מצד שני מעוררת מחדש את העניין שלו במשחק"


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


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




"אפשר לעשות פשוט restart"






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


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


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


"אפילו אם השחקן הוא באמת חסר סבלנות,  הכפתורים מופיעים כל כך מהר, כך שאפילו שחקן קצר רוח יכול להמשיך לשלב הבא תוך פחות משנייה"






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


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


"מה שקורה במעבר משאיר את השחקן בתחושה שהוא היה בה בעת ששיחק"




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


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


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


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


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


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


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


מן הסתם, להעביר את fruit ninja לקינקט היה רעיון אדיר, מה יותר טוב מלתת לשחקן להזיז את הידים במהירות כדי לחתוך פירות על המסך, גם כייף, גם אינטואיטיבי, והאמת שגם קצת מעייף in a good way - אבל כל זה סבבה. ובכל זאת המפתחים עשו טעות אחת קטנה לכאורה, אבל קריטית, הם השאירו את מנגנון השליטה בתפריטים, זהה לזה של המשחק באיפון. 


"בלי להגזים - זו חוויה די נוראית. ולמרות שנהניתי יחסית לשחק במשחק, השטות הזאת גרמה לי לעזוב אותו די מהר."


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

בלי להגזים - זו חוויה די נוראית. ולמרות שנהניתי יחסית לשחק במשחק, השטות הזאת גרמה לי לעזוב אותו די מהר. 


היו לי עוד כמה דוגמאות בנושא, רעות וטובות. אבל בין Angry Birds, ל  Cut the Rope ל Fruit Ninja - נראה לי שמצינו. הנושא הזה הוא רק חלק קטן מהמכלול של הנושאים שקשורים לחווית משתמש טובה במשחק. אבל אני רואה אותו כמאוד חשוב, כיוון שלפעמים אנחנו כל כך מתאמצים לתת לשחקן חוויה טובה צבעונית וכיפית בתוך הגיים פלי, שאנחנו שוכחים כמה חשוב זה פשוט לדאוג שהוא גם ישאר עם ההרגשה הזאת..



יום שני, 14 בנובמבר 2011

שיווק - its a bitch



"זה המקום שלי לדבר,  כמו כל ישראלי טוב, על משהו שאני לא מבין בו"




שיווק - its a bitch...


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


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


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




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










רק שלשום הייתי בכנס של גוגל ואנדרואיד (תודה ליובל ספיר על הכניסה, ומצטער שלא מצאתי לך אפור, והמבין יבין) יצא לי לפגוש כמה מחברי, איתם יצא לי לעבוד בעבר בהייטק. [ הכנס כאן shoutout לרנן, ולמייק] .  מן הסתם חלק גדול מהכנס היה ממוקד אנדרואיד, ובין השאר שמעתי כמה הצעות לעבור לפיתוח לאנדרואיד, או לגרסאות מוביל עתידיות של windows. עכשיו, זה לא שאני לא מבין, שהשווקים האלה טומנים בתוכם אפשרויות חדשות ליצור ולהתפתח, אבל להגיד לכם את האמת, אחרי שכבר למדתי די טוב, ליצור משחקים שאני אוהב עם objective c ו cocos2d. ממש אבל ממש לא בא לי להחליף כיוון כל כך מהר. 


ללמוד לתכנת לאייפון עם  objective c  ו cocos2d זה היה לא פשוט. זה היה ללמוד סינטקט שונה, זה היה ללמוד מחדש להתמודד עם ניהול זיכרון (מה שלא ממש עשיתי מאז שתכנתתי ב C בלימודים) ולהתמודד עם זה, שזה לא תכנות עם מנוע, ושצריך לבנות כלים, מסויימים, רק כדי שתוכל לדעת לפחות חלקית אייך דברים נראים על המסך. באמת, לתכנות הזה יש קשיים, ואני לא מישהו שמפחד מללמוד שפה חדשה. כבר קשה להפתיע אותי אחרי בייסיק, C++, ג'אווה, פיטון, C#,  שלא לדבר על actionscript 2 ו- 3 ואפילו קצת XNA ושפת התכנות לתוכנת התלת מימד מאיה. אבל אני מודה, להכנס ל אובג'קטיב  C היה קצת קשה, אחרי הכל זה כיוון התפתחות שונה של שפות, מהצד של העץ של C++, ג'אווה ו actionscript. אבל למדתי לאהוב את השפה הזאת, והיום אני כבר מסוגל לעשות משחקים פיזיקאליים די ממגניבים תוך זמן קצר.


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




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


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


"משחק טוב + כסף לשיווק != המון כסף"














ובואו אני אספר לכם עוד אמת קטנה שאתה מכירים:


משחק טוב + כסף לשיווק != המון כסף


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






"משחקים פחות טובים, עם תוכן יותר דליל יכולים להצליח יותר פשוט כי הם שוקלים פחות מהמשחק המושקע שלכם. "












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






" - Marketing is underrated."










אז זרקתי פה כל מיני דברים של שיווק, וכל מיני בעיות, וזה אולי נשמע כאילו יש לי התחלה של הבנה מה אמורים לעשות בשיווק של משחק, אבל בתחלס - ממש לא. זו בעיה אמיתית. ולהגיד את האמת, אני לא מתכוון לטפל בה יותר מידי. אני מתכנת, ואני Game Designer ואני גם tester ובונה שלבים אם צריך, אבל שיווק משחקים, זה משהו שגדול עלי. אני נאלץ להשאיר את החלק הזה של העבודה לאנשים אחרים. כך שיש לי רק דבר אחד נוסף להגיד על שיווק - Marketing is underrated.


לדעתי שיווק זה משהו שצריך להתחיל לעבוד עליו מ Day 1. צריך להשקיע בו לא פחות מתכנות ו ART , וצריך להתייחס אליו כדבר החשוב ביותר. לעשות משחק, לא משנה כמה טוב, ואז להתחיל לעבוד על השיווק שלו - זו טעות. צריך שיהיו אנשים בחברה  שזה מקצועם, ושמרוכזים בזה יומם בלילה, ועדיף גם שיהיו טובים בזה. זו האמת העצובה קצת, אבל שטויות - אנחנו אוהבים אתגרים. 
אם היינו רוצים חיים רגועים, וכסף קל היינו עובדים בהיי טק... טוב, לא באמת. אין שום דבר קל בלהיות אומן, אבל לעבוד על דברים שלא אתה חשבת עליהם, ושאתה לא באמת תורם 110% מהיכולות שלך כדי לעבוד עליהם. והייטק לא באמת כזה קל, עובדה שפחות מ 10% עוסקים בזה. אז אם כבר עובדים קשה, עדיף כבר להתאמץ ולעבוד על החלומות שלנו. 


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


שפי