Як написати свою першу гру для Android на Java

Автор: John Stephens
Дата Створення: 1 Січень 2021
Дата Оновлення: 19 Травень 2024
Anonim
Урок 1.Создаем главный цикл LoopFW. Создание игры для Android на Java.
Відеоролик: Урок 1.Создаем главный цикл LoopFW. Создание игры для Android на Java.

Зміст


Існує безліч способів створити гру для Android, і один важливий спосіб - це зробити це з нуля в Android Studio з Java. Це дає вам максимальний контроль над тим, як ви хочете, щоб ваша гра виглядала та вела себе, і процес навчить вас навичкам, якими ви також можете скористатись у низці інших сценаріїв - чи створюєте ви екран заставки для програми, чи просто хочете додати кілька анімацій. Зважаючи на це, цей підручник покаже вам, як створити просту 2D гру за допомогою 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 робить для нас.


Але знову ж таки, це гра, що означає, що не потрібно мати вікна браузера або прокручувати подання рециркулятора. Замість цього ми хочемо натомість показати полотно. В Android Studio полотно точно таке ж, як і в мистецтві: це середовище, на якому ми можемо малювати.

Тому змініть цей рядок, щоб прочитати так:

setContentView (новий GameView (це))

Ви побачите, що це ще раз підкреслено червоним кольором. Але зараз якщо натиснути Alt + Enter, у вас немає можливості імпортувати клас. Натомість у вас є можливість творити клас. Іншими словами, ми збираємося створити свій власний клас, який визначатиме, що буде на полотні. Це те, що дозволить нам малювати на екрані, а не просто показувати готові погляди.

Тож клацніть правою кнопкою миші назву пакета у вашій ієрархії ліворуч та виберіть Новий> Клас. Тепер вам буде запропоновано вікно, щоб створити свій клас, і ви будете називати його GameView. Під SuperClass напишіть: android.view.SurfaceView що означає, що клас успадкує методи - його можливості - від SurfaceView.

У полі Інтерфейс (и) ви напишете android.view.SurfaceHolder.Callback. Як і у будь-якому класі, нам зараз потрібно створити наш конструктор. Використовуйте цей код:

приватна нитка MainThread; загальнодоступний GameView (контекст контексту) {super (контекст); getHolder (). addCallback (це); }

Кожен раз, коли наш клас викликається створити новий об’єкт (у цьому випадку наша поверхня), він запустить конструктор і він створить нову поверхню. Рядок "super" називає суперклас, а в нашому випадку це SurfaceView.

Додавши зворотний виклик, ми можемо перехоплювати події.

Тепер перекрийте кілька методів:

@Override public void surfaceChanged (тримач SurfaceHolder, формат int, ширина int, висота int) {} @ Oververide public void surfaceCreate (тримач SurfaceHolder) {} @ Oververide public void surfaceDestroyed (власник SurfaceHolder) {}

Вони в основному дозволяють нам переосмислити (звідси і назва) методи в надкласі (SurfaceView). Тепер у вашому коді не повинно бути більше червоних підкреслень. Приємно.

Ви тільки що створили новий клас, і кожен раз, коли ми посилатимемось на це, він створюватиме полотно для вашої гри, щоб намалювати. Заняття творити предметів, і нам потрібен ще один.

Створення ниток

Наш новий клас буде називатися MainThread. І його завдання полягатиме у створенні нитки. Потік по суті нагадує паралельну вилку коду, яка може працювати одночасно поряд із головний частина вашого коду. Ви можете мати багато ниток, що працюють відразу, тим самим дозволяючи речам відбуватися одночасно, а не дотримуватися суворої послідовності. Це важливо для гри, тому що ми повинні переконатися, що вона продовжує працювати безперебійно, навіть коли багато відбувається.

Створіть свій новий клас так само, як ви робили раніше, і цього разу він продовжиться Нитка. У конструкторі ми просто збираємось зателефонувати супер (). Пам'ятайте, що це супер клас, який є Нитка, і який може зробити все важке для нас. Це як створити програму для миття посуду, яка тільки дзвонить пральна машина().

Коли цей клас називається, він створить окремий потік, який працює як головне. І це від тут що ми хочемо створити наш GameView. Це означає, що нам також потрібно посилатися на клас GameView, а також ми використовуємо SurfaceHolder, який містить полотно. Отже, якщо полотно - це поверхня, SurfaceHolder - мольберт. І GameView - це те, що поєднує все це.

Повна річ повинна виглядати так:

MainThread публічного класу розширює нитку {приватний SurfaceHolder surfaceHolder; приватний GameView gameView; загальнодоступний MainThread (SurfaceHolder surfaceHolder, GameView gameView) {super (); this.surfaceHolder = surfaceHolder; this.gameView = gameView; }}

Щит. Тепер у нас є GameView і нитка!

Створення ігрового циклу

Тепер у нас є сировина, яка нам потрібна для гри, але нічого не відбувається. Сюди надходить ігровий цикл. В основному це цикл коду, який обходить і кругляє і перевіряє введення та змінні, перш ніж малювати екран. Наша мета полягає в тому, щоб зробити це максимально послідовним, щоб у кадрі не було заїкань чи гикавки, які я вивчу трохи пізніше.

На даний момент ми все ще в MainThread клас, і ми будемо заміняти метод із суперкласу. Цей є бігати.

І це щось подібне:

@Override public void run () {while (running) {canvas = null; спробуйте {canvas = this.surfaceHolder.lockCanvas (); синхронізований (surfaceHolder) {this.gameView.update (); this.gameView.draw (полотно); }} лов (виняток е) {} нарешті {if (canvas! = null) {try {surfaceHolder.unlockCanvasAndPost (canvas); } лов (виняток е) {e.printStackTrace (); }}}}}

Ви побачите багато підкреслення, тому нам потрібно додати ще кілька змінних та посилань. Поверніться до початку та додайте:

приватний SurfaceHolder surfaceHolder; приватний GameView gameView; приватний булевий біг; публічне статичне полотно полотна;

Не забудьте імпортувати полотно. Полотно - це те, на чому ми насправді будемо малювати. Що стосується "lockCanvas", то це важливо, оскільки саме воно по суті заморожує полотно, щоб ми могли на ньому намалювати. Це важливо, тому що в іншому випадку ви можете зробити кілька ниток, намагаючись намалювати на ньому відразу. Тільки знайте, що для редагування полотна потрібно спочатку замок полотно.

Оновлення - це метод, який ми збираємось створити, і саме тут веселі речі відбудуться згодом.

The спробуйте і улов тим часом - просто вимоги Java, які показують, що ми готові спробувати виправити винятки (помилки), які можуть виникнути, якщо полотно не готове тощо.

Нарешті, ми хочемо мати можливість запустити свою нитку, коли нам це потрібно. Для цього нам знадобиться інший метод, який дозволяє нам приводити речі в рух. Це те, що біг змінна призначена для (зауважте, що булева будова - це тип змінної, яка завжди є вірною або помилковою). Додайте цей метод до MainThread клас:

public void setRunning (булевий isRunning) {running = isRunning; }

Але на даний момент все одно слід виділити одне, і це оновлення. Це тому, що ми ще не створили метод оновлення. Тож поскакайте назад GameView а тепер додайте метод.

публічне оновлення недійсності () {}

Нам теж потрібно почати нитка! Ми будемо робити це в нашому поверхню метод:

@Override public void surfaceCreate (тримач SurfaceHolder) {thread.setRunning (вірно); thread.start (); }

Нам також потрібно зупинити нитку, коли поверхня зруйнована. Як ви могли здогадатися, ми вирішуємо це в поверхня знищена метод. Але бачачи, як насправді може знадобитися кілька спроб зупинити потік, ми збираємося поставити це в цикл і використовувати спробуйте і улов знову. Так:

@Override public void surfaceDestroyed (власник SurfaceHolder) {булева спроба = true; while (повторити) {try {thread.setRunning (false); thread.join (); } ловити (InterruptException e) {e.printStackTrace (); } повторити = помилково; }}

І нарешті, зверніться до конструктора та переконайтесь, що створити новий екземпляр своєї нитки, інакше ви отримаєте жахливий виняток нульового вказівника! І тоді ми зробимо GameView зосередженим, тобто він може обробляти події.

нитка = новий MainThread (getHolder (), це); setFocusable (true);

Тепер ти можеш нарешті насправді тестуйте цю річ! Правильно, натисніть запустити повинен насправді працювати без помилок. Підготуйся до того, що здується!

Це… це… порожній екран! Весь цей код. Для порожнього екрана. Але це порожній екран можливість. У вас є поверхня і працює з ігровим циклом для обробки подій. Тепер все, що залишилося, - це зробити щось. Це навіть не має значення, якщо ви до цього моменту не дотримувались усього підручника. Справа в тому, що ви можете просто переробити цей код, щоб почати робити славні ігри!

Робити графіку

Зараз у нас є порожній екран, на якому потрібно звернутись, все, що нам потрібно зробити, - це намалювати на ньому. На щастя, це проста частина. Все, що вам потрібно зробити, це перекрити метод малювання в нашому GameView клас, а потім додайте кілька гарних зображень:

@Override public void draw (Canvas canvas) {super.draw (полотно); if (canvas! = null) {canvas.drawColor (Color.WHITE); Фарба фарба = нова Paint (); paint.setColor (Color.rgb (250, 0, 0)); canvas.drawRect (100, 100, 200, 200, фарба); }}

Виконайте це, і тепер у вас повинен бути гарний червоний квадрат у верхньому лівому куті екрана, який інакше є білим. Це, безумовно, поліпшення.

Теоретично ви могли б створити майже всю свою гру, дотримуючись її всередині цього методу (і переважаючи) onTouchEvent обробляти вклад), але це не буде надзвичайно хорошим способом вирішити справи. Розміщення нової фарби всередині нашого циклу значно зменшить ситуацію, і навіть якщо ми поставимо її в іншому місці, додавши занадто багато коду до малювати метод став би потворним і важким для дотримання.

Натомість має набагато більше сенсу обробляти ігрові об’єкти своїми класами. Ми почнемо з того, який показує характер, і цей клас буде називатися Характер характеру. Вперед і зроби це.

Цей клас буде малювати спрайт на полотні і буде виглядати так

загальнодоступний клас CharacterSprite {приватне зображення Bitmap; загальнодоступний CharacterSprite (Bitmap bmp) {image = bmp; } public void draw (Canvas canvas) {canvas.drawBitmap (зображення, 100, 100, null); }}

Тепер, щоб скористатися цим, вам потрібно спочатку завантажити растрову карту, а потім викликати клас GameView. Додати посилання на приватний характерSprite characterSprite а потім у поверхню метод, додайте рядок:

znakSprite = новий CharacterSprite (BitmapFactory.decodeResource (getResources (), R.dravable.avdgreen));

Як бачимо, растровий файл, який ми завантажуємо, зберігається в ресурсах і називається avdgreen (це було з попередньої гри). Тепер все, що вам потрібно зробити, - це передати цей растровий файл до нового класу в малювати метод за допомогою:

characterSprite.draw (полотно);

Тепер натисніть запустити, і ви повинні побачити вашу графіку на екрані! Це BeeBoo. Раніше я малював його в своїх шкільних підручниках.

Що робити, якщо ми хотіли змусити цього маленького хлопця рухатися? Просто: ми просто створюємо змінні x і y для його позицій, а потім змінюємо ці значення в оновлення метод.

Тому додайте посилання до свого Характер характеру а потім намалюйте свою растрову карту на х, у. Створіть тут метод оновлення, і зараз ми просто намагатимемося спробувати:

y ++;

Щоразу, коли цикл гри запускається, ми будемо переміщувати персонажа вниз по екрану. Пам'ятайте, у координати вимірюються зверху, так 0 - у верхній частині екрана. Звичайно, нам потрібно зателефонувати оновлення метод в Характер характеру від оновлення метод в GameView.

Натисніть кнопку "Відтворити" ще раз, і тепер ви побачите, що ваше зображення повільно простежується по екрану. Ми ще не вигравали жодної ігрової нагороди, але це початок!

Гаразд, щоб зробити речі трохи що цікавіше, я просто кину сюди якийсь код «підстрибного кулі». Це зробить наш графічний відскак по екрану від країв, як і ті старі заставки Windows. Знаєте, дивно гіпнотичні.

публічне оновлення недійсності () {x + = xVelocity; y + = y швидкість; if ((x & gt; screenWidth - image.getWidth ()) || (x <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 (). висотаPixels;

Оптимізація

є достаток більше, щоб заглибитись сюди, від обробки вводу програвача, до масштабування зображень, до управління великою кількістю символів, що рухаються по екрану одночасно. Зараз персонаж підстрибує, але якщо придивитися дуже уважно, виникає незначне заїкання. Це не страшно, але той факт, що ви можете побачити це неозброєним оком, є чимось попереджувальним знаком. Швидкість також сильно різниться на емуляторі порівняно з фізичним пристроєм. Тепер уявіть, що станеться, коли у вас є тонн відбувається відразу на екрані!

Існує декілька рішень цієї проблеми. Для початку я хочу створити приватне ціле число MainThread і називайте це targetFPS. Це матиме значення 60.Я спробую змусити свою гру працювати з такою швидкістю, а тим часом я перевіряю, чи є вона. Для цього я також хочу приватний подвійний дзвінок середній FPS.

Я також збираюся оновити бігати метод, щоб виміряти, скільки часу займає кожен цикл гри, а потім до пауза цей цикл гри тимчасово, якщо він випереджає targetFPS. Потім ми підрахуємо, як довго це буде зараз взяв, а потім надрукував це, щоб ми могли бачити це в журналі.

@Override public void run () {long startTime; тривалий часMillis; тривалий час очікування; довгий загальний час = 0; int frameCount = 0; довгий targetTime = 1000 / targetFPS; while (працює) {startTime = System.nanoTime (); полотно = null; спробуйте {canvas = this.surfaceHolder.lockCanvas (); синхронізований (surfaceHolder) {this.gameView.update (); this.gameView.draw (полотно); }} лов (виняток е) {} нарешті {if (canvas! = null) {try {surfaceHolder.unlockCanvasAndPost (canvas); } лов (виняток е) {e.printStackTrace (); }}} timeMillis = (System.nanoTime () - startTime) / 1000000; waitTime = targetTime - timeMillis; спробуйте {this.sleep (waitTime); } catch (Виняток е) {} totalTime + = System.nanoTime () - startTime; frameCount ++; if (frameCount == targetFPS) {prosjeнийFPS = 1000 / ((totalTime / frameCount) / 1000000); frameCount = 0; totalTime = 0; System.out.println (середній FPS); }}}

Тепер наша гра намагається заблокувати її FPS до 60, і ви повинні виявити, що вона загалом вимірює досить стійкі 58-62 FPS на сучасному пристрої. На емуляторі ви можете отримати інший результат.

Спробуйте змінити 60 - 30 і подивіться, що станеться. Гра сповільнюється і це повинен тепер прочитайте 30 у вашій лог-коті.

Заключні думки

Є ще деякі речі, які ми можемо зробити для оптимізації продуктивності. Тут є чудова публікація в блозі. Спробуйте утриматися від створення нових екземплярів Paint або растрових зображень всередині циклу і зробіть усі ініціалізації зовні до початку гри.

Якщо ви плануєте створити наступну хіт-гру для Android, тоді є звичайно простіші та ефективніші шляхи вирішення цього питання. Але, безумовно, все ще існують сценарії використання для малювання на полотні, і це дуже корисна навичка, щоб додати до свого репертуару. Я сподіваюся, що цей посібник дещо допоміг і бажаю вам удачі в майбутніх кодуваннях!

ДаліПосібник для початківців Java

Програми для запуску Android вже давно є невід’ємною частиною досвіду Android. Якщо вам не подобається, як виглядають чи діють ваші домашні екрани, ви можете просто завантажити додаток, щоб змінити в...

Для багатьох людей клавіатура за замовчуванням, яка постачається на їхніх пристроях, є прохідною. Зазвичай це або клавіатура Android Android, або клавіатура OEM від amung, LG тощо. Однак це не єдині в...

Популярний