Программирование игр в WEB
0,0
рейтинг
21 августа 2015 в 18:54

Разработка → Разработка HTML5 игры под Android с нуля и до релиза

Вместо вступления


Потратив несколько суток подряд (без перерыва на сон) на изучение поддержки HTML5 всеми любимыми Android-гаджетами, решил, что данной теме стоит уделить внимание. В статье постараюсь раскрыть по шагам все этапы (конечно же базовые/ключевые/основные) создания HTML5 Игрового приложения для Android от идеи до релиза самого APK файла. Возможно, ничего нового я и не открою маститым разработчикам, но для новичков постараюсь описать все как можно проще, со скриншотами и пояснениями.

image

Желающих узнать подробнее приглашаю под кат.

Идея


Вообще много можно говорить о потенциале Android, о развитии HTML5 и об их взаимодействии. Я этого делать не буду. Так что, сразу к делу.

Идея создания игры под Android наверняка заседает в разумах десятков сотен разработчиков, и тех, кто себя таковыми считает. Я не исключение.

Весь процесс будет разбит на несколько шагов а итоговое приложение будет состоять из двух частей:
— Обертка (в данном случае для Android)
— Игра

Шаг 1. Написание самой игры


Еще одним плюсом написания игры на HTML5 является тот факт, что для тестирования не требуется куча запущенных программ, IDE, эмуляторов и так далее. Нужен лишь браузер (в моем случае это Chromium) и текстовый редактор (BlueFish)

Игра будет несложной: есть синий прямоугольник и есть зеленый прямоугольник. Задача игрока — перетащить синий прямоугольник на зеленый в обход красного, который перемещается по игровому полю в произвольном направлении.

Для разработки игры буду использовать J2ds (игровой движок).

Код готовой игры:

index.html
<!DOCTYPE html>
<html> 
 <head>
  <script type="text/javascript" src="j2ds/engineMath.js"></script>
  <script type="text/javascript" src="j2ds/engineKey.js"></script>   
  <script type="text/javascript" src="j2ds/engineDOM.js"></script>
  <script type="text/javascript" src="j2ds/engine2D.js"></script>
  <script type="text/javascript" src="j2ds/engineNet.js"></script>
  <script type="text/javascript" src="j2ds/engineParticles.js"></script>
  <script type="text/javascript" src="j2ds/enginePE.js"></script>  
  <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
  <meta name="viewport" content="width=device-width,user-scalable=no" />  
  <title>Demo Game on J2ds v.0</title>
 </head>

<body id="gameBody">

 <canvas id="iCanvas" width="500" height="280"></canvas>
<br>
<div id="hint"></div>

<script type="text/javascript">
// Инициализируем устройство ввода
initInput('gameBody');

// Создаем сцену
scene= createScene('iCanvas', '#aeeaae');

// Стартуем в полноэкранном режиме
scene.fullScreen(true);

post= createPost(scene);

score= 5;

// Создаем прямоугольники

blue= createRect(vec2di(100, 100), vec2di(30, 30), 'blue');

green= createRect(vec2di(300, 200), vec2di(30, 30), 'green');
green.dX= -1; green.dY= 1;

red= createRect(vec2di(16, 200), vec2di(30, 30), 'red');
red.dX= 1; red.dY= -1;

restart= createRect(vec2di(430, 10), vec2di(60, 60), '#ad21ad');


GameOver= function() {
	// Обрабатываем позицию касания / мыши
 input.upd(scene);
 // Выводим текст
 scene.drawText(vec2di(5,5), 'Score: '+score);
 // Выводим текст
 scene.drawTextOpt(vec2df(140, 100), 'Проиграл!',
    'bold 40px Courier New', '#326598');
 if (input.lClick && input.onNode(restart)) setActivEngine(Game);   
 restart.draw(scene);
}

Success= function() {
	// Обрабатываем позицию касания / мыши
 input.upd(scene);
 // Выводим текст
 scene.drawText(vec2di(5,5), 'Score: '+score);
 // Выводим текст
 scene.drawTextOpt(vec2df(140, 100), 'Победа!',
    'bold 40px Courier New', '#326598');
 if (input.lClick && input.onNode(restart)) setActivEngine(Game);   
 restart.draw(scene);
}


// Описываем игровое состояние Game
Game= function() {
 // Обрабатываем позицию касания / мыши
 input.upd(scene);

 // Выводим текст
 scene.drawText(vec2di(5,5), 'Score: '+score);

 blue.color= input.lClick?'yellow' : 'blue';

 if (input.lClick)  
 {
  red.move(vec2di(red.dX, red.dY));
  green.move(vec2di(green.dX, green.dY));  
  
  
  blue.move(
   vec2df(
    blue.getPosition().x > input.pos.x ? -1*score/2 : 1*score/2,
    blue.getPosition().y > input.pos.y ? -1*score/2 : 1*score/2    
   ) )
  ;
  
  
  if (green.collisionScene(scene).x != 0) green.dX= -green.dX;
  if (green.collisionScene(scene).y != 0) green.dY= -green.dY;
  if (red.collisionScene(scene).x != 0) red.dX= -red.dX;
  if (red.collisionScene(scene).y != 0) red.dY= -red.dY;
 
 }

 if (blue.collision(red)) {
  input.cancel(); score-= 1;
  setActivEngine(GameOver);
  red.setPosition(vec2df(200, 100));
  blue.setPosition(vec2df(50, 50));
 }

 if (blue.collision(green)) {
  input.cancel(); score+= 1;
  setActivEngine(Success);
  red.setPosition(vec2df(200, 100));
  blue.setPosition(vec2df(50, 50));
  blue.setPosition(vec2di(Random(0, 450), Random(0, 250)));
 }


 // Вращаем прямоугольники
 blue.turn(1); 
 green.turn(720/blue.getDistance(green)); 
 red.turn(Random(1, 5));
	
	
	// Отрисовываем объекты
	green.draw(scene); blue.draw(scene); red.draw(scene);

 //post.motionBlur(4);
 
}

// Стартуем игру с игровым состоянием Game и FPS 25
startGame(Game, 25);
</script>

</body>
</html>



На качество кода игры внимания можно не обращать, ибо не это цель статьи. Хотя конечно, можно оптимизировать сколько угодно, этот процесс вообще наверное бесконечен.

Шаг 2. Android Studio. Создание обертки для игры


Я не собираюсь ни с кем мериться крутостью той или иной IDE для разработки под Android, а покажу на примере Android Studio. Для работы нам потребуется:
— Java машина (под мою Linux подходит OpenJDK);
— Дистрибутив Android Studio.

Скачиваем, устанавливаем.

Как только все установите (Этих двух программ достаточно), запускайте Android Studio.

image

Откроется стартовое окно (если первый запуск), если не первый — то откроется сама IDE, но сути не меняет, пройдем в SDK Manager:

image

Тут нужно галочками отметить необходимые вам версии Android, с которыми вы будете работать, в моем случае это Android 4.4.2, вы можете выбрать хоть все сразу.

Главное — выберете обязательно «Tools» и «Extras» и нажимайте «install packages».

Как только у вас все скачалось, запустится IDE с унылым серым фоном и несколькими кнопками, жмем первую и создаем новый проект. Если IDE запустилась сразу в рабочем состоянии, то: «File->New->New Project»

image
Заполняем необходимые поля, и жмем Next

image
Выбираем нужную версию андроида и Next

image
Тут выбираем Blank Activity (пустой шаблон с Hello, World!)

В следующем окне заполняем данные для создания классов, я менять не буду для наглядности:

image

Торжественно жмем Finich и ждем, пока IDE все сконфигурирует и подготовит для работы.

image

Откроется окно с дизайнером форм. Оно не такое, как в Lazarus, Delphi, но что-то схожее все равно имеется:

image

Не спешите ничего менять или что-то щелкать, настройка еще не окончена. Открываем «Tolls->Android->AVD Manager» для настройки эмулятора.

image

Тут, если ничего нет, жмем «Create Virtual Device», если есть, можете не создавать новый, у меня уже был, т.к. я «натыкал» его, пока разбирался. Если же вам нужно создать новый эмулятор, то там все просто:
1. Выбираем размер экрана и модель телефона
2. Выбираем версию андроида (у меня 4.4.2)
3. Настраиваем устройство.

На третьем шаге подробнее:

image

Т.К. игра у нас вытянута по горизонтали, выбрать нужно ландшафтный режим.

Когда все настройки введены, жмем на зеленый треугольник и запускаем эмулятор. После запуска ждем, когда устройство полностью загрузится и запустится ОС:

image

Это окно не закрывайте, в нем будет происходить эмуляция. Теперь можно вернуться в редактор, и изменить ориентацию в дизайнере форм:

image

Можно запускать! Вот теперь точно можно.

Если появится запрос на выбор эмулятора — то можно поставить галочку внизу:

image

Мои поздравления! Все работает, проверено!

image

Сворачиваем наш эмулятор (Но не закрываем!) и переходим в редактор, Там все немного сложнее (чуть-чуть).
Переключиться нужно в режим «Text». У вас в activity_main описаны все элементы, которые есть на форме. Включая саму форму. Да и не форма это вовсе.

Т.к. мы делаем игру в HTML5, а тут у нас только обертка для игры, удаляем весь текст и вставляем следующее:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    tools:context=".MainActivity">

    <WebView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/webView"
        android:clickable="true"
        android:scrollbars="none" />
</RelativeLayout>


Теперь, если опять переключиться на дизайн, то выглядеть будет иначе:
image

Как видно, теперь вместо «Hello, World» во всю красуется растянутый на весь экран — WebView. Этот объект и является нашим «окном» в игровой мир.

Можете запустить даже, посмотреть, будет белый экран. Идем дальше.

А дальше нам нужно перейти в наш проект, для этого слева открываем поле «Project» и выбираем вкладку «Android», если не выбрана:

image
В этой вкладке представлена структура проекта и все его внутренние файлы и ресурсы.

Пояснение
Нам требуется найти файл «манифест» и дописать в определение «application» следующую строку:
android:hardwareAccelerated="true"



Пришло время поработать над функционалом нашего «браузера», ведь это именно он! Открываем класс «MainActivity.java» и удаляем все лишнее, оставив только основное:

Пояснение
package com.soft.skaner.demogamehtml5;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }


}



Если не забыли, мы в файле activity_main добавили WebView, обратите внимание на выделенную жирным строчку:
<WebView
android:layout_width=«fill_parent»
android:layout_height=«fill_parent»
android:id="@+id/webView"
android:clickable=«true»
android:scrollbars=«none» />

Нам нужно объявить объект класса WebView.

Для этого к списку импортов дописываем:

import android.webkit.WebView;

А затем объявляем наш объект myWeb внутри класса MainActivity:

protected WebView myWeb;

Теперь, после строчки setContentView(R.layout.activity_main); вставляем следующий код:

        /* Находим наш браузер */
        myWeb= (WebView) findViewById(R.id.webView);

        /* Настраиваем наш браузер */
        myWeb.getSettings().setUseWideViewPort(true);
        myWeb.setInitialScale(1);
        myWeb.getSettings().setJavaScriptEnabled(true);
        
        /* Загружаем страничку */
        myWeb.loadUrl("file:///android_asset/index.html");


Вот что получилось у меня в редакторе:

image

А вот, что в эмуляторе:

image

Если у вас так же — мы на верном пути!

Осталось дело за небольшим:
Там, где мы подгружаем страницу нашему браузеру, путь к файлу выглядит так: «file:///android_asset/index.html»
Следует учесть, что любые файлы мы можем хранить внутри нашей игры, имея к ним доступ.

В нашем случае ключевая папка: «android_asset», давайте ее создадим (да, по умолчанию ее нет в проекте):
«File -> New -> Folder -> Assets folder», откроется окно где достаточно просто согласиться с IDE.
Заметили? В проекте появилась новая папка:

image

Жмем по ней правой кнопкой мыши -> «Show in Files», откроется системный проводник (в моем случае Nautilus), обратите внимание на путь к папке. Имейте так же ввиду, что папка называется «assets», но доступ к ней идет через «android_asset».

image

Дальше все совсем просто — копируем нашу игру в папку assets:

image

Файл index.html — это тот самый index из начала этой статьи. Ну что, пробуем запустить!

image

Небольшой совет: тестировать лучше всего на реальном устройстве посредством USB, так результаты теста будут нагляднее, да и управлять мышью не самый удобный вариант, не говоря уже о множественном нажатии.

Шаг 3. Android Studio. Сборка приложения и его подписывание


Когда игра вами полностью отлажена (в браузере или на эмуляторе), обертка полностью готова и все этапы разработки позади, можно собирать приложение. Android Studio позволяет собирать приложения и подписывать их вашими ключами.

Для создания ключей в этой IDE есть специальная утилита «KeyTool».

Переходим к созданию исполняемого файла приложения («Build -> Generate Signed APK»):

image

Если ранее ключей и алиасов вы не создавали, нажимайте «Create New». Заполнить поля можете на свое усмотрение, достоверность данных целиком лежит на вас.

image

Первое поле — это путь к папке, в которую будет сохранен ключ. Форма после нажатия Ok заполнится автоматически:

image

Для последующих приложений создавать новые ключи не обязательно, вы можете подписывать вашим ключем и другие приложения, именно для этого и есть кнопка «Choose Existing».

На следующем шаге IDE попросит у вас еще раз ввести пароль, а затем указать папку для сохранения APK файла.

image

Теперь можете расслабиться и попить, к примеру, кофе.Система начала компиляцию, результат в статусбаре:

image

После того, как компиляция завершится, система вам об этом сообщит.

image

image

Теперь достаточно переместить файл на телефон / планшет и установить, как обычное приложение.

Результат:

image

image

За примером в ЛС, если нужно.
Петр @Skaner
карма
8,0
рейтинг 0,0
Программирование игр в WEB
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (21)

  • +19
    Почему HTML5? — Нативность.
    Што?
    • +5
      наверно он хотел сказать «наивность» :)) ну а если серьезно — то видимо зачеркнутый текст таки был ближе к истине
      • 0
        На момент моего комментария зачеркнутого текста не было.
        • 0
          Не было =)
        • +2
          Появление зачёркнутого текста не отменяет актуальности вашего вопроса.
          • 0
            HTML5 в принципе актуален, для меня, конечно же. Но не исключено, что взгляд перебросится на что-то более актуальное.
            • +1
              Что может быть актуальней HTML5? Только шоу с осликом!
  • +1
    Ну заголовок немного не соответствует статье. Тут ни как не разработка игры "с нуля". Уже есть готовый index.html файл. Вот если бы вы описали процесс создания игры на html, то презентаций не было бы.
    К примеру, эта статья заслуживает фразы «С нуля».
    • 0
      Это продолжение моей предыдущей статьи.

      Сейчас почитаю ту статью, но вообще на J2ds FlappyBirds не составит труда сделать. =)
      • +1
        Ну вот если вы напишите клон какой-то популярной легкой игры с 0, примерно с таким же разъяснением, как в статье, которую я указал выше, то будет очень круто. Как правила вот такого рода полноценные статьи, если конечно они хорошо оформлены + красиво написано, попадают в топ и приносят много кармы (хотя я думаю мало кто тут вообще ради кармы пишет статьи).
  • +1
    Есть же человеческие технологии для создания игр. Нет, хочу писать на всякой не предназначенной для этого фигне. Хватит тащить везде свой HTML5. А потом удивляются че это все тормозит.
    • –2
      Извините, что язвлю, но попробую ответить так: «Есть же консоли и ПК, зачем ты делаешь змейку для мобильника, кто в нее будет играть? Не удивляйся потом, что она никого не заинтересовала» (Nokia, 1997)
      • 0
        Они абсолютно правы. Если есть сомнения, то попробуйте выложить змейку в play store
      • +1
        В данном случае больше подходит «Если есть отвертка, то зачем ты забиваешь саморезы молотком?»
  • –1
    Если знаете JS то почему Unity не взяли?
  • +1
    Спасибо автору за статью. А то раньше только при помощи PhoneGap собирал приложения.
  • +1
    А чем это лучше Ionic, PhoneGap, Cordova? Обертку же придется писать самому для каждой платформы.
  • +2
    У подобного способа (WebView и вся логика в джаваскрипте) множество ограничений и подводных камней. Начиная от банальных проблем с производительностью и заканчивая жуткими глюками c выводом аудио и т.п., если захочется создать что-нибудь посложнее описываемой игрушки с квадратиками. Множество проблем и способов их обхода описано в этой статье.
  • 0
    Спасибо за толковую иллюстрацию как там чего, чтоб заработало.
  • +1
    Да, статья не про код, но все же…
    // Стартуем игру с игровым состоянием Game и FPS 25
    startGame(Game, 30);
    

    Я люблю такое соответствие кода и комментариев. Может, автор забыл обновить комментарий. Или константу в коде. Или FPS 25 зашит внутри, а 30 — нечто иное. Обожаю разбираться с таким кодом на работе.
    • +1
      Спасибо, поправил. Осталось еще с тестов моих.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.