Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Работа с ресурсами приложения

Лабораторная работа №3, 4

Разработка игрового приложения

 

Цель работы: Научиться разрабатывать простые игровые приложения для мобильной платформы Android.

Теоретические сведения

При работе с 2D графикой в Android перерисовку можно выполнять используя полотно класса Canvas. Проще всего это сделать с помощью своего класса, унаследованного от View. Необходимо просто описать метод onDraw() и использовать предоставленный в качестве аргумента canvas для выполнения всех необходимых действий. Однако этот подход имеет свои недостатки. Метод onDraw() вызывается системой. Вручную же можно использовать метод invalidate(), говорящий системе о необходимости перерисовки. Но вызов invalidate() не гарантирует незамедлительного вызова метода onDraw(). Поэтому, если необходимо постоянно делать перерисовку, как в случае динамической игры, вышеописанный способ вряд ли подойдет. Поэтому лучше использовать другой способ - с использованием класса SurfaceView.

Класс SurfaceView

Особенность класса SurfaceView заключается в том, что он предоставляет отдельную область для рисования, действия с которой должны быть вынесены в отдельный поток приложения. Таким образом, приложению не нужно ждать, пока система будет готова к перерисовке всей иерархии view-элементов. Вспомогательный поток может использовать полотно canvas объекта SurfaceView для перерисовки с той скоростью, которая необходима.

Вся реализация сводится к двум основным шагам:

1.Создание класса, унаследованного от SurfaceView и реализующего интерфейс SurfaceHolder.Callback.

2.Создание потока, который будет управлять перерисовкой.

 

Создание класса

Создаваемый класс должен расширять SurfaceView и реализовать интерфейс SurfaceHolder.Callback. Этот интерфейс предлагает реализовать три метода: surfaceCreated(), surfaceChanged() и surfaceDestroyed(), вызываемые соответственно при создании области для рисования, ее изменении и разрушении.

Работа с полотном для рисования осуществляется не напрямую через созданный класс, а с помощью объекта SurfaceHolder. Получить его можно, вызвав метод getHolder(). Именно этот объект будет предоставлять canvas для перерисовки:

 

public class CannonView extends SurfaceView implements SurfaceHolder.Callback {

public CannonView(Context context, AttributeSet attrs) {

super(context, attrs);

 

getHolder().addCallback(this);

}

 

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

 

}

 

@Override

public void surfaceCreated(SurfaceHolder holder) {

 

}

 

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

 

}

}

 

В конструкторе класса получаем объект SurfaceHolder и с помощью метода addCallback() задаем, что хотим получать соответствующие обратные вызовы.

В методе surfaceCreated(), как правило, необходимо начинать выполнять перерисовку, а в surfaceDestroyed(), наоборот, завершать ее.

 

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

 

Очевидно, создаваемый класс должен наследовать класс потока Thread. В конструкторе он должен принимать в качестве аргумента интерфейс SurfaceHolder. Также в классе нам понадобится переменная-флаг, указывающая на то, работает ли поток, т. е. выполняется ли перерисовка графических элементов игры, а также метод для изменения ее значения. Естественно, нужно также переопределить метод run().

Так как язык Java допускает вложенность классов данный класс можно вложить в класс CannonView и сделать его приватным. В итоге получим примерно следующее:

 

private class CannonThread extends Thread {

private SurfaceHolder surfaceHolder;

private boolean threadIsRunning = true;

 

public CannonThread(SurfaceHolder holder) {

surfaceHolder = holder;

 

}

 

public void setRunning(boolean running) {

threadIsRunning = running;

 

}

 

@Override

public void run() {

Canvas canvas = null;

long previousFrameTime = System.currentTimeMillis();

while (threadIsRunning) {

try {

canvas = surfaceHolder.lockCanvas(null);

synchronized(surfaceHolder) {

long currentTime = System.currentTimeMillis();

double elapsedTimeMS = currentTime - previousFrameTime;

totalElapsedTime += elapsedTimeMS / 1000.00;

updatePositions(elapsedTimeMS); // обновление состояния игры

 

// Рисование графических элементов на canvas

 

previousFrameTime = currentTime; // обновление пред. времени

}

}

finally {

if (canvas!= null)

surfaceHolder.unlockCanvasAndPost(canvas);

}

}

}

}

 

Рисование графики, используя классы Paint и Canvas

 

Методы класса Canvas (пакет android.graphics) применяются для рисования текста, линий и окружностей. Каждый метод рисования класса Canvas использует объект класса Paint (пакет android.graphics), который содержит характеристики рисования, включая цвет, толщину линии, размер шрифта и другие параметры. Эти характеристики реализуются с помощью метода drawGameElements(). Чтобы получить дополнительные сведения о характеристиках, используемых для рисования с помощью объекта Paint, посетите веб-сайт: developer.android.com/reference/android/graphics/Paint.html.

 

Добавление звука, используя классы SoundPool и AudioManager

Звуковыми эффектами приложения можно управлять с помощью класса SoundPool (пакет android.media). Доступны загрузка, воспроизведение и выгрузка звуков. Для воспроизведения звуков используется один из нескольких аудиопотоков Android, включающих потоки для оповещений, тонов DTMF, музыки, уведомлений, телефонных звонков, системных звуков и рингтонов. В документации Android рекомендуется использовать для воспроизведения звука в играх музыкальный аудиопоток. С помощью метода setVolumeControlStream() класса Activity определяется возможность управления громкостью звука в игре кнопками регулировки громкости устройства, которые также используются для изменения громкости воспроизведения музыки. Метод получает константу из класса AudioManager (пакет android.media).

Задание на разработку

В разрабатываемой игре CannonGame требуется разрушить состоящую из семи частей мишень в течение 10 секунд, отведенных на игру (рис. 1).

Рисунок 1. Общий вид приложения CannonGame

 

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

 

 

Рисунок 2. После разрушения всех семи секций мишени в окне AlertDialog появляется сообщение о выигрыше

 

 

Рисунок 3. Если время истекает до разрушения всех секций мишени, в окне AlertDialog отобразится сообщение о проигрыше

 

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

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

 

Управление игрой

Одиночное касание экрана задает направление выстрела для пушки. Дважды коснитесь экрана, чтобы выстрелить из пушки. Вы сможете выстрелить пушечным ядром только в том случае, если на экране не отображается другое ядро. Если приложение выполняется на экране AVD, в качестве «пальца» будет использоваться мышь. Попытайтесь уничтожить мишень как можно быстрее. Если показания таймера обнулятся, игра завершится.

Программирование проекта

Создание проекта

1. Обычным образом создайте новый проект с именем CannonGame.

2. Затем в окне редактора отобразите Java-код главной активности приложения (MainActivity) и измените базовый (супер-) класс этой активности в первой строке кода

 

public class MainActivity extends ActionBarActivity {

 

или

 

public class MainActivity extends AppCompatActivity {

 

на класс Activity. В результате измененная строка должна выглядеть как:

 

public class MainActivity extends Activity {

 

А так как в автоматически сгенерированном коде отсутствует инструкция импорта вновь включенного базового класса, то в секцию импорта нужно добавить:

 

import android.app.Activity;

 

Работа с ресурсами приложения

 

Файл AndroidManifest.xml

В листинге ниже представлен примерный XML-код файла манифеста приложения AndroidManifest.xml. В нем атрибуту элемента активности android:screenOrientation присвоено значение "portrait"(строка 9), в результате чего активность приложения всегда отображается в портретном режиме:

 

 

Файл strings.xml

В листинге ниже представлен вариант XML-кода файла strings.xml:

 

 

В файле strings.xml определяются форматные строки (строки 4–5 и 9–10). В форматных строках, включающих несколько спецификаторов формата, спецификаторы нумеруются (например, для задач локализации приложения). Запись 1$ в спецификаторе %1$.1d (строка 5) указывает на то, что первый аргумент после форматной строки должен заменять спецификатор формата %1$d. Аналогично, запись %2$.1f указывает на то, что второй аргумент после форматной строки должен заменять спецификатор формата %2$.1f. Буква d в первом спецификаторе формата указывает на то, что выполняется форматирование в виде десятичного целого числа, а буква f во втором спецификаторе формата определяет форматирование в виде значения с плавающей точкой. В локализованных версиях файла strings.xml спецификаторы формата %1$d и %2$.1f могут переупорядочиваться в случае необходимости. То есть значение первого аргумента после форматной строки в вызове метода getString() класса Resources заменяет %1$d, а второй аргумент заменяет %2$.1f, независимо от того, в каком порядке они появляются в ресурсной строке формата.

 

Файл activity_main.xml

Сначала с активности нужно удалить текстовый элемент, сгенерированный по умолчанию и содержащий текст “Hello world!”.

После этого в интерфейс добавляется единственный компонент главной активности приложения — объект (экземпляр) пользовательского (под-) класса CannonView, производного (расширяющего) от системного базового (супер-) класса SurfaceView. Процесс определения пользовательского класса CannonView будет описан позже. В листинге ниже приведен пример XML-текста окончательного файла activity_main.xml, в который вручную добавлен XML-элемент, показанный в строках 6 – 11. Этот элемент определяет, что компонент CannonView занимает всю ширину и высоту активности приложения:

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...