Принципы работы с игровыми приложениями на Java

 

Содержание


Введение

. Начало работы с Java

1.1 Java Runtime Environment

.2 Java development Kit

1.3 Документация Java API

. Среда программирования Java

.1 Компиляция исходного кода через командную строку

.2 Java IDE

. Основные моменты создания игрового 2d - приложения

.1 Анимация при помощи таймера

.2 Анимация при помощи потоков

.3 Frame Per Second при использовании потоков

.4Создание фрейма, вставка контейнера

.5 Методы update() и draw()

.6 Game State Manager

.7 События кнопок

. Графические примитивы

.1 Прямая линия

.2 Цвет

.3 Цвет фона

.4 Прямоугольник

.5 Овал

.6 Многоугольник

.7 Объект точки

.8 Изображение

Заключение

Список использованных источников

Приложения

Введение


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

Требования к программистам постоянно увеличиваются, за счет бурного развития отрасли. Так или иначе, первостепенной важности вопрос, который встает перед каждым IT-специалистом - это правильный выбор языка программирования, в пределах которого программист будет совершенствоваться. Конечно же, профессионалы и близко не ограничиваются одним языком, но у каждого специалиста высокие познания развиты в пределах одного - двух языков. Если брать многочисленные статистики по языкам программирования, то первое место на данный момент по популярности и по востребованности, делят языки Java и PHP. Именно язык Java и был выбран мной для активного самостоятельного изучения. Далее мне хотелось бы упомянуть ключевые моменты этого интересного языка программирования.- это язык программирования и вычислительная платформа, впервые выпущенная компанией Sun Microsystems в 1995 году. Это базовая технология, на которой основываются многие современные программы (в том числе утилиты, игры и бизнес-приложения). Java работает на более чем 850 млн. персональных компьютерах и в миллиардах устройств (в том числе в мобильных телефонах и в телевизорах) по всему миру. На языке java разрабатываются desktop-приложения различных уровней сложности, web - интерфейсы.

Одно из главных преимуществ Java - это кроссплатформенность (независимость от архитектуры компьютера). Т.е. «программа, единожды написанная на Java, будет работать везде». В Java это достигается за счет виртуальной машины JVM (Java Virtual Machine), которая интерпретирует байт - код. Также JVM существенно повышает безопасность, поскольку в процессе работы можно оценить последствия каждой конкретной команды.

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

Также, язык Java активно используется для создания различных игровых приложений. Большая часть мобильных игр под операционную систему Symbian были написаны на Java, благодаря технологии j2me.ME - подмножество платформы Java для устройств, ограниченных в ресурсах, например: сотовых телефонов, карманных компьютеров, ресиверов цифрового телевидения, проигрывателей дисков Blu-ray. В настоящее время является устаревшей технологией из-за прихода на рынок Android и IOS.

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

Немалую роль занимают и desktop - игры, написанные на Java. В основном, разработка игр под pc ведется либо при помощи различных игровых Java библиотек (LWJGL - lightweight Java game library, Slick 2D, libGDX и т.д.).

Однако, при написаний игрового движка «с нуля», игровые библиотеки не используются, а весь процесс разработки ведется на «чистом» Java SE.

Существует ошибочное мнение, что платформа Java не подходит для написания сложных игровых проектов. Программы, написанные на Java, имели репутацию более медленных и занимающих больше оперативной памяти, чем написанные на языке Си. Тем не менее, скорость выполнения программ, написанных на языке Java, была существенно улучшена с выпуском в 1997 - 1998 годах так называемого JIT-компилятора версии 1.1 в дополнение к другим особенностям языка, для поддержки лучшего анализа кода (такие как внутренние классы, класс StringBuffer, упрощенные логические вычисления и т. д.). Кроме того, была произведена оптимизация виртуальной машины Java - с 2000 года для этого используется виртуальная машина HotSpot.

Еще одним преимуществом в сторону выбора Java для написания игр является возможность перевода Java - проектов в т.н. jar - файлы. JAR файл - это Java - архив (сокращение от англ. Java ARchive). Представляет собой обычный ZIP-архив, в котором содержится часть программы на языке Java. Jar файлы весьма удобны, т.к. их можно запустить абсолютно на любой ОС, на которой установлена JVM. Еще одно удобство jar - файла в том, что сложный проект, с глубокой иерархией, можно несколькими несложными действиями перевести во всего лишь один jar - файл, который можно будет свободно запускать.

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

Инди игры - это игры, которые были созданы независимыми разработчиками. Обычно такие игры отличаются оригинальной концепцией и неповторимым геймплеем. На сегодняшний день, популярность инди игр стремительно растет. Попробовать свои силы в разработке инди игры, может каждый. Обычно для таких целей выбирается либо язык C++, либо Java, т.к. именно на этих языках было написано большинство инди игр и они отлично себя зарекомендовали в данной сфере.

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



. Начало работы с Java


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


.1 Java Runtime Environment


«Java Runtime Environment» - минимальная реализация виртуальной машины, необходимая для исполнения Java - приложений, без компилятора и других средств разработки. Состоит из виртуальной машины - «Java Virtual Machine» и библиотеки Java - классов. JRE распространяется свободно и для большинства платформ может быть загружена с сайта Oracle.

При установке JRE, у нас появится возможность простого запуска приложений, написанных на Java, без возможности разработки. На данный момент, самые актуальная версия JRE - это JRE 7. Скачать JRE 7 можно по ссылке #"justify">На странице можно найти JRE под множество операционных систем и архитектур (рисунок 1.1).


Рисунок 1.1 - Выбор нужного JRE 7


1.2 Java Development Kit

Development Kit - бесплатно распространяемый компанией Oracle Corporation (ранее Sun Microsystems) комплект разработчика приложений на языке Java, включающий в себя компилятор Java (Javac), стандартные библиотеки классов Java, примеры, различные утилиты и исполнительную систему Java (JRE). Для разработки необязательно качать JRE отдельно - достаточно будет JDK.

Самую последнюю версию JDK можно скачать по ссылке #"justify">

Рисунок 1.2 - Выбор нужного JDK 7


.3 Документация Java API


Совершенно невозможно запомнить всю информацию, которая может понадобиться при написании программ. Например, даже стандартная библиотека Java содержит тысячи классов, содержащих огромное количество методов. Следовательно, очень важно уметь пользоваться интерактивной справочной системой, содержащей документацию об API, и находить нужные классы и методы. Документация является составной частью набора инструментальных средств JDK. Она представлена в формате HTML. Если перейти в браузере по ссылке #"justify">Окно браузера разделено на три фрейма. В небольшом фрейме в верхнем левом углу отображаются имена всех доступных пакетов. Под ним во фрейме побольше перечислены все классы. (рисунок 1.3). Если щелкнуть кнопкой мыши на любом из имен классов, то информация об этом классе будет показана в большом фрейме, расположенном справа (рисунок 1.4).


Рисунок 1.3 - Окно с документацией по API


Рисунок 1.5 - Перечень методов класса


Для того, чтобы скачать документацию Java API, можно перейти по ссылке #"justify">. Среда программирования Java


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

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


.1 Компиляция исходного кода через командную строку


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

Ниже представлена последовательность действий:

. Сохраняем наш исходный код в формате *.java (рисунок 2.1).

. Запускаем командную строку и входим в папку с исходным Java - кодом (рисунок 2.2).

. При помощи команды Javac, компилируем исходный Java - код в байт - код (рисунок 2.3).

. Запускаем байт код при помощи команды Java (рисунок 2.4).


Рисунок 2.1 - Сохранение исходного кода


Рисунок 2.2 - Путь до папки в командной строке


Рисунок 2.3 - Компиляция в байт - код


Рисунок 2.4 - Запуск байт - кода


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


.2 Java IDE


Компилировать Java код из командной строки может показаться обременительным занятием, но, тем не менее, это важнейшее умение. Выполняя базовые шаги работы с JDK самостоятельно, можно получить лучшее представление о том, как работает среда разработки. Чаще всего, крайне рекомендуется перед тем, как устанавливать какое - либо IDE (integrated development environment), научиться работать с Java JDK через командную строку.

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

За последнее время такие среды стали настолько мощны и удобны, что теперь просто нет особого смысла обходиться без них.Самые распространенные IDE для Java на сегодняшний день - это : Eclipse, NetBeans и IDEA. У каждой из данных сред д есть свои преимущества и свои недостатки. Лично я остановился на IDE Eclipse по некоторым причинам. Во-первых, у данной среды весьма удобные горячие клавиши. Под нее в свободном доступе находится огромное количество инструментов для разработчика. Даже такая крупная корпорация, как Google лично написала для Eclipse немало инструментария. При разработке ,например, под ОС Android, лучшую IDE найти сложно - для Eclipse в свободном доступе находится весьма мощный Android SDK, на котором было разработано не одно поколение Android приложений.

Для того, чтобы скачать данную IDE, стоит перейти по ссылке #"justify">

Рисунок 2.5 - Предлагаемые решений Eclipse


Всего предлагается около двенадцати решений для разработчиков различных направленностей. Как видим, выбор достаточно велик. Для своей задачи, я выбрал стандартный пакет Eclipse Standart. Далее выбираем нужную операционную систему с архитектурой (рисунок 2.6) и начинается бесплатное скачивание данной среды.


Рисунок 2.6 - Выбор нужной ОС и архитектуры


. Основные моменты создания игрового 2d - приложения


Краеугольным камнем любого игрового приложения является анимация. Анимация - это иллюзия движения слоев на экране, путем быстрой смены последовательности изображений. Все движения, действия, физика персонажей - это специальным образом запрограммированная быстрая смена изображений. Благодаря высокой вычислительной мощности компьютера, будет создаваться иллюзия прыжков, ходьбы, атак и т.д. Существует множество аспектов при «правильном» программирований 2d графики, основные из которых я затрону ниже.


.1 Анимация при помощи таймера


При создании анимации на Java SE, существует 2 основных приема для смены изображений.

Самый распространенный - это использование Swing таймера. Это самый простой, но менее эффективный способ для создания Java игр. Для его реализации, наш класс обязан расширять интерфейс Action Listener и при этом реализовывать метод данного интерфейса - Action Performed. Данный метод вызывается всякий раз, когда происходит некоторое действие. Правда, не всегда необходимо расширять Action Listener. Чаще всего, просто используются вложенные классы.

Сам таймер имеет вид: Timer ( int interval, ActionListener listener ).

Данный вызов создает таймер, передающий сообщение объекту listener. Сообщение передается по истечении интервала времени, продолжительность которого задается параметром interval.

Метод start() запускает таймер, который запускает метод actionPerformed() его слушателей.

Метод stop() останавливает таймер. После остановки таймера, метод actionPerformed() слушателей больше не вызывается.

.2 Анимация при помощи потоков


Самый эффективный способ создания анимации - это использование потоков. В Java поток представлен классом Thread (полное имя Java.lang.Thread), все потоки, в конечном счете наследуются от Thread. Есть два подхода к созданию своего потока:

унаследовать Thread;

реализовать Runnable (полное имя Java.lang.Runnable).

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

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

У класса Thread есть много полезных методов и приёмов, построенных на их применении. Большинство этих методов статические, то есть можно использовать их, не имея ссылки на объект класса Thread, что особенно удобно, если используется реализация Runnable вместо Thread.

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

Важно упомянуть о том, как же нормально остановить поток. Если необходимо остановить выполнение потока, то для этого есть два варианта:

нужно просто остановить;

нужно остановить и убедиться, что поток больше не работает.

Чтобы остановить, нужно иметь в потоке контрольные точки. Например, если это итерационный процесс, можно разместить контрольную точку в условие цикла. Чтобы дождаться завершения потока нужно вызвать метод join( ) от экземпляра потока и ждать пока этот метод будет пройден.


.3 Frame Per Second при использовании потоков


Самый легкий путь использования потоков при создании Java - игры - это в бесконечном цикле организовать обновление и перерисовку различных событий. Такой способ имеет множество недостатков. Самый существенный - это использование слишком больших объемов памяти. Чтобы разумно использовать память при работе с потоками, в играх используется т.н. кадровая частота (FPS) - количество сменяемых кадров за единицу времени на мониторе. Минимальная кадровая частота для создания ощущения плавности движения составляет 12-18 кадров в секунду. FPS рассчитывается следующим образом:

. Заводим заранее 2 переменные: базовый FPS и FPS для понимания его потоком. Второй вычисляется, как 1000 / FPS, это делается исключительно из-за того, что основное разряд времени для работы с потоками - 1 миллисекунда

. Когда поток входит в цикл, фиксируем время его входа (startTime).

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

. Нужная нам величина - переменная wait, хранит оптимальное время, на которое нужно временно остановить поток (ввести в сон). Оно вычисляется, как разность между поточной FPS и временем, затраченным для выполнения потоком отрисовки. Именно на эту величину можно останавливать поток, не опасаясь, потери памяти и подвисаний игры.

Пример:


private int FPS = 100;long targetTime = 1000 / FPS; (running) {= System.nanoTime();();();= System.nanoTime() - start;= targetTime - elapsed / 1000000;(wait < 0)= 5;{.sleep(wait);

} catch (Exception e) {.printStackTrace();

}

}


.4 Создание фрейма, вставка контейнера


Окно верхнего уровня (т.е. окно, не содержащееся внутри другого окна) в языке Java называется фреймом (frame). В библиотеке AWT для такого окна предусмотрен класс Frame. В библиотеке Swing аналогом этого класса является JFrame. Классрасширяет класс Frame и представляет собой один из немногих компонентов в библиотеке Swing, которые не отображаются на холсте (canvas).

По умолчанию фрейм имеет совершенно бесполезный размер - 0x0 пикселей, поэтому устанавливаем размер вручную методом setSize(int width, int height). И еще один важный момент - это определяем, что должно произойти, если пользователь закроет фрейм.

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

frame. setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE)

Определяем вручную, т.к. по умолчанию ничего не определено.

В самом конце обязательно делаем окно видимым (true), иначе результата никакого не увидим : (boolean vis);

Окно создано, но отображать оно ничего не будет.

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

Само добавление контейнера в наш фрейм, происходит с помощью метода setContentPane(contentPane obj)


.5 Методы update() и draw()


Данные два метода незаменимы при разработке игровых приложений. Поток постоянно вызывает эти методы для «чистоты» картинки. Если первоначально не согласовать порядок отрисовки, то на экране будут появляться графические аномалии, или события будут происходить не в своей очередности. Именно эти проблемы и предотвращают методы update и draw. Update никогда не взаимодействует напрямую с методами отрисовки нашего окна. Update мгновенно производит расчеты по всем изменениям, которые произошли в нашей игре. Уже после этого, за дело берется метод draw, который проходит по всем дочерним методам draw в различных игровых разделах и уже там взаимодействует напрямую с методом объекта Graphics - drawImage. Поток, в зависимости от заданного FPS, постоянно выполняет эти два метода, тем самым «обновляя» полностью все приложение. Здесь ключевым моментом является очередность. Нельзя размещать draw перед update, т.к. на экране тем самым окажется старый игровой контекст.


.6 Game State Manager

- абстрактная структура, которая просто незаменима в игростроении. Именно она дает возможность размещать методы update и draw во всех разделах игры. Центральное место ее приходится на класс GameStateManager, у которого два ключевых поля - целочисленная переменная currentState и одномерный массив gameStates абстрактного класса GameState, который содержит абстрактные методы draw, update, init, keyPressed, keyReleased. В массиве gameStates содержатся объекты текущего состояния игры (Меню, Уровень1, Настройки и т.д.). currentState - идентификатор, указывающий на то, какой именно режим игры сейчас активен. Поток постоянно обновляет методы update и draw объекта GameStateManager, в которых, в свою очередь, обновляются эти же методы, только уже текущего режима из массива gameStates, вызываясь уже из самого этого объекта. Т.е. объект GameStateManager никогда напрямую не взаимодействует с режимами игры, а благодаря массиву gameStates, можно не беспокоиться, что активный объект режим сам своевременно не обновит себя, или не отрисует нужную информацию (рисунок 3.1).



Рисунок 3.1 - Схема GSM


.7 События кнопок


Как и с update и draw, события кнопок передаются через объект GameStateManager. Само событие - это keyEvent. Оно же и будет передаваться через GameStateManager в нужный раздел, где и будет обрабатываться, в зависимости от контекста. Пример определения нажатой клавиши :


public void keyPressed(keyEvent key) { ( key == VK_ENTER )

System.out.printl(The enter was pressed);

}


Для слушания событий, класс должен реализовывать интерфейс KeyListener, переопределяя мутоды keyPressed (keyEvent) ( клавиша нажата) и keyReleased(keyEvent) (клавиша отпущена). keyEvent - события клавиш при нажатии и отпускании клавиши, соответственно (рисунок 3.2).


Рисунок 3.2 - Работа с клавишами в GSM



. Графические примитивы


Графику в Java обслуживают классы Graphics и Graphics2D. Работа с графикой осуществляется в графическом контексте элементов, унаследованных от класса Component. Понимать это можно так: на элементах управления, например, JFrame, JPanel, JButton и других, есть возможность рисовать. Такие элементы обладают графическим контекстом, в этом контексте мы и рисуем. Всё, что нарисовано в контексте, будет показано на элементе. Классы Graphics и Graphics2D необходимы для работы с графическим контекстом. Мы должны получить экземпляр такого класса и, используя его методы, рисовать. Получить экземпляр контекста можно в методе paint:

public void paint(Graphics g);

Данный метод наследуется из класса Component. Аргумент Graphics g создаётся системой, а мы берём его в готовом виде и используем для рисования. При создании элемента метод paint будет вызван автоматически.\


.1 Прямая линия


Метод drawLine класса Graphics начертит прямую линию:

g.drawLine(x1, y1, x2, y2);

Здесь x1 и y2 - это координаты x и y начала линии, x2 и y2 - координаты конца линии.


.2 Цвет


Метод setColor класса Graphics сделает текущим новый цвет:

Аргументы конструктора new Color(0, 0, 255) - это красный, зелёный и синий цвета соответственно (rgb). Как задать rgb цвета? В примере задан чисто синий цвет, т.к. значения других составляющих равны нулю. Вот красный и зеленый цвета:


Color newColor = new Color(255, 0, 0);newColor = new Color(0, 255, 0);


4.3 Цвет фона


Задать цвет фона можно методом setBackground:.setBackground(Color.white);


.4 Прямоугольник


Нарисовать прямоугольник можно методом drawRect класса Graphics, где x1, y1 - это координаты верхнего левого угла прямоугольника;, y2 - высота прямоугольника:


g.drawRect(x1, y1, x2, y2);


4.5 Овал


Методом drawOval класса Graphics рисуется овал:

.drawOval(20, 110, 150, 60);


Аргументы определяют прямоугольник, в который вписан овал.



4.6 Многоугольник


Методом drawPolygon класса Graphics:


int[] arrayX = {20, 100, 100, 250, 250, 20, 20, 50};[] arrayY = {180, 180, 200, 200, 220, 200, 200, 190};poly = new Polygon(arrayX, arrayY, 8);

g.drawPolygon(poly);


Здесь создаём объект класса Polygon. arrayX - это х-координаты вершин многоугольника, arrayY - это y-координаты вершин многоугольника, 8 - число вершин многоугольника.


.7 Объект точки


Для этого используем класс Point:


Point aPoint = new Point(50, 190);


аргументы - это x, y координаты.


.8 Изображение


Для того, чтобы добавить изображение, нам необходим класс Graphics2D. Непосредственно создать объект класса Graphics2D не получится, поскольку графический контекст сильно зависит от конкретной графической платформы, этот класс сделан абстрактным. Самый очевидный выход - это явное приведение от Graphics:


Graphics2D g2 = (Graphics2D) g;


У объекта Graphics2D имеется очень полезный метод - drawImage(), который, собственно, и рисует изображение на экран. К примеру:

g2.drawImage( image, 0, 0, width, height, null);



Заключение


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

В ходе нажатии пользователем определенных клавиш, игровой персонаж совершает соответствующие действия: ходьба, прыжок, полет, удар рукой, стрельба. Уровни создавались в текстовом редакторе, при помощи специального редактора. Персонаж не может выйти за пределы уровня, контактирую со стенами, потолком и полом. В качестве ресурсов использовались .gif, .jpg и .png файлы. Также файл уровней .map, который представляет собой числовую последовательность , каждая цифра которого «символически» обозначает некоторый участок картинки из файла titles.

Игровой платформер состоит из нескольких пакетов: GameState, Entity, Main, TileMap. GameState - соответствующие режимы игры. В Entity находятся классы для персонажей игры и их доступные действия. Из пакета Main начинается запуск игры, идет полная настройка фрейма с добавлением к нему панели. Именно отсюда берут свое начало потоки. В пакете TileMap идет загрузка карты, ее прорисовка и работа с фоном.

Данное приложение можно использовать на абсолютно любых desktop - устройствах, на которых установлена JVM. Запуск идет из jar файла. В дальнейшем планируется перевод проекта в веб и на ОС Android.

игровое приложение java компиляция


Список использованных источников


Andrew Davison, Killer Game Programming in Java - «O'Reilly Media», Май 2005, - 998 c.

Java2. Библиотека профессионала Том 1. Основы, 8 - е издание - «Sun microsystems», 2010 - 820 c.

Эккель, Б. Философия Java. / Б. Эккель. - СПб. : Питер, 2001. - 880 с.

Шилдт, Г. Искусство программирования на JAVA / Г. Шилдт, Дж. Холмс. - М. : Вильямс, 2005. - 331 с.



Приложение A


Описание класса Game пакета Main

package Main;

import javax.swing.JFrame;class Game {static void main(String[] args) {window = new JFrame("Game");.setContentPane(new GamePanel());.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);.setResizable(false);.pack();.setVisible(true);

}

}


Приложение Б


Описание класса GamePanel пакета MainMain;java.awt.*;java.awt.image.BufferedImage;java.awt.event.*;javax.swing.JPanel;GameState.GameStateManager;

@SuppressWarnings("serial")class GamePanel extends JPanel implements Runnable, KeyListener {

// размерыstatic final int WIDTH = 800;static final int HEIGHT = 600;static final int SCALE = 2;

// потокThread thread;boolean running;int FPS = 100;long targetTime = 1000 / FPS;

// изображениеBufferedImage image;Graphics2D g;

// game state managerGameStateManager gsm;GamePanel() {();(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));(true);();

}void addNotify() {.addNotify();(thread == null) {= new Thread(this);(this);.start();

}

}void init() {= new BufferedImage(WIDTH, HEIGHT, .TYPE_INT_RGB);= (Graphics2D) image.getGraphics();= true;= new GameStateManager();

}void run() {();start;elapsed;wait;

// game loop(running) {= System.nanoTime();();();();= System.nanoTime() - start;= targetTime - elapsed / 1000000;(wait < 0)= 5;{.sleep(wait);

} catch (Exception e) {.printStackTrace();

}

}

}void update() {.update();

}void draw() {.draw(g);

}

void drawToScreen() {g2 = getGraphics();.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);.dispose();

}void keyTyped(KeyEvent key) {

}void keyPressed(KeyEvent key) {.keyPressed(key.getKeyCode());

}void keyReleased(KeyEvent key) {.keyReleased(key.getKeyCode());

}

}

Приложение В


Описание класса GameState пакета GameStateGameState;abstract class GameState {GameStateManager gsm;abstract void init();abstract void update();abstract void draw(Java.awt.Graphics2D g);abstract void keyPressed(int k);abstract void keyReleased(int k);

}


Приложение Г


Описание класса GameStateManager пакета GameState

package GameState;java.util.ArrayList;class GameStateManager {GameState[] gameStates;int currentState;static final int NUMGAMESTATES = 2;static final int MENUSTATE = 0;static final int LEVEL1STATE = 1;GameStateManager() {= new GameState[NUMGAMESTATES];= MENUSTATE;(currentState);

}void loadState(int state) {(state == MENUSTATE)[state] = new MenuState(this);(state == LEVEL1STATE)[state] = new Level1State(this);

}void unloadState(int state) {[state] = null;

}void setState(int state) {(currentState);= state;(currentState);

//gameStates[currentState].init();

}void update() {{[currentState].update();

} catch(Exception e) {}

}void draw(Java.awt.Graphics2D g) {{[currentState].draw(g);

} catch(Exception e) {}

}void keyPressed(int k) {[currentState].keyPressed(k);

}void keyReleased(int k) {[currentState].keyReleased(k);

}

}



Приложение Д


Описание класса Level1State пакета GameStateGameState;Main.GamePanel;TileMap.*;Entity.*;java.awt.*;java.awt.event.KeyEvent;java.util.ArrayList;class Level1State extends GameState {TileMap tileMap;Background bg;Player player;ArrayList<Explosion> explosions;HUD hud;Level1State(GameStateManager gsm) {.gsm = gsm;();

}void init() {= new TileMap(30);.loadTiles("/Tilesets/grasstileset2.gif");.loadMap("/Maps/level1.map");.setPosition(0, 0);.setTween(1);= new Background("/Backgrounds/back.gif", 0.1);= new Player(tileMap);.setPosition(100, 100);= new ArrayList<Explosion>();= new HUD(player);

}void update() {

// обновление персонажа.update();.setPosition(.WIDTH / 2 - player.getx(),.HEIGHT / 2 - player.gety()

);

// фон.setPosition(tileMap.getx(), tileMap.gety());

// обновление взрывов(int i = 0; i < explosions.size(); i++) {.get(i).update();(explosions.get(i).shouldRemove()) {.remove(i);-;

}

}

}void draw(Graphics2D g) {

// нарисовать фон.draw(g);

// нарисовать карту.draw(g);

// нарисовать персонажа.draw(g);

// нарисовать взрыв(int i = 0; i < explosions.size(); i++) {.get(i).setMapPosition(

(int)tileMap.getx(), (int)tileMap.gety());.get(i).draw(g);

}

//нарисовать панель здоровья.draw(g);

}void keyPressed(int k) {(k == KeyEvent.VK_LEFT) player.setLeft(true);(k == KeyEvent.VK_RIGHT) player.setRight(true);(k == KeyEvent.VK_UP) player.setUp(true);(k == KeyEvent.VK_DOWN) player.setDown(true);(k == KeyEvent.VK_W) player.setJumping(true);(k == KeyEvent.VK_E) player.setGliding(true);(k == KeyEvent.VK_R) player.setScratching();(k == KeyEvent.VK_F) player.setFiring();

}void keyReleased(int k) {(k == KeyEvent.VK_LEFT) player.setLeft(false);(k == KeyEvent.VK_RIGHT) player.setRight(false);(k == KeyEvent.VK_UP) player.setUp(false);(k == KeyEvent.VK_DOWN) player.setDown(false);(k == KeyEvent.VK_W) player.setJumping(false);(k == KeyEvent.VK_E) player.setGliding(false);

}

}



Приложение Е


Описание класса MenuState пакета GameState

package GameState;TileMap.Background;java.awt.*;java.awt.event.KeyEvent;class MenuState extends GameState {Background bg;int currentChoice = 0;String[] options = { "Start", "Help", "Quit" };Color titleColor;Font titleFont;Font font;MenuState(GameStateManager gsm) {.gsm = gsm;{= new Background("/Backgrounds/back.jpg", 1);.setVector(-0.2, 0);= new Color(128, 0, 0);= new Font("Charlemagne Std", Font.PLAIN, 28);= new Font("Charlemagne Std", Font.PLAIN, 12);

} catch (Exception e) {.printStackTrace();

}

}void init() {

}void update() {.update();

}void draw(Graphics2D g) {.draw(g);.setColor(titleColor);.setFont(titleFont);.drawString("Student dragon", 200, 90);.setFont(font);(int i = 0; i < options.length; i++) {(i == currentChoice) {.setColor(Color.BLACK);

} else {.setColor(Color.RED);

}.drawString(options[i], 324, 140 + (int) (i * 15 * 1.2));

}

}void select() {(currentChoice == 0) {.setState(GameStateManager.LEVEL1STATE);

}(currentChoice == 1) {

// help

}(currentChoice == 2) {.exit(0);

}

}void keyPressed(int k) {(k == KeyEvent.VK_ENTER) {();

}(k == KeyEvent.VK_UP) {-;(currentChoice == -1) {= options.length - 1;

}

}(k == KeyEvent.VK_DOWN) {++;(currentChoice == options.length) {= 0;

}

}

}void keyReleased(int k) {

}

}



Приложение Ж


Описание класса Background пакета TileMap

package TileMap;Main.GamePanel;java.awt.*;java.awt.image.*;javax.imageio.ImageIO;class Background {BufferedImage image;double x;double y;double dx;double dy;double moveScale;Background(String s, double ms) {{= ImageIO.read(().getResourceAsStream(s)

);= ms;

}(Exception e) {.printStackTrace();

}

}void setPosition(double x, double y) {.x = (x * moveScale) % GamePanel.WIDTH;.y = (y * moveScale) % GamePanel.HEIGHT;

}void setVector(double dx, double dy) {.dx = dx;.dy = dy;

}void update() {+= dx;+= dy;

}void draw(Graphics2D g) {.drawImage(image, (int)x, (int)y, null);(x < 0) {.drawImage(,

(int)x + GamePanel.WIDTH,

(int)y,

);

}(x > 0) {.drawImage(,

(int)x - GamePanel.WIDTH,

(int)y,

);

}(x <= -GamePanel.WIDTH) {+= GamePanel.WIDTH;

}}}


Приложение З


Описание класса Tile пакета TileMapjava.awt.image.BufferedImage;class Tile {BufferedImage image;int type;

// типы тайловstatic final int NORMAL = 0;static final int BLOCKED = 1;Tile(BufferedImage image, int type) {.image = image;.type = type;

}BufferedImage getImage() { return image; }int getType() { return type; }

}



Приложение И


Описание класса TileMap пакета TileMap

import java.awt.*;java.awt.image.*;java.io.*;javax.imageio.ImageIO;Main.GamePanel;class TileMap {

// позицияdouble x;double y;

// границыint xmin;int ymin;int xmax;int ymax;double tween;

// картаint[][] map;int tileSize;int numRows;int numCols;int width;int height;

// тайлыBufferedImage tileset;int numTilesAcross;Tile[][] tiles;

// рисованияint rowOffset;int colOffset;int numRowsToDraw;int numColsToDraw;TileMap(int tileSize) {.tileSize = tileSize;= GamePanel.HEIGHT / tileSize + 2;= GamePanel.WIDTH / tileSize + 2;= 0.07;

}void loadTiles(String s) {{= ImageIO.read(getClass().getResourceAsStream(s));= tileset.getWidth() / tileSize;= new Tile[2][numTilesAcross];subimage;(int col = 0; col < numTilesAcross; col++) {= tileset.getSubimage(col * tileSize, 0, tileSize, tileSize);[0][col] = new Tile(subimage, Tile.NORMAL);= tileset.getSubimage(col * tileSize, , tileSize, tileSize);[1][col] = new Tile(subimage, Tile.BLOCKED);

}

} catch (Exception e) {.printStackTrace();

}


}void loadMap(String s) {

{in = getClass().getResourceAsStream(s);br = new BufferedReader(InputStreamReader(in)

);= Integer.parseInt(br.readLine());= Integer.parseInt(br.readLine());= new int[numRows][numCols];= numCols * tileSize;= numRows * tileSize;

= GamePanel.WIDTH - width - 100;= 0;= GamePanel.HEIGHT - height;//here= 0;delims = "\\s+";(int row = 0; row < numRows; row++) {line = br.readLine();[] tokens = line.split(delims);(int col = 0; col < numCols; col++) {[row][col] = Integer.parseInt(tokens[col]);

}

}

} catch (Exception e) {.printStackTrace();

}

}int getTileSize() {tileSize;

}double getx() {x;

}double gety() {y;

}int getWidth() {width;

}int getHeight() {height;

}int getType(int row, int col) {rc = map[row][col];r = rc / numTilesAcross;c = rc % numTilesAcross;tiles[r][c].getType();

}void setTween(double d) {= d;

}void setPosition(double x, double y) {.x += (x - this.x) * tween;.y += (y - this.y) * tween;();= (int) -this.x / tileSize;= (int) -this.y / tileSize;

}void fixBounds() {(x < xmin)= xmin;(y < ymin)= ymin;(x > xmax)= xmax;(y > ymax)= ymax;

}void draw(Graphics2D g) {(int row = rowOffset; row < rowOffset + numRowsToDraw; row++) {(row >= numRows);(int col = colOffset; col < colOffset +; col++)

{(col >= numCols);(map[row][col] == 0);rc = map[row][col];r = rc / numTilesAcross;c = rc % numTilesAcross;.drawImage(tiles[r][c].getImage(),

(int) x + col * tileSize,

(int) y + row * tileSize, null);

}

}


}

}

Приложение К


Описание класса Animation пакета Entity

package Entity;java.awt.image.BufferedImage;class Animation {BufferedImage[] frames;int currentFrame;long startTime;long delay;boolean playedOnce;Animation() {= false;

}void setFrames(BufferedImage[] frames) {.frames = frames;= 0;= System.nanoTime();= false;

}void setDelay(long d) {= d;

}void setFrame(int i) {= i;

}void update() {(delay == -1);elapsed = (System.nanoTime() - startTime) / 1000000;(elapsed > delay) {++;= System.nanoTime();

}(currentFrame == frames.length) {= 0;= true;

}

}int getFrame() {currentFrame;

}BufferedImage getImage() {frames[currentFrame];

}boolean hasPlayedOnce() {playedOnce;

}

}



Приложение Л


Описание класса Explosion пакета EntityEntity;java.awt.Graphics2D;java.awt.image.BufferedImage;javax.imageio.ImageIO;class Explosion {int x;int y;int xmap;int ymap;int width;int height;Animation animation;BufferedImage[] sprites;boolean remove;Explosion(int x, int y) {.x = x;.y = y;= 30;= 30;{spritesheet = ImageIO.read(().getResourceAsStream(

"/Sprites/Enemies/explosion.gif"

)

);= new BufferedImage[6];(int i = 0; i < sprites.length; i++) {[i] = spritesheet.getSubimage(* width,

,,

);

}

}(Exception e) {.printStackTrace();

}= new Animation();.setFrames(sprites);.setDelay(70);

}void update() {.update();(animation.hasPlayedOnce()) {= true;

}

}boolean shouldRemove() { return remove; }void setMapPosition(int x, int y) {= x;= y;

}void draw(Graphics2D g) {.drawImage(.getImage(),+ xmap - width / 2,+ ymap - height / 2,

);

}

}


Приложение М


Описание класса FireBall пакета EntityEntity;Main.GamePanel;TileMap.TileMap;java.awt.*;java.awt.image.BufferedImage;javax.imageio.ImageIO;class FireBall extends MapObject {boolean hit;boolean remove;BufferedImage[] sprites;BufferedImage[] hitSprites;FireBall(TileMap tm, boolean right) {(tm);= right;= 3.8;(right) dx = moveSpeed;dx = -moveSpeed;= 30;= 30;= 14;= 14;

// load sprites{spritesheet = ImageIO.read(().getResourceAsStream(

"/Sprites/Player/fireball.gif"

)

);= new BufferedImage[4];(int i = 0; i < sprites.length; i++) {[i] = spritesheet.getSubimage(* width,

,,

);

}= new BufferedImage[3];(int i = 0; i < hitSprites.length; i++) {[i] = spritesheet.getSubimage(* width,,,

);

}= new Animation();.setFrames(sprites);.setDelay(70);

}(Exception e) {.printStackTrace();

}

}void setHit() {(hit) return;= true;.setFrames(hitSprites);.setDelay(70);= 0;

}boolean shouldRemove() { remove;

}void update() {();(xtemp, ytemp);(dx == 0 && !hit) {();

}.update();(hit && animation.hasPlayedOnce()) {= true;

}


}void draw(Graphics2D g) {();.draw(g);

}

}



Приложение Н


Описание класса HUD пакета Entity

package Entity;

import java.awt.*;java.awt.image.BufferedImage;javax.imageio.ImageIO;class HUD {Player player;BufferedImage image;Font font;HUD(Player p) {= p;{= ImageIO.read(().getResourceAsStream(

"/HUD/hud.gif"

)

);= new Font("Arial", Font.PLAIN, 14);

}(Exception e) {.printStackTrace();

}

}void draw(Graphics2D g) {.drawImage(image, 0, 10, null);.setFont(font);.setColor(Color.WHITE);.drawString(.getHealth() + "/" + player.getMaxHealth(),

,


);.drawString(.getFire() / 100 + "/" + player.getMaxFire() / 100,

,


);

}

}



Приложение О


Описание класса MapObject пакета Entity

package Entity;

import Main.GamePanel;TileMap.TileMap;TileMap.Tile;java.awt.Rectangle;abstract class MapObject {TileMap tileMap;int tileSize;double xmap;double ymap;

// позицияdouble x;double y;double dx;double dy;

// измерениеint width;int height;

// коллизияint cwidth;int cheight;

// еще коллизияint currRow;int currCol;double xdest;double ydest;double xtemp;double ytemp;boolean topLeft;boolean topRight;boolean bottomLeft;boolean bottomRight;

// анимацияAnimation animation;int currentAction;int previousAction;boolean facingRight;

// движениеboolean left;boolean right;boolean up;boolean down;boolean jumping;boolean falling;

// свойства движенияdouble moveSpeed;double maxSpeed;double stopSpeed;double fallSpeed;double maxFallSpeed;double jumpStart;double stopJumpSpeed;MapObject(TileMap tm) {= tm;= tm.getTileSize();

}boolean intersects(MapObject o) {r1 = getRectangle();r2 = o.getRectangle();r1.intersects(r2);

}Rectangle getRectangle() {new Rectangle(

(int)x - cwidth,

(int)y - cheight,,

);

}void calculateCorners(double x, double y) {leftTile = (int)(x - cwidth / 2) / tileSize;rightTile = (int)(x + cwidth /2 - 1) / tileSize;topTile = (int)(y - cheight / 2) / tileSize;bottomTile = (int)(y + cheight / 2 - 1) / tileSize;tl = tileMap.getType(topTile, leftTile);tr = tileMap.getType(topTile, rightTile);bl = tileMap.getType(bottomTile, leftTile);br = tileMap.getType(bottomTile, rightTile);= tl == Tile.BLOCKED;= tr == Tile.BLOCKED;= bl == Tile.BLOCKED;= br == Tile.BLOCKED;

}void checkTileMapCollision() {= (int)x / tileSize;= (int)y / tileSize;= x + dx;= y + dy;= x;= y;(x, ydest);(dy < 0) {(topLeft || topRight) {= 0;= currRow * tileSize + cheight / 2;

}{+= dy;

}

}(dy > 0) {(bottomLeft || bottomRight) {= 0;= false;= (currRow + 1) * tileSize - cheight / 2;

}{+= dy;

}

}(xdest, y);(dx < 0) {(topLeft || bottomLeft) {= 0;= currCol * tileSize + cwidth / 2;

}{+= dx;

}

}(dx > 0) {(topRight || bottomRight) {= 0;= (currCol + 1) * tileSize - cwidth / 2;

}{+= dx;

}

}(!falling) {(x, ydest + 1);(!bottomLeft && !bottomRight) {= true;

}

}


}int getx() { return (int)x; }int gety() { return (int)y; }int getWidth() { return width; }int getHeight() { return height; }int getCWidth() { return cwidth; }int getCHeight() { return cheight; }void setPosition(double x, double y) {.x = x;.y = y;

}void setVector(double dx, double dy) {.dx = dx;.dy = dy;

}void setMapPosition() {= tileMap.getx();= tileMap.gety();

}void setLeft(boolean b) { left = b; }void setRight(boolean b) { right = b; }void setUp(boolean b) { up = b; }void setDown(boolean b) { down = b; }void setJumping(boolean b) { jumping = b; }boolean notOnScreen() {x + xmap + width < 0 ||+ xmap - width > GamePanel.WIDTH ||+ ymap + height < 0 ||+ ymap - height > GamePanel.HEIGHT;

}void draw(Java.awt.Graphics2D g) {(facingRight) {.drawImage(.getImage(),

(int)(x + xmap - width / 2),

(int)(y + ymap - height / 2),

);

}{.drawImage(.getImage(),

(int)(x + xmap - width / 2 + width),

(int)(y + ymap - height / 2),

width,,

);

}

}

}



Приложение П


Описание класса Player пакета EntityEntity;TileMap.*;java.util.ArrayList;javax.imageio.ImageIO;java.awt.*;java.awt.image.BufferedImage;java.util.HashMap;class Player extends MapObject {

// действия игрокаint health;int maxHealth;int fire;int maxFire;boolean dead;boolean flinching;long flinchTimer;

// стрельбаboolean firing;int fireCost;int fireBallDamage;ArrayList<FireBall> fireBalls;

// удар рукойboolean scratching;int scratchDamage;int scratchRange;

// полетboolean gliding;

// анимацияArrayList<BufferedImage[]> sprites;final int[] numFrames = {

, 8, 1, 2, 4, 2, 5

};

// id анимацииstatic final int IDLE = 0;static final int WALKING = 1;static final int JUMPING = 2;static final int FALLING = 3;static final int GLIDING = 4;static final int FIREBALL = 5;static final int SCRATCHING = 6;Player(TileMap tm) {(tm);= 30;= 30;= 30;= 30;= 0.3;= 1.6;= 0.4;= 0.15;= 4.0;= -4.8;= 0.3;= true;= maxHealth = 5;= maxFire = 2500;= 200;= 5;= new ArrayList<FireBall>();= 8;= 40;

// загрузка спрайтов{spritesheet = ImageIO.read(().getResourceAsStream(

"/Sprites/Player/playersprites.gif"

)

);= new ArrayList<BufferedImage[]>();(int i = 0; i < 7; i++) {[] bi =BufferedImage[numFrames[i]];(int j = 0; j < numFrames[i]; j++) {

(i != SCRATCHING) {[j] = spritesheet.getSubimage(* width,* height,,

);

}{[j] = spritesheet.getSubimage(* width * 2,* height,* 2,

);

}

}.add(bi);

}

}(Exception e) {.printStackTrace();

}= new Animation();= IDLE;.setFrames(sprites.get(IDLE));.setDelay(400);

}int getHealth() { return health; }int getMaxHealth() { return maxHealth; }int getFire() { return fire; }int getMaxFire() { return maxFire; }void setFiring() { = true;

}void setScratching() {= true;

}void setGliding(boolean b) { = b;

}void hit(int damage) {(flinching) return;-= damage;(health < 0) health = 0;(health == 0) dead = true;= true;= System.nanoTime();

}void getNextPosition() {

// движение(left) {-= moveSpeed;(dx < -maxSpeed) {= -maxSpeed;

}

}if(right) {+= moveSpeed;(dx > maxSpeed) {= maxSpeed;

}

}{(dx > 0) {-= stopSpeed;(dx < 0) {= 0;

}

}if(dx < 0) {+= stopSpeed;

if(dx > 0) {= 0;

}

}

}

// во время удара запрет движение

if(

(currentAction == SCRATCHING || currentAction == FIREBALL) &&

!(jumping || falling)) {= 0;

}

// прыжок(jumping && !falling) {= jumpStart;= true;

}

// падение(falling) {(dy > 0 && gliding) dy += fallSpeed * 0.1;dy += fallSpeed;(dy > 0) jumping = false;(dy < 0 && !jumping) dy += stopJumpSpeed;(dy > maxFallSpeed) dy = maxFallSpeed;

}

}void update() {

// обновление позиции();();(xtemp, ytemp);

// проверка остановки атаки(currentAction == SCRATCHING) {(animation.hasPlayedOnce()) scratching = false;

}(currentAction == FIREBALL) {(animation.hasPlayedOnce()) firing = false;

}

// стрельба+= 1;(fire > maxFire) fire = maxFire;(firing && currentAction != FIREBALL) {(fire > fireCost) {-= fireCost;fb = new FireBall(tileMap, facingRight);.setPosition(x, y);.add(fb);

}

}

// обновить огонь(int i = 0; i < fireBalls.size(); i++) {.get(i).update();(fireBalls.get(i).shouldRemove()) {.remove(i);-;

}

}(flinching) {elapsed =

(System.nanoTime() - flinchTimer) / 1000000;(elapsed > 1000) {= false;

}

}

// установить анимацию(scratching) {(currentAction != SCRATCHING) {= SCRATCHING;.setFrames(sprites.get(SCRATCHING));.setDelay(50);= 60;

}

}if(firing) {(currentAction != FIREBALL) {= FIREBALL;.setFrames(sprites.get(FIREBALL));.setDelay(100);= 30;

}

}if(dy > 0) {(gliding) {(currentAction != GLIDING) {= GLIDING;.setFrames(sprites.get(GLIDING));.setDelay(100);= 30;

}

}if(currentAction != FALLING) {= FALLING;.setFrames(sprites.get(FALLING));.setDelay(100);= 30;

}

}if(dy < 0) {(currentAction != JUMPING) {= JUMPING;.setFrames(sprites.get(JUMPING));.setDelay(-1);= 30;

}

}if(left || right) {(currentAction != WALKING) {= WALKING;.setFrames(sprites.get(WALKING));.setDelay(40);= 30;

}

}{(currentAction != IDLE) {= IDLE;.setFrames(sprites.get(IDLE));.setDelay(400);= 30;

}

}.update();

// установить направление(currentAction != SCRATCHING && currentAction != FIREBALL) {(right) facingRight = true;(left) facingRight = false;

}

}void draw(Graphics2D g) {();

// отрисовка огня(int i = 0; i < fireBalls.size(); i++) {.get(i).draw(g);

}

// нарисовать игрока(flinching) {elapsed =

(System.nanoTime() - flinchTimer) / 1000000;(elapsed / 100 % 2 == 0) {;

}

}.draw(g);

}

}



Приложение Р


Результат разработанного приложения


Рисунок Р.1 - Персонаж на стоит на месте


Рисунок Р.2 - Прыжок


Рисунок Р.3 - Персонаж летит


Рисунок Р.4 - Стрельба огнем


Рисунок Р.5 - Разрушение огня


Рисунок Р.6 - Удар когтем

Рисунок Р.7 - Невозможность пройти через потолок


Рисунок Р.8 - Окраина уровня


Содержание Введение . Начало работы с Java 1.1 Java Runtime Environment .2 Java development Kit 1.3 Документация Java API . Среда программ

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ