Как создать игру на телефон самому с нуля инструкция

Время на прочтение
10 мин

Количество просмотров 144K

Этот туториал предназначен в первую очередь для новичков в разработке под андроид, но может быть будет полезен и более опытным разработчикам. Тут рассказано как создать простейшую 2D игру на анроиде без использования каких-либо игровых движков. Для этого я использовал Android Studio, но можно использовать любую другую соответствующее настроенную среду разработки.

Шаг 1. Придумываем идею игры
Для примера возьмём довольно простую идею:

Внизу экрана — космический корабль. Он может двигаться влево и вправо по нажатию соответствующих кнопок. Сверху вертикально вниз движутся астероиды. Они появляются по всей ширине экрана и двигаются с разной скоростью. Корабль должен уворачиваться от метеоритов как можно дольше. Если метеорит попадает в него — игра окончена.

Шаг 2. Создаём проект
В Android Studio в верхнем меню выбираем File → New → New Project.

Тут вводим название приложения, домен и путь. Нажимаем Next.

Тут можно ввести версию андроид. Также можно выбрать андроид часы и телевизор. Но я не уверен что наше приложение на всём этом будет работать. Так что лучше введите всё как на скриншоте. Нажимаем Next.

Тут обязательно выбираем Empty Activity. И жмём Next.

Тут оставляем всё как есть и жмём Finish. Итак проект создан. Переходим ко третьему шагу.

Шаг 3. Добавляем картинки

Скачиваем архив с картинками и распаковываем его.

Находим папку drawable и копируем туда картинки.

Позже они нам понадобятся.

Шаг 4. Создаём layout

Находим activity_main.xml, открываем вкладку Text и вставляем туда это:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.spaceavoider.spaceavoider.MainActivity">
    <LinearLayout
        android:id="@+id/gameLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:layout_weight="100"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/leftButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="50"
            android:text="Left" />
        <Button
            android:id="@+id/rightButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="50"
            android:text="Right" />
    </LinearLayout>
</LinearLayout>

На вкладке Design видно как наш layout будет выглядеть.

Сверху поле в котором будет сама игра, а снизу кнопки управления Left и Right. Про layout можно написать отдельную статью, и не одну. Я не буду на этом подробно останавливаться. Про это можно почитать тут.

Шаг 5. Редактируем MainActivity класс

В первую очередь в определение класса добавляем implements View.OnTouchListener. Определение класса теперь будет таким:

public class MainActivity extends AppCompatActivity implements View.OnTouchListener {

Добавим в класс нужные нам статические переменные (переменные класса):

public static boolean isLeftPressed = false; // нажата левая кнопка
public static boolean isRightPressed = false; // нажата правая кнопка

В процедуру protected void onCreate(Bundle savedInstanceState) {
добавляем строки:

GameView gameView = new GameView(this); // создаём gameView

LinearLayout gameLayout = (LinearLayout) findViewById(R.id.gameLayout); // находим gameLayout
gameLayout.addView(gameView); // и добавляем в него gameView

Button leftButton = (Button) findViewById(R.id.leftButton); // находим кнопки
Button rightButton = (Button) findViewById(R.id.rightButton);

leftButton.setOnTouchListener(this); // и добавляем этот класс как слушателя (при нажатии сработает onTouch)
rightButton.setOnTouchListener(this);

Классы LinearLayout, Button и т.д. подсвечены красным потому что ещё не добавлены в Import.
Чтобы добавить в Import и убрать красную подсветку нужно для каждого нажать Alt+Enter.
GameView будет подсвечено красным потому-что этого класса ещё нет. Мы создадим его позже.

Теперь добавляем процедуру:

public boolean onTouch(View button, MotionEvent motion) {
    switch(button.getId()) { // определяем какая кнопка
        case R.id.leftButton:
            switch (motion.getAction()) { // определяем нажата или отпущена
                case MotionEvent.ACTION_DOWN:
                    isLeftPressed = true;
                    break;
                case MotionEvent.ACTION_UP:
                    isLeftPressed = false;
                    break;
            }
            break;
        case R.id.rightButton:
            switch (motion.getAction()) { // определяем нажата или отпущена
                case MotionEvent.ACTION_DOWN:
                    isRightPressed = true;
                    break;
                case MotionEvent.ACTION_UP:
                    isRightPressed = false;
                    break;
            }
            break;
    }
    return true;
}

Если кто-то запутался ― вот так в результате должен выглядеть MainActivity класс:

package com.spaceavoider.spaceavoider;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity implements View.OnTouchListener {
    public static boolean isLeftPressed = false; // нажата левая кнопка
    public static boolean isRightPressed = false; // нажата правая кнопка
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        GameView gameView = new GameView(this); // создаём gameView
        LinearLayout gameLayout = (LinearLayout) findViewById(R.id.gameLayout); // находим gameLayout
        gameLayout.addView(gameView); // и добавляем в него gameView
        Button leftButton = (Button) findViewById(R.id.leftButton); // находим кнопки
        Button rightButton = (Button) findViewById(R.id.rightButton);
        leftButton.setOnTouchListener(this); // и добавляем этот класс как слушателя (при нажатии сработает onTouch)
        rightButton.setOnTouchListener(this);
    }
    public boolean onTouch(View button, MotionEvent motion) {
        switch(button.getId()) { // определяем какая кнопка
            case R.id.leftButton:
                switch (motion.getAction()) { // определяем нажата или отпущена
                    case MotionEvent.ACTION_DOWN:
                        isLeftPressed = true;
                        break;
                    case MotionEvent.ACTION_UP:
                        isLeftPressed = false;
                        break;
                }
                break;
            case R.id.rightButton:
                switch (motion.getAction()) { // определяем нажата или отпущена
                    case MotionEvent.ACTION_DOWN:
                        isRightPressed = true;
                        break;
                    case MotionEvent.ACTION_UP:
                        isRightPressed = false;
                        break;
                }
                break;
        }
        return true;
    }
}

Итак, класс MainActivity готов! В нём инициирован ещё не созданный класс GameView. И когда нажата левая кнопка — статическая переменная isLeftPressed = true, а когда правая — isRightPressed = true. Это в общем то и всё что он делает.

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

Шаг 6. Создаём класс GameView

Теперь наконец-то создадим тот самый недостающий класс GameView. Итак приступим. В определение класса добавим extends SurfaceView implements Runnable. Мобильные устройства имею разные разрешения экрана. Это может быть старенький маленький телефон с разрешением 480×800, или большой планшет 1800×2560. Для того чтобы игра выглядела на всех устройствах одинаково я поделил экран на 20 частей по горизонтали и 28 по вертикали. Полученную единицу измерения я назвал юнит. Можно выбрать и другие числа. Главное чтобы отношение между ними примерно сохранялось, иначе изображение будет вытянутым или сжатым.

public static int maxX = 20; // размер по горизонтали
public static int maxY = 28; // размер по вертикали
public static float unitW = 0; // пикселей в юните по горизонтали
public static float unitH = 0; // пикселей в юните по вертикали

unitW и unitW мы вычислим позже. Также нам понадобятся и другие переменные:

private boolean firstTime = true;
private boolean gameRunning = true;
private Ship ship;
private Thread gameThread = null;
private Paint paint;
private Canvas canvas;
private SurfaceHolder surfaceHolder;

Конструктор будет таким:

public GameView(Context context) {
    super(context);
    //инициализируем обьекты для рисования
    surfaceHolder = getHolder();
    paint = new Paint();

    // инициализируем поток
    gameThread = new Thread(this);
    gameThread.start();
}

Метод run() будет содержать бесконечный цикл. В начале цикла выполняется метод update()
который будет вычислять новые координаты корабля. Потом метод draw() рисует корабль на экране. И в конце метод control() сделает паузу на 17 миллисекунд. Через 17 миллисекунд run() запустится снова. И так до пока переменная gameRunning == true. Вот эти методы:

@Override
public void run() {
    while (gameRunning) {
        update();
        draw();
        control();
    }
}

private void update() {
    if(!firstTime) {
        ship.update();
    }
}

private void draw() {
    if (surfaceHolder.getSurface().isValid()) {  //проверяем валидный ли surface

        if(firstTime){ // инициализация при первом запуске
            firstTime = false;
            unitW = surfaceHolder.getSurfaceFrame().width()/maxX; // вычисляем число пикселей в юните
            unitH = surfaceHolder.getSurfaceFrame().height()/maxY;

            ship = new Ship(getContext()); // добавляем корабль
        }

        canvas = surfaceHolder.lockCanvas(); // закрываем canvas
        canvas.drawColor(Color.BLACK); // заполняем фон чёрным

        ship.drow(paint, canvas); // рисуем корабль

        surfaceHolder.unlockCanvasAndPost(canvas); // открываем canvas
    }
}

private void control() { // пауза на 17 миллисекунд
    try {
        gameThread.sleep(17);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Обратите внимание на инициализацию при первом запуске. Там мы вычисляем количество пикселей в юните и добавляем корабль. Корабль мы ещё не создали. Но прежде мы создадим его родительский класс.

Шаг 7. Создаём класс SpaceBody

Он будет родительским для класса Ship (космический корабль) и Asteroid (астероид). В нём будут содержаться все переменные и методы общие для этих двух классов. Добавляем переменные:

protected float x; // координаты
protected float y;
protected float size; // размер
protected float speed; // скорость
protected int bitmapId; // id картинки
protected Bitmap bitmap; // картинка

и методы

void init(Context context) { // сжимаем картинку до нужных размеров
    Bitmap cBitmap = BitmapFactory.decodeResource(context.getResources(), bitmapId);
    bitmap = Bitmap.createScaledBitmap(
            cBitmap, (int)(size * GameView.unitW), (int)(size * GameView.unitH), false);
    cBitmap.recycle();
}

void update(){ // тут будут вычисляться новые координаты
}

void drow(Paint paint, Canvas canvas){ // рисуем картинку
    canvas.drawBitmap(bitmap, x*GameView.unitW, y*GameView.unitH, paint);
}

Шаг 8. Создаём класс Ship

Теперь создадим класс Ship (космический корабль). Он наследует класс SpaceBody поэтому в определение класа добавим extends SpaceBody.

Напишем конструктор:

public Ship(Context context) {
    bitmapId = R.drawable.ship; // определяем начальные параметры
    size = 5;
    x=7;
    y=GameView.maxY - size - 1;
    speed = (float) 0.2;

    init(context); // инициализируем корабль
}

и переопределим метод update()

@Override
public void update() { // перемещаем корабль в зависимости от нажатой кнопки
    if(MainActivity.isLeftPressed && x >= 0){
        x -= speed;
    }
    if(MainActivity.isRightPressed && x <= GameView.maxX - 5){
        x += speed;
    }
}

На этом космический корабль готов! Всё компилируем и запускаем. На экране должен появиться космический корабль. При нажатии на кнопки он должен двигаться вправо и влево. Теперь добавляем сыплющиеся сверху астероиды. При столкновении с кораблём игра заканчивается.

Шаг 9. Создаём класс Asteroid

Добавим класс Asteroid (астероид). Он тоже наследует класс SpaceBody поэтому в определение класса добавим extends SpaceBody.

Добавим нужные нам переменные:

private int radius = 2; // радиус
private float minSpeed = (float) 0.1; // минимальная скорость
private float maxSpeed = (float) 0.5; // максимальная скорость

Астероид должен появляться в случайной точке вверху экрана и лететь вниз с случайной скоростью. Для этого x и speed задаются при помощи генератора случайных чисел в его конструкторе.

public Asteroid(Context context) {
    Random random = new Random();

    bitmapId = R.drawable.asteroid;
    y=0;
    x = random.nextInt(GameView.maxX) - radius;
    size = radius*2;
    speed = minSpeed + (maxSpeed - minSpeed) * random.nextFloat();

    init(context);
}

Астероид должен двигаться с определённой скорость вертикально вниз. Поэтому в методе update() прибавляем к координате x скорость.

@Override
public void update() {
    y += speed;
}

Так же нам нужен будет метод определяющий столкнулся ли астероид с кораблём.

public boolean isCollision(float shipX, float shipY, float shipSize) {
    return !(((x+size) < shipX)||(x > (shipX+shipSize))||((y+size) < shipY)||(y > (shipY+shipSize)));
}

Рассмотрим его поподробнее. Для простоты считаем корабль и астероид квадратами. Тут я пошёл от противного. То есть определяю когда квадраты НЕ пересекаются.

((x+size) < shipX) — корабль слева от астероида.
(x > (shipX+shipSize)) — корабль справа от астероида.
((y+size) < shipY) — корабль сверху астероида.
(y > (shipY+shipSize)) — корабль снизу астероида.

Между этими четырьмя выражениями стоит || (или). То есть если хоть одно выражение правдиво (а это значит что квадраты НЕ пересекаются) — результирующие тоже правдиво.

Всё это выражение я инвертирую знаком!. В результате метод возвращает true когда квадраты пересекаются. Что нам и надо.

Про определение пересечения более сложных фигур можно почитать тут.

Шаг 10. Добавляем астероиды в GameView

В GameView добавляем переменные:

private ArrayList<Asteroid> asteroids = new ArrayList<>(); // тут будут харанится астероиды
private final int ASTEROID_INTERVAL = 50; // время через которое появляются астероиды (в итерациях)
private int currentTime = 0;

также добавляем 2 метода:

private void checkCollision(){ // перебираем все астероиды и проверяем не касается ли один из них корабля
    for (Asteroid asteroid : asteroids) {
        if(asteroid.isCollision(ship.x, ship.y, ship.size)){
            // игрок проиграл
            gameRunning = false; // останавливаем игру
            // TODO добавить анимацию взрыва
        }
    }
}

private void checkIfNewAsteroid(){ // каждые 50 итераций добавляем новый астероид
    if(currentTime >= ASTEROID_INTERVAL){
        Asteroid asteroid = new Asteroid(getContext());
        asteroids.add(asteroid);
        currentTime = 0;
    }else{
        currentTime ++;
    }
}

И в методе run() добавляем вызовы этих методов перед вызовоом control().

@Override
public void run() {
    while (gameRunning) {
        update();
        draw();
        checkCollision();
        checkIfNewAsteroid();
        control();
    }
}

Далее в методе update() добавляем цикл который перебирает все астероиды и вызывает у них метод update().

private void update() {
    if(!firstTime) {
        ship.update();
        for (Asteroid asteroid : asteroids) {
            asteroid.update();
        }
    }
}

Такой же цикл добавляем и в метод draw().

private void draw() {
    if (surfaceHolder.getSurface().isValid()) {  //проверяем валидный ли surface

        if(firstTime){ // инициализация при первом запуске
            firstTime = false;
            unitW = surfaceHolder.getSurfaceFrame().width()/maxX; // вычисляем число пикселей в юните
            unitH = surfaceHolder.getSurfaceFrame().height()/maxY;

            ship = new Ship(getContext()); // добавляем корабль
        }

        canvas = surfaceHolder.lockCanvas(); // закрываем canvas
        canvas.drawColor(Color.BLACK); // заполняем фон чёрным

        ship.drow(paint, canvas); // рисуем корабль

        for(Asteroid asteroid: asteroids){ // рисуем астероиды
            asteroid.drow(paint, canvas);
        }

        surfaceHolder.unlockCanvasAndPost(canvas); // открываем canvas
    }
}

Вот и всё! Простейшая 2D игра готова. Компилируем, запускаем и смотрим что получилось!
Если кто-то запутался или что-то не работает можно скачать исходник.

Игра, конечно, примитивна. Но её можно усовершенствовать, добавив новые функции. В первую очередь следует реализовать удаление вылетевших за пределы экрана астероидов. Можно сделать чтобы корабль мог стрелять в астероиды, чтобы игра постепенно ускорялась, добавить таймер, таблицу рекордов и прочее. Если это будет вам интересно — напишу продолжение, где всё это опишу.

На этом всё. Пишите отзывы, вопросы, интересующие вас темы для продолжения.

Вы новичок в разработке мобильных игр и хотите освоить основы? Тогда вы пришли по адресу! Эта статья содержит исчерпывающее руководство по началу работы в мире разработки мобильных игр. Мы обсудим различные типы мобильных игр, инструменты и программное обеспечение, которые вам понадобятся, и даже несколько советов по монетизации вашего творения. К концу этого руководства для начинающих у вас должно быть достаточно знаний и уверенности, чтобы погрузиться в свой первый проект мобильной игры.

Введение в разработку мобильных игр

.

Введение в разработку мобильных игр

Мобильные игры стали одним из самых популярных видов развлечений в последние годы. С появлением смартфонов, планшетов и других мобильных устройств мобильные игры превратились из второстепенного рынка в бурно развивающуюся индустрию. В результате многие разработчики стремятся заняться разработкой мобильных игр.

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

Платформы

Когда дело доходит до разработки мобильных игр, существуют две основные платформы для разработки: iOS и Android. Обе эти платформы имеют свои собственные наборы для разработки программного обеспечения (SDK), которые можно использовать для создания игр. iOS, как правило, является более популярной платформой для разработки игр благодаря своей закрытой экосистеме и простоте использования.

В дополнение к этим двум платформам, Windows Phone и другие новые мобильные платформы, такие как HTML5 и Unity, также могут использоваться для разработки игр. Каждая из этих платформ предлагает уникальные преимущества, которые могут быть выгодны определенным типам разработчиков игр.

Конструктивные соображения

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

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

Инструменты разработки

Когда дело доходит до разработки мобильных игр, существует целый ряд доступных инструментов разработки. Популярные инструменты включают Unity, HTML5 и Xcode. Каждый из этих инструментов имеет свои преимущества и недостатки, поэтому разработчикам следует тщательно изучить каждый вариант, чтобы определить, какой из них лучше всего подходит для их нужд.

В дополнение к инструментам разработки, разработчикам игр доступен ряд других ресурсов, таких как игровые движки, аудиотеки и API. Все эти ресурсы могут быть использованы для ускорения разработки и создания лучшей игры.

Вывод

Разработка мобильных игр — захватывающая и быстро развивающаяся область. Это требует от разработчиков учитывать множество уникальных факторов, таких как требования к оборудованию, стратегии монетизации и инструменты разработки. Понимая эти факторы, разработчики игр могут создавать успешные и увлекательные мобильные игры.

Основные инструменты и ресурсы для разработки

.

Основные инструменты и ресурсы для разработки

Для разработчиков крайне важно иметь правильные инструменты для создания эффективного и надежного программного обеспечения. В этой статье речь пойдет об основных инструментах разработки и ресурсах, которые вам следует учитывать при настройке вашей среды разработки.

интегрированная среда разработки

Интегрированная среда разработки (IDE) предоставляет универсальное решение для кодирования, компиляции, выполнения и отладки вашего приложения. Он предлагает встроенный текстовый редактор для написания кода, компилятор для выполнения ваших приложений и отладчик для обнаружения и исправления ошибок. Популярные IDE включают Eclipse, NetBeans и Visual Studio.

Система контроля версий (VCS)

Система контроля версий (VCS) позволяет вам отслеживать изменения, вносимые в вашу кодовую базу с течением времени. Это особенно важно при работе в командах, поскольку гарантирует, что любые изменения, внесенные одним членом команды или филиалом, отслеживаются и объединяются в основную кодовую базу организованным образом. Распространенные VCS включают Git, SVN и Mercurial.

Менеджеры пакетов

Менеджеры пакетов необходимы для управления сторонними библиотеками и фреймворками, используемыми для создания вашего приложения. Популярные менеджеры пакетов для различных языков и платформ включают npm (Node.js ), pip (Python) и maven (Java).

Другие ресурсы

  • Документация — Каждый язык программирования и фреймворк, который вы используете, должен иметь обширную документацию, которая поможет вам лучше понять и использовать язык / фреймворк. Примерами могут служить документация разработчика Android, RubyDocs и документация по Python.
  • Средства отладки — эти инструменты помогают вам выявлять и исправлять ошибки в вашем коде. Популярные опции включают Chrome DevTools, Firebug и Xdebug.
  • Средства автоматизации тестирования — средства автоматизированного тестирования помогут вам убедиться в том, что ваше приложение не содержит ошибок и функционирует должным образом. Популярные варианты включают Selenium, Watir и JUnit.

Разработка структуры вашей игры

Тема Полезная информация
Гибкая архитектура При разработке структуры вашей игры важно иметь гибкую архитектуру. Это позволит вам легко добавлять новые функции или вносить изменения без необходимости переписывать всю базу кода.
пользовательский интерфейс При разработке структуры вашей игры учитывайте пользовательский опыт. Убедитесь, что игра проста для понимания и навигации, чтобы обеспечить наилучший пользовательский опыт.
Оптимизация Чтобы убедиться, что ваша игра работает плавно и без ошибок, используйте методы оптимизации, такие как сжатие данных и объединение объектов в пул, которые помогут сделать вашу игру более эффективной.

Программирование Вашей игры

Руководство для начинающих по разработке мобильных игр.

Программирование Вашей игры

Создание видеоигр сильно отличается от создания других программ из-за своей интерактивности и делится на несколько этапов, которые часто называют стадиями.

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

Когда вы решите, какую игру вы хотите создать, вот основные шаги, которые вам следует предпринять:

  • Создайте концепцию Должна быть установлена базовая концепция и руководящие принципы игры. Проработайте сюжет, сценарий, персонажей и настройки.
  • Тестирование и отладка Любые ошибки или проблемы с игрой должны быть выявлены и устранены. Это следует делать на каждом этапе создания игры.
  • Создавайте произведения искусства Все рисунки и анимации должны быть созданы. Это может включать в себя фоны игры, спрайты, персонажей и другие графические элементы.
  • Тест и баланс Игра должна быть протестирована, чтобы обеспечить сбалансированную сложность и приятный игровой опыт.
  • Напишите программу Для создания игры должен быть написан программный код. Он должен определять, как работает игра, и реагировать, когда игрок взаимодействует с игрой.
  • Выпуск и маркетинг После того, как игра будет создана, ее нужно будет выпустить и продать, чтобы охватить целевую аудиторию и увеличить продажи.

После выполнения этих шагов ваша игра будет окончательно завершена и будет готова к просмотру широкой аудиторией.

Включение графики и аудио

Включение графики и аудио

Включение графики и аудио в цифровые продукты, веб-сайты и веб-приложения может улучшить пользовательский опыт, а также общий дизайн приложения. Чтобы понять, как можно использовать графику и звук для улучшения пользовательского опыта, важно изучить различные возможности.

Эффективное использование графики

Графика используется для передачи информации с помощью визуальных средств. Они могут помочь пользователю быстро определить назначение продукта или страницы, на которую он смотрит, а также функции, которые он предлагает. Графика может быть в виде изображений, диаграмм, иллюстраций (например, значков) и даже видеороликов. В то время как некоторые графические изображения используются для визуальной привлекательности, другие могут передавать сложные идеи или объяснять их более простым способом.

Правильное использование звука

Аудио добавляет еще одно измерение к опыту использования цифровых продуктов, веб-сайтов и веб-приложений. Аудио можно использовать для создания атмосферы, передачи информации, обеспечения обратной связи и даже обеспечения возможности общения. Звук следует использовать продуманно, чтобы улучшить пользовательский опыт, а не умалять его.

Преимущества использования аудио и графики

  • Позволяет пользователю быстро понять назначение продукта или страницы, а также определить функции и возможности.
  • Создает привлекательный интерфейс, добавляя визуальное и слуховое измерение в пользовательский интерфейс.
  • Может использоваться для объяснения сложных идей или концепций более простым способом.
  • Может использоваться для создания атмосферы и обеспечения обратной связи.
  • Может обеспечивать связь между пользователями и/или цифровыми продуктами.
  • Помогает улучшить общий дизайн и пользовательский интерфейс.

Тестируем Вашу мобильную игру

Стратегия тестирования Влияние Предложения
Бета-тестеры Помогает выявлять ошибки Выявляйте и привлекайте пользователей для тестирования на целевом рынке игры
Тесты производительности Анализируйте скорость отклика и время загрузки Протестируйте игру на самых разных устройствах
Тесты на удобство использования Проверьте пользовательский интерфейс Тестируйте с реальными пользователями в реальных условиях

Маркетинг и публикация вашего названия

Маркетинг и публикация вашего названия

Когда вы будете готовы опубликовать свою книгу, вам нужно сосредоточиться на том, как ее продвигать, а также на логистике публикации названия. В этой статье мы рассмотрим три ключевые концепции маркетинга вашей книги, организации официального запуска и распространения книги по различным каналам.

Продвигайте свою книгу

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

  • Социальные сети — используйте свои существующие аккаунты в Twitter, Facebook и других платформах, чтобы привлечь новых читателей.
  • Создание веб-сайта или блога — Создайте интерактивный веб-сайт или блог, который привлечет потенциальных читателей на вашу страницу.
  • Цифровая реклама — используйте такие платформы, как Google Ads и AdWords, чтобы увеличить свое присутствие в Интернете и, в конечном счете, увеличить продажи.
  • Список адресов электронной почты — Создайте список адресов электронной почты потенциальных читателей и отправляйте им обновления и информацию о вашей книге и о том, как ее приобрести.

Создание официального запуска

Проведение официального дня презентации, на котором вы объявляете о выходе своей книги, — отличный способ создать ажиотаж и привлечь потенциальных читателей. Вот несколько советов по созданию официального запуска:

  • Назначьте дату — решите, когда вы хотите провести свой официальный запуск, и объявите об этом в своем списке рассылки по электронной почте, на платформах социальных сетей и в любых других средствах массовой информации, которые вы используете для маркетинга.
  • Подготовьте контент — создайте уникальный контент для публикации в день презентации, такой как выдержки из книг, обзоры и интервью.
  • Соберите свое племя — попросите своих самых преданных читателей и подписчиков помочь распространить информацию в день запуска и за его пределами.

Выпуск Вашей книги

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

  • Интернет-магазины — Amazon, Barnes & Noble и другие интернет-магазины являются наиболее распространенными местами для покупки книг.
  • Физические магазины розничной торговли — Если у вас есть физическая книга, которую вы продаете, подумайте о размещении ее в книжных магазинах и других физических магазинах розничной торговли.
  • Цифровые платформы — используйте такие платформы, как Apple Books, Kobo и Google Play, чтобы предлагать цифровые версии вашей книги.

Советы по получению финансирования

Руководство для начинающих по разработке мобильных игр

Советы по получению финансирования

Правильное финансирование может стать разницей между успехом и неудачей при запуске бизнеса или проекта. Следуя этим советам, вы сможете получить деньги, необходимые для успешного развития вашего предприятия.

Исследования и сеть

Прежде чем начать поиск финансирования, составьте список источников финансирования, к которым вы хотели бы обратиться. Затем потратьте время на изучение каждого из них. Проверьте квалификацию, чтобы убедиться, что ваш проект хорошо подходит. Вы также захотите изучить прошлые финансируемые проекты организации, узнать, кто там работает, и любую другую соответствующую информацию, которая могла бы помочь вам настроить свою презентацию.

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

Напишите убедительное предложение

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

Ищите другие источники финансирования

В дополнение к традиционным источникам финансирования изучите другие способы привлечения капитала. Рассмотрим краудфандинг, ангелов-инвесторов, венчурных капиталистов и инкубаторы. Конкурсы грантов — еще один отличный вариант. В некоторые из них вход платный, поэтому обязательно проведите свое исследование, прежде чем подавать заявку.

следовать за

Предполагая, что вы отправите свое предложение лично, ответьте на него телефонным звонком или электронным письмом через несколько дней. В дальнейшем напомните им о своем проекте и дайте понять, что вы цените их внимание. Это свидетельствует о том, что вы полны энтузиазма и вложены в проект.

Советы по подписке на предложения издателей

Чаевые Подробности
Исследовательские сделки Ищите предложения, которые предлагают наилучшие комиссионные, продолжительность сделки и структуру комиссионных.
Требования к проверке Выясните, существуют ли какие-либо ограничения или требования, требующие одобрения сделки, и убедитесь, что ваш веб-сайт соответствует им.
Проверьте коэффициенты конверсии Изучите показатели конверсии различных предложений и убедитесь, что на веб-сайте хорошие показатели конверсии.

Советы по расширению вашей аудитории

“Успех приходит к тем, кто посвящает все своей страсти в жизни. Чтобы добиться успеха, также очень важно быть скромным и никогда не позволять славе или деньгам вскружить вам голову”. Ирина Шейк, модель

Советы по расширению вашей аудитории

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

Как увеличить свою аудиторию

  • Будьте искренни. Важно быть самим собой в социальных сетях и демонстрировать свою истинную индивидуальность. Люди реагируют на аутентичность, поэтому убедитесь, что контент, которым вы делитесь, является подлинным и демонстрирует, кто вы как личность или бренд.
  • Взаимодействуйте со своей аудиторией. Общайтесь со своими подписчиками и выясняйте, что их волнует. Прислушивайтесь к их потребностям и помогайте им находить решения их проблем. Демонстрация того, что вы цените свою аудиторию и ее мнение, поможет вам построить с ней более прочные отношения.
  • Будьте последовательны. Последовательность является ключевым фактором, когда дело доходит до формирования аудитории. Убедитесь, что вы регулярно размещаете посты в своих каналах социальных сетей и создаете контент, отражающий индивидуальность вашего бренда и обращенный к вашей аудитории.
  • Стимулируйте. Найдите способы стимулировать и вознаграждать своих подписчиков за интерес к вашему контенту. Предложение скидок, подарков или чего-либо еще, что поможет вашей аудитории почувствовать, что ее ценят, будет иметь большое значение.
  • Сотрудничать. Ищите возможности для сотрудничества с другими специалистами в вашей отрасли или смежных областях. Это даст вам доступ к их аудитории и поможет вам охватить новый круг людей.
  • Анализировать. Потратьте время на анализ эффективности вашего контента, чтобы вы могли понять, что работает, а что нет. Это даст вам представление о типе контента, который больше всего резонирует с вашей аудиторией, и поможет вам усовершенствовать свой подход.

.

Основные вопросы по теме «gamedev»

Целевая аудитория

Определение целевой аудитории для игры может оказаться непростой задачей.

Выбор платформы

Игровая платформа, на которой выпущена игра, влияет на ее успех.

Монетизация

Интеграция стратегий монетизации в игру — важнейший шаг.

Визуальные эффекты и аудио

Ключевым моментом является поиск идеальных визуальных и звуковых эффектов для игры.

Обновления и стабильность

Для успеха необходимы постоянные обновления и меры по обеспечению стабильности.

Какие основные инструменты необходимы для разработки мобильных игр?

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

Существуют ли какие-либо хорошие онлайн-ресурсы для начала разработки мобильных игр?

Да, существует множество отличных ресурсов для начала разработки мобильных игр. Некоторые варианты включают учебные пособия и ресурсы с таких сайтов, как Codecademy, Udemy и Game Development Stack Exchange.

Какой тип языка программирования я должен использовать для разработки мобильных игр?

Наиболее часто используемым языком для разработки мобильных игр является C#, но существует множество других языков, таких как Java, Python и C++. Выбор языка зависит от платформы, на которую вы ориентируетесь, и типа игры, которую вы разрабатываете.Разработка мобильных игр становится все более популярной в последние годы в связи с распространением мобильных устройств и легким доступом к инструментам разработки. Обладая необходимыми знаниями, даже новички могут создавать прибыльные игры как для платформ Android, так и для iOS. Большинство мобильных игр полагаются на такие функции, как 2D- или 3D-графика и анимация, звук и простой игровой процесс. Ожидается, что в ближайшие несколько лет такие отрасли, как мобильные игры, значительно вырастут, предоставляя разработчикам множество возможностей. Кроме того, набор навыков, необходимых для разработки игр, теперь доступен через онлайн-курсы, обучающие программы и даже учебные лагеря. У разработчиков есть потенциал добиться большого успеха в своих играх, используя оптимизацию App Store (ASO) и кроссплатформенные рекламные кампании. Творческое использование социальных сетей может быть использовано для повышения узнаваемости бренда, а разработчики могут использовать микротранзакции для создания базы лояльных клиентов. В целом, будущее разработки мобильных игр чрезвычайно многообещающее и сейчас предлагает больше возможностей, чем когда-либо прежде, для новых разработчиков добиться успеха. Как и в любом процессе разработки, важно оставаться в курсе отраслевых тенденций и извлекать выгоду из расширяющейся индустрии мобильных игр.

Список используемой литературы:

Название книги Автор(ы) Описание
Начало разработки игр для iOS Патрик Алесси Это исчерпывающее руководство поможет вам создать и опубликовать игру для iPhone или iPad с помощью Unity, содержащее подробные пошаговые инструкции и множество скриншотов и иллюстраций.
Начинаю программировать игры для Android Джером Димарцио Эта книга — идеальное введение в разработку игр для пользователей Android. В нем рассматриваются основы программирования игр, а также то, как работать с Android SDK и OpenGL.
Разработка игр для iPhone Грэм Дэблинг Эта книга представляет собой исчерпывающее руководство по созданию высококачественных, увлекательных игр для iPhone. В нем рассматриваются все необходимые темы, от сбора ресурсов и управления ими до обработки состояния игры и развертывания игры в App Store.
Начало разработки игр для Windows Phone Крис Олд Эта книга идеально подходит как для начинающих, так и для опытных разработчиков игр. В нем рассматриваются основные игровые концепции, как создать игру с помощью XNA и как развернуть ее для использования на Windows Phone и в Windows Store.
Разработка мобильных игр Unity Николас Браун В этой книге предлагается подробный обзор создания мобильных игр с помощью Unity. В нем рассматриваются такие темы, как игровая механика, дизайн, написание сценариев, отладка, оптимизация производительности и развертывание в App Store.

Читать ещё

Что такое MR технологии смешанной реальности

Большинство пользователей не считает виртуальную реальность чем-то новым

Моушен дизайн и его применение в бизнесе

Моушен дизайн — это движущиеся изображения в 2d или 3d стиле.

Лучшие VR клубы Москвы

В мире VR-развлечений с каждым годом открывается все больше игровых клубов

Мобильные игры для Android – огромный рынок с потенциальной аудиторией более 2 миллиардов пользователей. Разработчики создали бесчисленное множество хитов, вроде Angry Birds, Nyan Cat и Pokemon Go, которые вдохновили миллионы людей начать собственные проекты.

Перспективы и направления

📱 Как начать разрабатывать мобильные игры для Android?

По данным Admob, 62% пользователей смартфонов устанавливают игру в течение первой недели после покупки устройства, однако лишь немногие мобильные игры могут окупить затраты на разработку. Создание приложений для Android имеет определенные особенности:

  • только 3% игроков тратят деньги в мобильных приложениях;
  • 80% продаж магазинов приложений составляют именно игры;
  • в 2010 году объем рынка мобильных игр оценивался в 33 миллиарда долларов;
  • в 2017 году выручка от мобильных игр превысила 50 миллиардов долларов, что составляет 43% всего мирового игрового рынка;
  • женщины в возрасте от 35 до 44 лет являются основными потребителями мобильных игр;
  • в 2015 году в США насчитывалось почти 165 миллионов игроков, использующих только мобильные устройства. Ожидается, что в 2021 году их количество увеличится до 213 миллионов

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

Популярные жанры

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

📱 Как начать разрабатывать мобильные игры для Android?

MOBA

Multiplayer Battle Arenas представляет собой смесь стратегии в реальном времени и экшена. Игроку предоставляется контроль над одним персонажем, известным как «чемпион» или «герой», которого можно выбрать из большого списка. Нужно собрать команду и разрушить базу противников, защищая собственную.

Arena of Valor, Vainglory и Mobile Legends входят в тройку лучших MOBA для телефонов и планшетов. В 2017 году в Arena of Valor было 200 миллионов уникальных игроков, а ежедневное среднее их количество игроков достигло 80 миллионов, что сделало игру самой популярной в мире.

Battle Royale

Battle Royale сочетает выживание с разведкой, собирая большое количество игроков с минимальным снаряжением для поиска оружия и устранения противников. Цель игры – стать последним выжившим. Идея частично вдохновлена ​​японским фильмом ужасов «Королевская битва» 2000 года. Игрок соперничает с конкурентами, пытаясь оставаться в безопасной зоне, которая со временем сужается. Победителем становится последний выживший.

В наши дни крупные стримеры на Twitch транслируют одну или несколько игр Battle Royale, что является причиной массового притока новичков в возрасте преимущественно от 8 до 14 лет. Обычно приложения Battle Royale бесплатны и монетизируются за счет продажи внутриигровых предметов как и MOBA.

MMORPG

Многопользовательские ролевые онлайн-игры – это онлайн-RPG, в которой игроки повышают уровень персонажей и приобретают новые способности. При этом сотни аккаунтов одновременно взаимодействуют друг с другом в одном мире и в режиме реального времени.

Мобильные MMORPG – упрощенные версии ПК-аналогов, здесь игроки не хотят тратить часы и месяцы на изучение механики. Некоторые мобильные MMORPG чрезвычайно популярны: например, Arcane Legends и Dungeon Hunter 5.

Головоломки

Более половины пользователей смартфонов и планшетов играют в головоломки. Candy Crush и Tetris популярны даже среди аудитории, которая не идентифицируют себя как геймеров. Логические игры сосредоточены на простых для понимания, но сложных в освоении механиках и требуют использования быстрого мышления.

Казуальные игры

Эта категория доминирует на рынке игр для мобильных устройств. Казуальные игры являются наиболее популярным жанром среди пользователей Android. Их можно легко начать и отложить в любой момент, что позволяет использовать потенциально короткие периоды игры.

📱 Как начать разрабатывать мобильные игры для Android?

Выбор движка

Как только у вас появится идея игры, стоит определиться с инструментами разработки. Можно написать приложение с нуля на Java или Kotlin в Android Studio или использовать веб-интерфейс из стандартного стека HTML5, JavaScript и CSS. В качестве примера такого подхода приведем пошаговое создание легендарной игры Bejeweled на jQuery. Для более масштабных проектов стоит присмотреться к специальным движкам.

Unity

Unity – интуитивно понятный движок с широким набором функций для разработки кроссплатформенных мобильных игр. Он поддерживает импорт из 3dsMax, Maya, Softimage, CINEMA 4D, Blender.

Хотя Unity интегрируется со всеми основными 3D-приложениями, внутренние его возможности для редактирования имеют множество ограничений. За исключением некоторых примитивных форм, все должно быть создано с помощью сторонней программы. С новой 64-битной архитектурой и поддержкой WebGL, Unity 5 считается сильным решением. Это одна из наиболее часто используемых платформ, так что вы легко найдете в сети множество учебных пособий и руководств.

Unreal

Unreal Engine 4 – последняя на данный момент версия движка UDK, выпущенного Epic Games. В нем есть возможности разработки игр для мобильных устройств, ПК и консолей. UE4 обеспечивает потрясающие графические возможности, вроде расширенного динамического освещения или одновременной обработки до миллиона частиц в сцене.

В новом движке Unreal Engine 4 много изменений по сравнению с предыдущими версиями. В качестве языка сценариев используется C++, который полностью заменил популярный некогда UnrealScript, а Kismet заменен более удобной системой Blueprint. Из-за этих перемен даже опытным дизайнерам игр придется пройти обучение, чтобы освоить обновленную версию.

Unreal поставляется с инструментами для использования технологий виртуальной и дополненной реальности для разработки мобильных игр. В «Библиотеке программиста» вы найдете подробный туториал по созданию первого объекта и освоению Unreal Engine 4.

Solar2D

Solar2D ранее был известен как Corona SDK – это кроссплатформенный инструмент разработки, использующий язык сценариев Lua. Corona Market Place содержит множество плагинов для игр 2D. Движок славится четкой документацией и активным сообществом, а одним из недостатков Solar2D является отсутствие инструментов 3D-моделирования.

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

📱 Как начать разрабатывать мобильные игры для Android?

Основные этапы разработки

Чтобы создать мобильную игру под Android, нужно пройти определенные этапы. Предлагаем вашему вниманию пошаговый план для начинающих:

Идея и план

Идея – самый сложный и ответственный шаг к созданию успешной мобильной игры. Ключ к поиску идеи – придумать что-то новаторское и увлекательное. Идея должна понравиться массовой аудитории.

Распространенный прием – модифицировать существующую идею вместо того, чтобы придумывать новую с нуля. И побольше импровизировать.

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

Выбор языка и инструментов

Вы можете выбрать любой движок и подход к разработке, в любом случае придется засесть за изучение языка программирования. Отличным началом может стать C#, Kotlin или Java.

Графика

Создание игрового дизайна намного сложнее создания дизайна обычного приложения. Приходится учитывать множество факторов: историю, персонажей и финальный внешний вид. В первую очередь именно дизайн отличает вашу игру от конкурентов, однако обсчет сложных деталей требует вычислительной мощности – нужно соблюдать баланс между хорошей графикой и производительностью, учитывая возможности мобильных устройств под Android. Далеко не у всех пользователей будут крутые флагманы.

Для создания деталей стоит овладеть основами Photoshop и/или GIMP для 2D, а также 3dsMax и/или Blender для 3D-моделей.

Работа в команде

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

Как грамотно организовать рабочие процессы в геймдев-команде, поможет разобраться этот материал.

Тестирование, запуск и монетизация

Перед запуском игры ее стоит всесторонне протестировать, но не стоит на этом зацикливаться. Многие начинающие разработчики чересчур усердно пытаются сделать программу идеальной, все время задерживая выпуск. Это серьезная ошибка – лучше быстрее выпустить релиз без критичных багов. Если игра понравится аудитории, ее можно будет улучшить.

Стоит подумать и о монетизации проекта. Существует несколько распространенных способов о ней позаботиться:

  • Покупки в приложении. Модель Freemium – самый распространенный метод монетизации мобильных игр.
  • Реклама. Во многих играх реклама сочетается с покупками в приложении. Эта стратегия может принести значительный доход.
  • Премиум-версии. Можно предложить игрокам бесплатную демо-версию и попросить заплатить за дальнейшее использование.

Развитие проекта

Если ваша игра собрала значительную аудиторию, не стоит останавливаться на достигнутом. Обновления и улучшения позволят сделать ее лучше и привлечь большее количество довольных геймеров.

***

Стремительное развитие смартфонов за 10 лет изменило игровую индустрию кардинально. От простых карманных консолей Game Boy мобильные игры эволюционировали до многопользовательских платформ со сложной механикой и интересной визуальной составляющей. Это не должно вас пугать: даже простые проекты в стиле платформеров и казуальных игр могут найти свою аудиторию благодаря доступности и простому управлению.

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

Содержание

  • Начало
  • Типичный сценарий
  • Import Android
  • Пример разработки простой 2D-игрушки Андроид
  • MainActivity, GameView, SpaceBody

Android Studio – официальная среда разработки приложений под ОС Андроид. Также она доступна пользователям Windows, Linux и Mac OS X. Мы расскажем, как создать в этой среде простую 2D-игру без применения специальных движков. Однако прежде чем приступать к работе, нужно в достаточной степени изучить саму программу.

Начало

Пользователи среды могут программировать на языках Java, C++ и Kotlin. Планируется, что последний со временем полностью заменит привычный Java, который пока остается основным. Для работы потребуется от 3 (минимум) до 8 Гб (желательно) оперативной памяти плюс дополнительный гигабайт для Android Emulator. Свободного места на жестком диске должно быть не меньше, чем 2 Гб.

Процесс установки Андроид Студио мало чем отличается от других программ

Если используется Microsoft Windows, подойдут версии 2003, Vista, 7–10. Для OS X нужен Mac от 10.8.5 до 10.13 / 10.14 (High Sierra/Mojave). Для Linux – KDE или GNOME. Изготовление приложения проходит в несколько этапов:

  • создаем новый проект;
  • разрабатываем пользовательский интерфейс;
  • добавляем навигацию, действия, дополнительные опции;
  • тестируем программу в эмуляторе.

Если собираетесь работать с Java, обязательно установите последнюю версию JDK. Скачать ее можно на официальном сайте. Помимо главной программы, для работы также потребуются элементы Андроид SDK – скрипты, библиотеки, документы, файлы. Эти компоненты будут скачаны автоматически. В установочный комплект также входит Андроид Emulator.

Проверяйте количество свободного места на диске

Следующим шагом станет определение адресов Студио и СДК. Их предлагается установить в отдельные папки. Перед началом инсталляции стоит убедиться, что на выбранном диске достаточно места. Сама Studio требует не так много свободного пространства, а вот элементы SDK занимают больше 3 Гб. Это минимум, так как затем потребуется дополнительная площадь для обновлений.

Каждое приложение, сделанное под Андроид, должно состоять из четырех точек входа:

  • Service. Компонент, обеспечивающий работу в фоновом режиме. Он отвечает за выполнение удаленных и длительных операций при выключенном визуальном интерфейсе.
  • Activity. Элементы интерактивного управления. Через класс Intent передается информация о намерениях пользователя. Активности устроены по подобию веб-страниц. Intent выполняет функцию ссылок между ними. Запускается приложение посредством activity Main.
  • Broadcast receiver. «Широковещательный приемник» передает намерения одновременно разным участникам.
  • Content provider. «Поставщик содержимого» передает нужную информацию из БД SQLite, файловой системы и других хранилищ.

Разработка приложения начинается с нового проекта. В меню последовательно выбираем Tools, Android, SDK Manager. В нашем примере последней версией является Андроид API 26. Выбирайте новейшую версию, поставив напротив нее галочку, и приступайте к скачиванию.

Выбирайте новейшую версию Андроид SDK

После нажатия New project появится форма нового проекта. В поле Application name выбираем FirstGame, Company domain – оставим без изменения. Путь к проекту Project location должен быть целиком на английском языке. В следующем окне оставьте галочку только напротив Phone and Tablet.

В этом окне определяется версия ОС для мобильных и планшетов

Теперь выберем версию ОС, с которой сможет запускаться игра. Чем ниже она будет, тем больше пользователей получат доступ к приложению. С другой стороны, разработчику тогда доступно меньше опций. Поочередно выбираем Empty Activity, Next, Next, Finish. Проект готов к работе.

С каждым запуском Студио открывается вкладка «Совет дня» (Tip of the day). Для начинающих программистов от этой опции мало толку, но по мере знакомства со средой рекомендации начнут казаться интересными и полезными. Вообще, для новичков многое будет выглядеть таинственно и даже страшновато. Не стоит бояться трудностей. Накапливайте опыт и непонятное быстро станет простым и ясным. В конце концов, это не изучение языка программирования.

Типичный сценарий

Простая игра строится по определенной схеме. Для взаимодействия с пользователем предусмотрены следующие элементы:

  • Основной дисплей. На нем разворачиваются события. По завершении процесса рекомендуется реализовать переход к таблице рекордов, если результат оказался достойным этой «доски почета».
  • Меню. С помощью этого инструмента выбирают действия и делают настройки. Он обеспечивает переход к другим элементам. Меню обычно появляется сразу после заставки. Пользователю предлагается выбор дальнейших действий: приступить к игровому процессу, ознакомиться с инструкцией и правилами, просмотреть текущие рекорды и т. д.
  • Заставка. Представляет собой краткий анонс или рекламу с изображением логотипа. Демонстрируется в начале или во время пауз. Приветствуется использование хотя бы простой анимации.
  • Справка. В этом разделе меню описывают правила. Если текст не помещается в окне целиком, необходимо обеспечить возможность прокрутки.
  • Счет. Здесь отображаются текущие рекорды участников. В данном разделе можно просмотреть список в любой момент, не дожидаясь, когда сам там окажется. Также здесь бывает доступна информация о текущем игровом счете, но последний обычно можно наблюдать на основном дисплее.
  • Настройки. Пользователь должен иметь возможность поменять игровые параметры, свой аватар и логин или зарегистрироваться в качестве нового участника.

Это основные инструменты стандартного игрового сценария. При разработке приложения какие-то можно убирать или добавлять дополнительные. Чтобы обеспечить появление этих шести экранов, нужно реализовать соответствующее число активностей.

В MenuActivity будут содержаться кнопки и другие элементы, запускающие остальные подпрограммы. SplashActivity потребуется для вывода заставки. Через несколько секунд автоматически запустится MenuActivity. Остальные активности: GameActivity (основной), SettingsActivity (настройки), ScoresActivity (счет) и HelpActivity (справка с возможностью прокрутки).

Рекомендуется также задать базовый class BaseActivity, включающий общедоступные компоненты. Для каждой Activity требуется отдельный разметочный файл с набором нужных элементов. Первоначальной задачей разработчика является освоение работы с активностями. Для получения доступа к ресурсам и настройкам, используемым Activity, нужно сделать контекст приложения. Здесь прибегают к помощи метода getApplicationContext().

Import Android

Import Android – опция, позволяющая автоматически обновлять библиотеки (public static, public void, public class, override public void и др). Такая потребность часто возникает при использовании фрагментов кода. Можно воспользоваться традиционной комбинацией Import Android – Alt + Enter.

Этим простым методом обновления импорта public static, override public void, public void и прочих нужных для работы вещей воспользоваться несложно. Однако существует и более интересный вариант – автоматический Import Android.  Для его реализации нужно последовательно выбрать в меню File, Settings, Edito, AutoImport. Остается поставить флажки напротив нужных пунктов. Теперь Import Android будет обновляться самостоятельно.

Автоматический Import Android позволяет быстро обновлять public static, public void и другие инструменты

Пример разработки простой 2D-игрушки Андроид

Наша игра Android Studio развивается по известному сюжету. Пользователь управляет космическим кораблем, уворачивающимся от метеоритов (астероидов). Последние падают с верхней части экрана, корабль – движется внизу вправо или влево, в зависимости от решений участника. При столкновении аппарата с космическим объектом объявляется Game Over.

Начнем с открытия проекта. Для этого последовательно выберем в меню программы File, New, New Project. Придумываем проекту название, вводим домен и место, где будет храниться папка. Окно, появившееся после нажатия Next, лучше оставить без изменений. В следующем выбираем Empty Activity и движемся дальше. Кликнув по клавише Finish, мы получим готовый проект.

Следующим шагом станет скачивание необходимых картинок и копирование их в папку drawable. Это изображения корабля и метеоров. После этого нужно создать layout. Открываем Text в activity_main.xml и вставляем следующий код:

Код для layout

MainActivity, GameView, SpaceBody

Для редактирования класса MainActivity меняем определение, придав ему следующий вид: public class MainActivity extends AppCompatActivity implements View.OnTouchListener {. После этого нужно задать перемены для нажатия левой (public static boolean isLeftPressed = false) и правой (public static boolean isRightPressed = false) кнопок. Следующие действия мы расписывать не будем. В итоге MainActivity должен принять следующий вид:

Код для MainActivity

Разобравшись с классом MainActivity, переходим к GameView. В определение добавляем extends SurfaceView implements Runnable. Теперь нужно задать разрешение. У современных гаджетов разные параметры. Дисплей старого мобильника не может сравниться с новым большим планшетом.

Чтобы добиться одинакового изображения на любом устройстве, поделим монитор на одинаковые «клетки» 20х28 (первый показатель – горизонталь). Если эти части будут распределены неравномерно, картинка получится сжатой или растянутой. Задаем переменные:

Переменные для «уравнивания» графики

Для метода run() устанавливается бесконечный цикл, стартующий с update(). Задачей последнего является вычисление новых координат космического корабля. По окончании расчетов на экране будет сформирован сам аппарат (draw()). Control() завершает цикл, обеспечивая паузу на 17 миллисекунд. Затем снова запускается run(). Выглядеть это будет так:

Бесконечный цикл для run()

Чтобы появился сам корабль и астероиды, нужен родительский class SpaceBody. Зададим переменные и методы:

Код для родительского класса SpaceBody

Теперь отдельный класс Ship для корабля:

Код космического корабля

После этого останется произвести компиляцию и запуск программы. На дисплее Android Studio должен возникнуть корабль, который можно кнопками перемещать вправо и влево. Следующим шагом станет добавление астероидов. Для этого разработаем class Asteroid, тоже являющийся дочерним для SpaceBody. Зададим переменные:

Код для метеоров

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

Вписываем астероиды в GameView

На этом изготовление элементарной 2D-игры можно считать завершенным. Остается скомпилировать и запустить программу. Ничто не мешает добавлять в нее новые опции. Например, стрельбу по метеорам или постоянное ускорение их движения. Но это уже тема отдельного разговора.

15K
показов

5.8K
открытий

Многие программисты так или иначе имеют тягу и интерес к разработке игр. Немалое количество спецов было замечено за написанием маленьких и миленьких игрушек, которые были разработаны за короткое время «just for fun». Большинству разработчиков за счастье взять готовый игровой движок по типу Unity/UE и попытаться создать что-то своё с их помощью, особенно упорные изучают и пытаются что-то сделать в экзотических движках типа Godot/Urho, а совсем прожжённые ребята любят писать игрушки… с нуля. Таковым любителем писать все сам оказался и я. И в один день мне просто захотелось написать что-нибудь прикольное, мобильное и обязательно — двадэшное! В этой статье вы узнаете про: написание производительного 2D-рендерера с нуля на базе OpenGL ES, обработку «сырого» ввода в мобильных играх, организацию архитектуры и игровой логики и адаптация игры под любые устройства. Интересно? Тогда жду вас в статье!

❯ Как это работает?

Конечно же разработка собственных игр с нуля — это довольно веселое и увлекательное занятие само по себе. Ведь удовольствие получает не только пользователь, который играет в уже готовую игру, но и её разработчик в процессе реализации своего проекта. В геймдеве есть множество различных и интересных задач, в том числе — и для программиста.

Один из прошлых проектов — 3D шутэмап под… коммуникаторы с Windows Mobile без видеоускорителей! Игра отлично работала и на HTC Gene, и на QTek S110!

В больших студиях принято всю нагрузку распределять на целые команды разработчиков. Артовики занимаются графикой, звуковики — музыкой и звуковыми эффектами, геймдизайнеры — продумывают мир и геймплей будущей игры, а программисты — воплощают всё это в жизнь. Однако, за последние 20 лет появилось довольно большое количество бесплатных инструментов, благодаря которым маленькие команды или даже разработчики-одиночки могут разрабатывать собственные игры сами!

Подобные инструменты включают в себя как довольно функциональные конструкторы игр, которые обычно не требуют серьёзных навыков программирования и позволяют собирать игру из логических блоков, так и полноценных игровых движков на манер Unity или Unreal Engine, которые позволяют разработчикам писать игры и продумывать их архитектуру самим. Можно сказать что именно «благодаря» доступности подобных инструментов мы можем видеть текущую ситуацию на рынке мобильных игр, где балом правят очень простые и маленькие донатные игрушки, называемые гиперкежуалом.

Но у подобных инструментов есть несколько минусов, которые банально не позволяют их использовать в реализации некоторых проектов:

  • Большой вес приложения: При сборке, Unity и UE создают достаточно объёмные пакеты из-за большого количества зависимостей. Таким образом, даже пустой проект может спокойно весить 50-100 мегабайт.
  • Неоптимальная производительность: И у Unity, и у UE очень комплексные и сложные рендереры «под капотом». Если сейчас купить дешевый смартфон за 3-4 тысячи рублей и попытаться на него накатить какой-нибудь 3 в ряд, то нас ждут либо вылеты, либо дикие тормоза.

Лично я для себя приметил ещё один минус — невозможность деплоить игры на устройства с старыми версиями Android, но это, опять же, моя личная хотелка.

Поэтому когда мне в голову пришла мысль сделать игрушку, я решил написать её с нуля — не используя никаких готовых движков, а реализовав всё сам — и игровую логику, и сам «движок» (правильнее сказать фреймворк). Не сказать, что в этом есть что-то очень сложное — в геймдеве есть отдельная каста «отшельников», которые называют себя «движкописателями» и пишут либо движки, либо игры — правда, не всегда хотя-бы одна игра доходит до релиза.

❯ Определяемся с задачами

Перед тем, как садится и пилить игрушку, нужно сразу же определится с целями и поставить перед собой задачи — какой стек технологий мы будет использовать, как будем организовать игровую логику, на каких устройствах игра должна работать и.т.п. Я прикинул и решил реализовать что-то совсем несложное, но при этом достаточно динамичное и забавное… 2D-шутер с видом сверху!

Игра будет написана полностью на Java — родном языке для Android-приложений. Пустые пакеты без зависимостей весят всего около 20 килобайт — что только нам на руку! Ни AppCompat, ни какие либо ещё библиотеки мы использовать не будем — нам нужен минимальный размер из возможных!

Итак, что должно быть в нашей игре:

  • Основная суть: Вид сверху, человечком по центру экрана можно управлять и стрелять во вражин. Цель заключается в том, чтобы набрать как можно больше очков перед тем, как игрока загрызут. За каждого поверженного врага начисляются баксы, за которые можно купить новые пушки!
  • Оружие: Несколько видов вооружения, в том числе пистолеты, дробовики, автоматы и даже пулеметы! Всё оружие можно купить в внутриигровом магазине за валюту, которую игрок заработал во время игры
  • Враги: Два типа врагов — обычный зомби и «шустрик». Враги спавнятся в заранее предусмотренных точках и начинают идти (или бежать) в сторону игрока с целью побить его.
  • Уровни: Можно сказать, простые декорации — на момент написания статьи без какого либо интерактива.

Поскольку игра пишется с нуля, необходимо сразу продумать необходимые для реализации модули:

  • Графика: Аппаратно-ускоренный рендерер полупрозрачных 2D-спрайтов с возможность аффинных трансформаций (поворот/масштаб/искривление и.т.п). На мобильных устройствах нужно поддерживать число DIP’ов (вызовов отрисовки) как можно ниже — для этого используется техника батчинга. Сам рендерер работает на базе OpenGLES 1.1 — т.е чистый FFP.
  • Ввод: Обработка тачскрина и геймпадов. Оба способа ввода очень легко реализовать на Android — для тачскрина нам достаточно повесить onTouchListener на окно нашей игры, а для обработки кнопок — ловить события onKeyListener и сопоставлять коды кнопок с кнопками нашего виртуального геймпада.
  • Звук: Воспроизведение как «маленьких» звуков, которые можно загрузить целиком в память (выстрелы, звуки шагов и… т.п), так и музыки/эмбиента, которые нужно стримить из физического носителя. Тут практически всю работу делает за нас сам Android, для звуков есть класс — SoundPool (который, тем не менее, не умеет сообщать о статусе проигрывания звука), для музыки — MediaPlayer. Есть возможность проигрывать PCM-сэмплы напрямую, чем я и воспользовался изначально, но с ним есть проблемы.
  • «Физика»: Я не зря взял этот пункт в кавычки :) По сути, вся физика у нас — это один метод для определения AABB (пересечения прямоугольник с прямоугольником). Всё, ни о какой настоящей физике и речи не идет :)

Поэтому, с учетом требований описанных выше, наша игра будет работать практически на любых смартфонах/планшетах/тв-приставках кроме китайских смартфонов на базе чипсета MT6516 без GPU из 2010-2011 годов. На всех остальных устройствах, включая самый первый Android-смартфон, игра должна работать без проблем. А вот и парк устройств, на которых мы будем тестировать нашу игру:

С целями определились, самое время переходить к практической реализации игры! По сути, её разработка заняла у меня около дву-трех дней — это с учетом написания фреймворка. Но и сама игра совсем несложная :)

❯ Рендерер

Начинаем, мы конечно же, с инициализации контекста GLES и продумывания архитектуры нашего будущего фреймворка. Я всегда ставил рендерер на первое место, поскольку реализация остальных модулей не особо сложная и их можно дописать прямо в процессе разработки игры.

private void attachMainLoop() {
GLView.setRenderer(new GLSurfaceView.Renderer() {
@Override
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
Engine.log(«GL context successfully created»);
Engine.log(«Vendor: %s», GLES10.glGetString(GLES10.GL_VENDOR));
Engine.log(«Renderer: %s», GLES10.glGetString(GLES10.GL_RENDERER));

Text = new TextRenderer();

setupRenderState();
Engine.Current.loadResources();
}

@Override
public void onSurfaceChanged(GL10 gl10, int w, int h) {
DeviceWidth = w;
DeviceHeight = h;

GLES10.glMatrixMode(GLES10.GL_PROJECTION);
GLES10.glLoadIdentity();
GLES10.glOrthof(0, w, h, 0, 0, 255);

Camera.autoAdjustDistance(w, h);

Engine.log(«New render target resolution: %dx%d», w, h);
}

@Override
public void onDrawFrame(GL10 gl10) {
Engine.Current.drawFrame();
}
});
GLView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);

Engine.Current.MainActivity.setContentView(GLView);
}

По сути, в современном мире, 2D — это частный случай 3D, когда рисуются всё те же примитивы в виде треугольников, но вместо перспективной матрицы, используется ортографическая матрица определенных размеров. Во времена актуальности DirectDraw (середина-конец 90х) и Java-телефонов, графику обычно не делали адаптивной, из-за чего при смене разрешения, игровое поле могло растягиваться на всю площадь дисплея. Сейчас же, когда разброс разрешений стал колоссальным, чаще всего можно встретить два подхода к организацию проекции:

  • Установка ортографической матрицы в фиксированные размеры: Если координатная система уже была завязана на пиксели, или по какой-то причине хочется использовать именно её, то можно просто завязать игру на определенном разрешении (например, 480×320, или 480×800). Растеризатор формально не оперирует с пикселями — у него есть нормализованные координаты -1..1 (где -1 — начало экрана, 0 — середина, 1 — конец, это называется clip-space), а матрица проекции как раз и переводит координаты геометрии в camera-space координатах в clip-space — т.е в нашем случае, автоматически подгоняет размеры спрайтов из желаемого нами размера в физический. Обратите внимание, физические движки обычно рассчитаны на работу в метрических координатных системах. Попытки задавать ускорения в пикселях вызывают рывки и баги.
  • Перевод координатной системы с пиксельной на метрическую/абстрактную:Сейчас этот способ используется чаще всего, поскольку именно его используют самые популярные движки и фреймворки. Если говорить совсем просто — то мы задаем координаты объектов и их размеры не относительно пикселей, а относительно размеров этих объектов в метрах, или ещё какой-либо абстрактной системы координат. Этот подход близок к обычной 3D-графике и имеет свои плюшки: например, можно выпустить HD-пак для вашей игры и заменить все спрайты на варианты с более высоким разрешением, не переделывая половину игры.

Для совсем простых игр я выбираю обычно первый подход. Самое время реализовать главный метод всего рендерера — рисование спрайтов. В моём случае, спрайты не были упакованы в атласы (одна текстура, содержащая в себе целую анимацию или ещё что-то в этом духе), поэтому и возможность выборки тайла из текстуры я реализовывать не стал. В остальном, всё стандартно:

public void drawSprite(Sprite spr, float x, float y, float width, float height, float z, float rotation, Color col) {
if(spr != null) {
if(col == null)
col = Color.White;

if(width == 0)
width = spr.Width;

if(height == 0)
height = spr.Height;

// Convert position from world space to screen space
x = x — Camera.X;
y = y — Camera.Y;

if(x > ViewWidth || y > ViewHeight || x + width < 0 || y + height < 0) {
Statistics.OccludedDraws++;

return;
}

GLES10.glEnable(GLES10.GL_TEXTURE_2D);
GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, spr.TextureId);

GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
GLES10.glLoadIdentity();
GLES10.glTranslatef(x + (width / 2), y + (height / 2), 0);
GLES10.glRotatef(rotation, 0, 0, 1);
GLES10.glTranslatef(-(width / 2), -(height / 2), 0);
GLES10.glScalef(width, height, 1.0f);

vertex(0, 0, 0, 0, col);
vertex(1, 0, 1, 0, col);
vertex(1, 1, 1, 1, col);
vertex(0, 0, 0, 0, col);
vertex(0, 1, 0, 1, col);
vertex(1, 1, 1, 1, col);
vPosBuf.rewind();
vColBuf.rewind();
vUVBuf.rewind();

GLES10.glVertexPointer(2, GLES10.GL_FLOAT, 0, vPosBuf);
GLES10.glColorPointer(4, GLES10.GL_FLOAT, 0, vColBuf);
GLES10.glTexCoordPointer(2, GLES10.GL_FLOAT, 0, vUVBuf);

GLES10.glDrawArrays(GLES10.GL_TRIANGLES, 0, 6);

Statistics.DrawCalls++;

}
}

private void vertex(float x, float y, float u, float v, Color col) {
vPosBuf.putFloat(x);
vPosBuf.putFloat(y);
vColBuf.putFloat(col.R);
vColBuf.putFloat(col.G);
vColBuf.putFloat(col.B);
vColBuf.putFloat(col.A);
vUVBuf.putFloat(u);
vUVBuf.putFloat(v);
}

Всё более чем понятно — преобразуем координаты спрайта из world-space в camera-space, отсекаем спрайт, если он находится за пределами экрана, задаем стейты для GAPI (на данный момент, их всего два), заполняем вершинный буфер геометрией и рисуем на экран. Никакого смысла использовать VBO здесь нет, а на nio-буфферы можно получить прямой указатель без лишних копирований, так что никаких проблем с производительностью не будет. Обратите внимание — вершинный буфер выделяется заранее — аллокации каждый дравколл нам не нужны и вредны.

// Vertex format:
// vec2 pos; — 8 bytes
// vec4 color; — 16 bytes
// vec2 uv; — 8 bytes
// 32 bytes total
int numVerts = 6;
vPosBuf = ByteBuffer.allocateDirect((4 * 8) * numVerts);
vColBuf = ByteBuffer.allocateDirect((4 * 16) * numVerts);
vUVBuf = ByteBuffer.allocateDirect((4 * 8) * numVerts);
vPosBuf.order(ByteOrder.LITTLE_ENDIAN);
vColBuf.order(ByteOrder.LITTLE_ENDIAN);
vUVBuf.order(ByteOrder.LITTLE_ENDIAN);

Обратите внимание на вызовы ByteBuffer.order — это важно, по умолчанию, Java создаёт все буферы в BIG_ENDIAN, в то время как большинство Android-устройств — LITTLE_ENDIAN, из-за этого можно запросто накосячить и долго думать «а почему у меня буферы заполнены правильно, но геометрии на экране нет!?».

В процессе разработки игры, при отрисовке относительно небольшой карты с большим количеством тайлов, количество вызовов отрисовки возросло аж до 600, из-за чего FPS в игре очень сильно просел. Связано это с тем, что на старых мобильных GPU каждый вызов отрисовки означал пересылку состояния сцены видеочипу, из-за чего мы получали лаги. Фиксится это довольно просто: реализацией батчинга — специальной техники, которая «сшивает» большое количество спрайтов с одной текстурой в один и позволяет отрисовать хоть 1000, хоть 100000 спрайтов в один проход! Есть два вида батчинга, статический — когда объекты «сшиваются» при загрузке карты/в процессе компиляции игры (привет Unity) и динамический — когда объекты сшиваются прямо на лету (тоже привет Unity). На более современных мобильных GPU с поддержкой GLES 3.0 есть также инстансинг — схожая технология, но реализуемая прямо на GPU. Суть её в том, что мы передаём в шейдер параметры объектов, которые мы хотим отрисовать (матрицу, настройки материала и.т.п) и просим видеочип отрисовать одну и ту же геометрию, допустим, 15 раз. Каждая итерация отрисовки геометрии будет увеличивать счетчик gl_InstanceID на один, благодаря чему мы сможем расставить все модельки на свои места! Но тут уж справедливости ради стоит сказать, что в D3D10+ можно вообще стейты передавать на видеокарту «пачками», что здорово снижает оверхед одного вызова отрисовки.

Для загрузки спрайтов используется встроенный в Android декодер изображений. Он умеет работать в нескольких режимах (ARGB/RGB565 и.т.п), декодировать кучу форматов — в том числе и jpeg, что положительно скажется на финальном размере игры.

public void upload(ByteBuffer data, int width, int height, int format) {
if(data != null) {
int len = data.capacity();

GLES10.glEnable(GLES10.GL_TEXTURE_2D);
GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, TextureId);
GLES10.glTexImage2D(GLES10.GL_TEXTURE_2D, 0, GLES10.GL_RGBA, width, height, 0, GLES10.GL_RGBA, GLES10.GL_UNSIGNED_BYTE, data);
GLES11.glTexParameteri(GLES10.GL_TEXTURE_2D, GLES10.GL_TEXTURE_MIN_FILTER, GLES10.GL_NEAREST);
GLES11.glTexParameteri(GLES10.GL_TEXTURE_2D, GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_NEAREST);

Width = width;
Height = height;
}
}

public static Sprite load(String fileName) {
InputStream is = null;
try {
is = Engine.Current.MainActivity.getAssets().open(«sprites/» + fileName);

BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inPreferredConfig = Bitmap.Config.ARGB_8888;

Bitmap bmp = BitmapFactory.decodeStream(is, null, opts);
ByteBuffer buf = ByteBuffer.allocateDirect(bmp.getRowBytes() * bmp.getHeight());
bmp.copyPixelsToBuffer(buf);
buf.rewind();

Sprite ret = new Sprite();
ret.upload(buf, bmp.getWidth(), bmp.getHeight(), FORMAT_RGBA);

return ret;
} catch (IOException e) {
Engine.log(«Failed to load sprite %s», fileName);

throw new RuntimeException(e);
}
}

На этом реализация рендерера закончена. Да, все вот так просто :)Переходим к двум остальным модулям — звук и ввод.

❯ Звук и ввод

Как я уже говорил, звук я решитл реализовать на базе уже существующей звуковой подсистемы Android. Ничего сложного в её реализацир нет, можно сказать, нам остаётся лишь написать обёртку, необходимую для работы. Изначально я написал собственный загрузчик wav-файлов и хотел использовать AudioTrack — класс для воспрозизведения PCM-звука напрямую, но мне не понравилось, что в нём нет разделения на источники звука и буферы, из-за чего каждый источник вынужден заниматься копированием PCM-потока в новый и новый буфер…

Полная реализация звукового потока выглядит так. И да, с SoundPool нет возможности получить позицию проигрывания звука или узнать, когда проигрывание закончилось. Увы.

public static class Instance {
private AudioStream parent;
private int id;

Instance(AudioStream parent) {
this.parent = parent;
}

public void play() {
id = sharedPool.play(parent.streamId, Audio.MasterAudioLevel, Audio.MasterAudioLevel, 0, 0, 1.0f);
}

public void stop() {
sharedPool.stop(id);
}
}

private static SoundPool sharedPool;
private int streamId;

static {
Engine.log(«Allocating SoundPool»);
sharedPool = new SoundPool(255, AudioManager.STREAM_MUSIC, 0);
}

public AudioStream(int streamId) {
this.streamId = streamId;
}

@Override
protected void finalize() throws Throwable {
sharedPool.unload(streamId);
super.finalize();
}

public static AudioStream load(String fileName) {
AssetManager assets = Engine.Current.MainActivity.getAssets();

try {
AssetFileDescriptor afd = assets.openFd(«sounds/» + fileName);
int streamId = sharedPool.load(afd, 0);

return new AudioStream(streamId);
} catch (IOException e) {
Engine.log(«Failed to load audio stream %s», fileName);

return null;
}
}

Не забываем и про музыку:

private MediaPlayer mediaPlayer;
private boolean ready;

public MusicStream(MediaPlayer player) {
mediaPlayer = player;
}

public void forceRelease() {
if(mediaPlayer.isPlaying())
mediaPlayer.stop();

mediaPlayer.release();
}

public void play() {
if(!mediaPlayer.isPlaying())
mediaPlayer.start();
}

public void pause() {
if(mediaPlayer.isPlaying())
mediaPlayer.pause();
}

public void stop() {
if(!mediaPlayer.isPlaying())
mediaPlayer.stop();
}

public boolean isPlaying() {
return mediaPlayer.isPlaying();
}

public void setLoop(boolean isLooping) {
mediaPlayer.setLooping(isLooping);
}

public static MusicStream load(String fileName) {
AssetManager assets = Engine.Current.MainActivity.getAssets();

try {
AssetFileDescriptor afd = assets.openFd(«music/» + fileName);
MediaPlayer player = new MediaPlayer();
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
player.setVolume(0.3f, 0.3f); // TODO: Move volume settings to Audio
player.prepare();

return new MusicStream(player);
} catch (IOException e) {
Engine.log(«Failed to load audio stream %s», fileName);

return null;
}
}

Сама реализация джойстика крайне простая — запоминаем координаты, куда пользователь поставил палец и затем считаем дистанцию положения пальца относительно центральной точки, параллельно нормализовывая их относительно максимальной дистанции:

Основа для игры есть, теперь переходим к её реализации!

❯ Пишем игру

Писать игру я начал с создания первого уровня и реализации загрузчика уровней. В качестве редактора, я выбрал популярный и широко-известныйTileEd— удобный редактор с возможностью экспорта карт в несколько разных форматов. Я лично выбрал Json, поскольку в Android уже есть удобный пакет для работы с этим форматом данных.

private void parseJson(String json) {
try {
JSONObject obj = new JSONObject(json);

width = obj.getInt(«width»);
height = obj.getInt(«height»);

JSONArray jtileSet = obj.getJSONArray(«tilesets»).getJSONObject(0).getJSONArray(«tiles»);
for(int i = 0; i < jtileSet.length(); i++) {
JSONObject tile = jtileSet.getJSONObject(i);

String name = tile.getString(«image»);
name = name.substring(name.lastIndexOf(«/») + 1);
tileSet[tile.getInt(«id»)] = Sprite.load(name);
}

JSONArray layers = obj.getJSONArray(«layers»);

this.tiles = new byte[width * height];
Engine.log(«Level size %d %d», width, height);

for(int i = 0; i < layers.length(); i++) {
JSONObject layer = layers.getJSONObject(i);
boolean isTileData = layer.has(«data»);

if(isTileData) {
JSONArray tiles = layer.getJSONArray(«data»);

Engine.log(«Loading tile data»);
for(int j = 0; j < tiles.length(); j++)
this.tiles[j] = (byte)(tiles.getInt(j) — 1);
} else {
JSONArray objects = layer.getJSONArray(«objects»);

for(int j = 0; j < objects.length(); j++) {
JSONObject jobj = objects.getJSONObject(j);

Prop prop = new Prop();
prop.Sprite = tileSet[jobj.getInt(«gid») — 1];
prop.Name = jobj.getString(«name»);
prop.X = (float)jobj.getDouble(«x»);
prop.Y = (float)jobj.getDouble(«y»);
prop.Visible = true;

String type = jobj.getString(«type»);
if(type.equals(«invisible»))
prop.Visible = false;

props.add(prop);
}
}
}
} catch (JSONException e) {
e.printStackTrace(); // Level loading is unrecoverable error
throw new RuntimeException(e);
}
}

Запекание батчей:

private void buildBatch() {
batches = new HashMap<Sprite, Graphics2D.StaticBatch>();

for(int i = 0; i < width; i++) {
for(int j = 0; j < height; j++) {
Sprite tile = tileSet[tiles[j * width + i]];

if(!batches.containsKey(tile))
batches.put(tile, new Graphics2D.StaticBatch(tile, width * height));

batches.get(tile).addInstance(i * 32, j * 32, Graphics2D.Color.White);
}
}

for(Sprite spr : batches.keySet()) {
batches.get(spr).prepare();
}

Engine.log(«Generated %d batches», batches.size());
}

Карта делится на 3 базовые понятия: тайлы — фон, с изображением травы/асфальта/земли и.т.п, пропы — статичные объекты по типу деревьев и кустов и сущности — объекты, участвующие в игровом процессе, т.е игрок, зомби и летящие пули. Система сущностей реализована в виде абстрактного базового класса, который реализовывает логику апдейтов, просчитывает Forward-вектор и выполняет другие необходимые задачи:

public abstract class Entity {

public float X, Y;
public float ForwardX, ForwardY; // Forward vector
public float RightX, RightY;
public float Rotation;
public boolean IsVisible;

public int DrawingOrder;

public float distanceTo(float x, float y) {
x = X — x;
y = Y — y;

return (float)Math.sqrt((x * x) + (y * y));
}

public boolean AABBTest(Entity ent, float myWidth, float myHeight, float width, float height) {
return X < ent.X + width && Y < ent.Y + height && ent.X < X + myWidth && ent.Y < Y + myHeight;
}

public void recalculateForward() {
ForwardX = (float)Math.sin(Math.toRadians(Rotation));
ForwardY = -(float)Math.cos(Math.toRadians(Rotation));
}

public void update() {
recalculateForward();
}

public void draw() {

}
}

После этого, я приступил к реализации игрока, оружия и механики стрельбы. В целом, практически всю логику игрока можно описать в виде одного метода update: обрабатываем ввод и ходьбу с джойстика, поворачиваем игрока в сторону пальца на экране и пока зажата какая-либо область на экране мы ходим и стреляем:

@Override
public void update() {
super.update();

joyInput.update();

float inpX = joyInput.VelocityX;
float inpY = joyInput.VelocityY;

if(Engine.Current.Input.Gamepad.Buttons[Input.GAMEPAD_DPAD_LEFT]) {
inpX = -1;
Rotation = 270;
}

if(Engine.Current.Input.Gamepad.Buttons[Input.GAMEPAD_DPAD_RIGHT]) {
inpX = 1;
Rotation = 90;
}

if(Engine.Current.Input.Gamepad.Buttons[Input.GAMEPAD_DPAD_DOWN]) {
inpY = 1;
Rotation = 180;
}

if(Engine.Current.Input.Gamepad.Buttons[Input.GAMEPAD_DPAD_UP]) {
inpY = -1;
Rotation = 0;
}

X += inpX * (WALK_SPEED * Engine.Current.DeltaTime);
Y += inpY * (WALK_SPEED * Engine.Current.DeltaTime);

Engine.Current.Graphics.Camera.X = X — (Engine.Current.Graphics.ViewWidth / 2);
Engine.Current.Graphics.Camera.Y = Y — (Engine.Current.Graphics.ViewHeight / 2);

int finger = 0;
if((finger = Engine.Current.Input.isTouchingZone(0, 0, Engine.Current.Graphics.ViewWidth, Engine.Current.Graphics.ViewHeight)) != -1) {
Input.TouchState state = Engine.Current.Input.Touches[finger];

aimX = state.X;
aimY = state.Y;

// Convert player position from world-space, to screen-space
float ptfX = (X — Engine.Current.Graphics.Camera.X) — state.X;
float ptfY = (Y — Engine.Current.Graphics.Camera.Y) — state.Y;

Rotation = (float)Math.toDegrees(Math.atan2(-ptfX, ptfY));
recalculateForward();

if(nextAttack < 0) {
GunItem currGun = Guns.get(EquippedGun);
currGun.Gun.FireEffect.createInstance().play();
nextAttack = currGun.Gun.Speed;

Bullet bullet = new Bullet();
bullet.Speed = 15;
bullet.LifeTime = 3.0f;
bullet.Rotation = Rotation;
bullet.Damage = currGun.Gun.Damage;

float bullX = sprites[currGun.Gun.Sprite].Width / 2;
float bullY = sprites[currGun.Gun.Sprite].Height / 2;
float fwXFactor = ForwardX * 19;
float fwYFactor = ForwardY * 19;

bullet.X = X + bullX — (Bullet.Drawable.Width / 2) + fwXFactor;
bullet.Y = Y + bullY — (Bullet.Drawable.Height / 2) + fwYFactor;

Game.current.World.spawn(bullet);
}
}
nextAttack -= Engine.Current.DeltaTime;
}

Ну и не забываем про реализацию зомби. Она тоже очень простая: есть базовый класс Zombie, от которого наследуются все монстры и который реализует несколько необходимых методов — повернуться в сторону игрока, идти вперед и конечно же атака!

@Override
public void update() {
super.update();

Player player = Game.current.World.Player;
rotateTowardsEntity(player);

if(distanceTo(player.X, player.Y) > 35)
moveForward(WALK_SPEED * Engine.Current.DeltaTime);
}

❯ Что у нас есть на данный момент?

Честно сказать, статья итак уже получилась слишком длинной. Я очень хотел написать игру, о разработке которой можно было бы рассказать в рамках одной не особо большой статьи, но с моим стилем написания текстов так сделать не выйдет. Придется разбивать на части!Однако, некоторый прогресс уже есть и мы можем даже поиграть в игру на текущем ее этапе!

Как мы видим, игра (а пока что — proof of concept) работает довольно неплохо на всех устройствах, которые были выбраны для тестирования. Однако это ещё не всё — предстоит добавить конечную цель игры (набор очков), магазин стволов и разные типы мобов. Благо, это всё реализовать уже совсем несложно :)

❯ Заключение

Написать небольшую игрушку с нуля в одиночку вполне реально. Разработка достаточно больших проектов конечно же требует довольно больших человекочасов, однако реализовать что-то своё, маленькое может и самому!

Пишите своё мнение в комментариях. Если вам вдруг интересна тематика самопальной разработки игр, то постараюсь выпускать подобные статьи почаще!

Статья подготовлена при поддержке TimeWeb Cloud. Подписывайтесь на меня и Таймвеб, чтобы не пропускать новые статьи каждую неделю.
Но тут я наврал чутка — следующая статья выйдет послезавтра — прошлую неделю я отдыхал :)

Понравилась статья? Поделить с друзьями:
  • Руководство девушек в греховности сериал смотреть
  • Атомфлот официальный сайт руководство
  • Руководство по ремонту хендай туссан 2019 года
  • Sony mhc gnz9d инструкция на русском
  • Saeco royal classic инструкция на русском языке