כיצד לכתוב את משחק האנדרואיד הראשון שלכם ב- Java

מְחַבֵּר: John Stephens
תאריך הבריאה: 1 יָנוּאָר 2021
תאריך עדכון: 19 מאי 2024
Anonim
How to Make a Tic Tac Toe Game in Android [Java 2020]
וִידֵאוֹ: How to Make a Tic Tac Toe Game in Android [Java 2020]

תוֹכֶן


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

מגדיר

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

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


באופן דומה, אנו רוצים גם להפוך את המשחק שלנו למסך מלא. הוסף את הקוד הבא ל- onCreate () לפני השיחה ל- setContentView ():

getWindow (). setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.requestWindowFeature (Window.FEATURE_NO_TITLE);

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

יצירת תצוגת המשחק שלך

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

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


אז שנה את השורה כדי לקרוא כך:

setContentView (GameView חדש (זה))

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

אז לחץ לחיצה ימנית על שם החבילה בהיררכיה שלך מצד שמאל ובחר חדש> כיתה. כעת תוצג בפניך חלון ליצירת הכיתה שלך ואתה הולך לקרוא לזה GameView. תחת SuperClass, כתוב: android.view.SurfaceView מה שאומר שהכיתה תירש שיטות - יכולותיה - מ- SurfaceView.

בתיבה הממשקים תכתוב android.view.SurfaceHolder.Callback. כמו בכל כיתה, כעת עלינו ליצור את הבנאי שלנו. השתמש בקוד זה:

פתיל MainThread פרטי; GameView ציבורי (context context) {סופר (context); getHolder (). addCallback (זה); }

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

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

עקוף עכשיו כמה שיטות:

@Orride שטח חלל ציבורי תלוי (מחזיק SurfaceHolder, פורמט int, רוחב int, גובה int) {} @ Override שטח חלל ציבוריCreated (מחזיק SurfaceHold) {} ​​@ הפוך שטח ריק לפומבי נהרס (מחזיק SurfaceHolder) {}

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

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

יצירת חוטים

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

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

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

הדבר המלא צריך להיראות כך:

המעמד הציבורי MainThread מרחיב את הנושא {שטח פנים פרטי מחזיק מחזיק; GameView פרטי פרטי; MainThread ציבורי (SurfaceHolder surfaceHolder, GameView gameView) {super (); this.surfaceHolder = שטח מחזיק; this.gameView = gameView; }}

Schweet. יש לנו כעת GameView וחוט!

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

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

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

וזה הולך למשהו קטן כזה:

@Orride הפעלת חלל ציבורי () {בזמן (פועל) {canvas = null; נסה {canvas = this.surfaceHolder.lockCanvas (); מסונכרן (surfaceHolder) {this.gameView.update (); this.gameView.draw (בד); }} לתפוס (חריג ה) {} סוף סוף {אם (קנבס! = null) {נסה {שטחHolder.unlockCanvasAndPost (קנבס); } לתפוס (חריג ה) {e.printStackTrace (); }}}}}

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

משטח מחזיק פרטי; GameView פרטי פרטי; ריצה בוליאית פרטית; בד קנבס סטטי ציבורי;

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

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

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

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

set voeling offRic (isRunning בוליאני) {running = isRunning; }

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

עדכון חלל ציבורי () {}

אנחנו גם צריכים התחל החוט! אנו הולכים לעשות זאת אצלנו משטח יצור שיטה:

@Orride שטח ריק לציבורCreated (מחזיק SurfaceHolder) {thread.setRunning (נכון); thread.start (); }

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

@Orride שטח חלל ציבורי הרוס (מחזיק SurfaceHold) {ניסיון בוליאני = נכון; בזמן (נסה שוב) {נסה {thread.setRunning (שקר); thread.join (); } לתפוס (InterruptException e) {e.printStackTrace (); } נסה שוב = שקר; }}

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

thread = MainThread חדש (getHolder (), זה); setFocusable (נכון);

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

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

עושה גרפיקה

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

@Orride לצייר חללים ציבוריים (בד קנבס) {super.draw (קנבס); if (canvas! = null) {canvas.drawColor (Color.WHITE); צבע צבע = צבע חדש (); paint.setColor (Color.rgb (250, 0, 0)); canvas.drawRect (100, 100, 200, 200, צבע); }}

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

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

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

שיעור זה עומד למשוך ספרייט על הבד וייראה כך

CharacterSprite מעמד ציבורי {תמונת Bitmap פרטית; CharacterSprite פומבית (bmp מפת סיביות) {image = bmp; } רישום חללים ציבוריים (בד קנבס) {canvas.drawBitmap (תמונה, 100, 100, null); }}

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

characterSprite = חדש CharacterSprite (BitmapFactory.decodeResource (getResources (), R.drawable.avdgreen));

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

characterSprite.draw (קנבס);

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

מה אם היינו רוצים לגרום לבחור הקטן הזה לעבור? פשוט: אנו פשוט יוצרים משתני x ו- y עבור מיקומיו ואז משנים את הערכים הללו ב- עדכון שיטה.

אז הוסף את ההפניות שלך CharacterSprite ואז צייר את מפת הסיביות שלך ב x, y. צור את שיטת העדכון כאן ועכשיו ננסה:

y ++;

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

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

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

עדכון חלל ציבורי () {x + = xVelocity; y + = yVelocity; if ((x & gt; screenWidth - image.getWidth ()) || (x & lt; 0)) {xVelocity = xVelocity * -1; } if ((y & gt; screenHeight - image.getHeight ()) || (y & lt; 0)) {yVelocity = yVelocity * -1; }}

יהיה עליכם גם להגדיר משתנים אלה:

פרטי int xVelocity = 10; פרטי int yVelocity = 5; private int screenWidth = Resources.getSystem (). getDisplayMetrics (). widthPixels; private int screenHeight = Resources.getSystem (). getDisplayMetrics () .hoogPixels;

אופטימיזציה

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

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

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

@Orride הפעלת חלל ציבורי () {זמן התחלה ארוך; זמן רב מיליס; זמן המתנה ארוך; זמן ארוך = 0; int frameCount = 0; יעד ארוך = 1000 / targetFPS; בזמן (פועל) {startTime = System.nanoTime (); בד = null; נסה {canvas = this.surfaceHolder.lockCanvas (); מסונכרן (surfaceHolder) {this.gameView.update (); this.gameView.draw (בד); }} לתפוס (חריג ה) {} סוף סוף {אם (קנבס! = null) {נסה {שטחHolder.unlockCanvasAndPost (קנבס); } לתפוס (חריג ה) {e.printStackTrace (); }}} timeMillis = (System.nanoTime () - startTime) / 1000000; waitTime = targetTime - timeMillis; נסה {this.sleep (waitTime); } catch (חריג ה) {} totalTime + = System.nanoTime () - startTime; frameCount ++; if (frameCount == targetFPS) {ממוצעFPS = 1000 / ((totalTime / frameCount) / 1000000); frameCount = 0; totalTime = 0; System.out.println (ממוצע FPS); }}}

כעת המשחק שלנו מנסה לנעול את ה- FPS ל- 60 ועליכם לגלות שהוא בדרך כלל מודד 58-62 FPS יציב למדי במכשיר מודרני. על אמולטור אם כי אתה עשוי לקבל תוצאה שונה.

נסה לשנות את ה 60 עד 30 ולראות מה קורה. המשחק מאט וזה צריך קרא עכשיו 30 בלוגקט שלך.

מחשבות סוגרות

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

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

הבאמדריך למתחילים לג'אווה

שיאומי אישרה מוקדם יותר בשבוע שעבר כי תציג טלפון עם מצלמה 108 מגה-בתים בשיתוף עם סמסונג. כעת, היצרנית הקוריאנית חשפה את החיישן המדובר, המכונה amung IOCELL Bright HMX....

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

בשבילך