Как сделать онлайн игру на java

Добавил пользователь Владимир З.
Обновлено: 19.09.2024

Любите ли вы играть? А создавать игры? Даже если раньше не пробовали, никогда не поздно начать! Тем более, написать свою собственную игру теперь можно всего за час. А если понравится быть не игроком, а творцом, новое умение можно превратить в полноценную профессию. Как? Сейчас расскажем!

Змейка или Тетрис - какая вам ближе?

IT-портал GeekBrains запустил новый проект - серию вебинаров по созданию несложных игр на языке Java.

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

На вебинарах подробно рассказывается о создании таких игр, как Conway'sGameofLife, Snake, Тетрис, SpaceInvaders, и полностью раскрывается процесс написания кода. Если же что-то не получилось или вам интересно увидеть “официальный” вариант кода, - все файлы для игры можно скачать со страницы с описанием вебинара.

Сейчас для просмотра доступны четыре вебинара, посвященных теплым ламповым играм 80-х годов. То, во что вы самозабвенно рубились когда-то на приставке или Nokia 3310, теперь можете создать сами!

Snake (“змейка”)

“Тетрис”

Space Invaders

Conway

А дальше что?

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

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

Чтобы понять как работают игровые движки и сами игры, давайте попробуем сами написать простой 2D движок.

Во всех играх есть основной игровой цикл, который непрерывно повторяется:

1. Чтение устройств ввода (клава, мышь, джойсткик, таймер)
2. Обновление игровых объектов
3. Отрисовка

И этот цикл повторяется пока игра запущена. FPS (frames per second) - сколько кадров в секунду отрисовал игровой движок или сколько циклов сделал данный цикл.

Для начала создадим класс Game, который будет основным. В нем же будет точка входа (метод main) в программу.

Здесь мы создали один объект класса Game и вызвали метод start(). В этом методе мы должны запустить игровой цикл.

Нам нужно окно для игры и панель, где мы будем рисовать саму игру. Создайте новый класс GameCanvas, который наслуедует от JPanel в новом файле:

Класс GameCanvas хранит при себе ссылку на объект Game, который ему передается при создании. Теперь, в классе Game создаем метод createWindow(), который создаст окно и панель GameCanvas.

Сначала объявляем свойства window и gameCanvas:

Затем создаем метод createWindow() и вызываем его в методе start():

Если сейчас вы запустите класс Game, то у вас будет пустое окно. Идем дальше.

Игровой цикл

Игровой цикл будет у нас движим таймером, который мы запустим в методе startTimer():

Убедитесь что класс Timer импортирован с пакета javax.swing, а не с пакета java.util:

Как вы видите в коде, таймер выполняется через каждые 50 миллисекунд и каждый раз запускает метод tick(). Метод tick() пока пустой, но в нем мы будем обновлять состояние игровых объектов и перерисовавыть экран. Теперь нужно вызвать метод startTimer() в методе start():

Игровые объекты

Любая игра состоит из объектов, с которыми так или иначе взаимодействует игрок и которые как-то отображается на экране. Конечно, есть объекты которые не отображаются, но отвечают за что-то. Эти объекты называются игровыми объектами.

У нас в движке будет основной класс GameObject, который будет иметь основные свойства игрового объекта и от которого будут наследоваться все другие игровые объекты.

Каждый игровой объект должен иметь ссылку на Игру, в которой он сейчас находится. И у каждого объекта есть позиция на экране. Так как у нас движок 2D, то у нас позиция это две координаты x и y. Как принято во всех игровых движках будем использовать класс Vector2, для хранения двух координат.

Создаем новый класс Vector2:

И создаем класс GameObject:

По умолчанию позиция у всех объектов 0,0.

Давайте сразу в класс GameObject добавим два метода, которые потом нам будут нужны:

* Метод draw() - метод будет вызываться, когда нужно отрисовать игровой объект на экран. Каждый тип игрового объекта по своему будет отрисовывать себя.
* Метод update() - метод будет вызываться, когда объекту следует проверить состояние игры, ввод, таймер и обновить свое состояние.

B итоге класс у нас такой:

Теперь переходим в класс Game. В любой игре игровых объектов может быть сколько угодно. Поэтому, нам нужно где-то держать все эти объекты. Будем держать их всех в классе Game, в свойства gameObjects типа Set, так как порядок объектов нам не важен:

Вначале множество объектов пустое. Но при запуске игры и во время игры объекты будут добавляться и удаляться.

Допустим что у нас уже есть много игровых объектов. Нам нужно их при каждом игровом цикле(tick) обновлять и перерисовывать. Давайте так и сделаем. Откроем метод tick() в классе Game:

Здесь мы обходим в цикле все игровые объекты и вызываем у них метод update(), чтобы они обновили свое состояние. Затем мы перерисовываем gameCanvas. Но пока класс GameCanvas у нас ничего не умеет рисовать. Нам нужно сделать так, чтобы GameCanvas умел отрисовывать все игровые объекты.

Откройте класс GameCanvas и в методе paint() для каждого игрового объекта нужно вызовите метод draw():

Корабль

Давайте добавим первый номральный игровой объект. Это будет примитивный корабль, которые будет выглядеть как красный треугольник высотой в 70 пикселей и шириной в 50.

Создайте класс Ship, который наследуется от GameObject:

Так, как он наследуется от GameObject у него есть свойства game и position, которые мы можем использовать для отрисовки корабля. Как видно из кода, мы нарисовали три линии, относительно текущей координаты игрового объекта. Основной точкой корабля мы взяли нижнюю среднюю точку.

Теперь в классе Game нам нужно создать корабль и добавить его в игровые объекты текущей игры. Создаем метод createInitialGameObjects() и вызываем его в методе start():

Если вы сейчас запустите класс Game, то увидите красный треугольник внизу экрана. Это наш корабль.

Давайте добавим возможность двигать кораблем.

Ввод и управление

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

Мы тоже будем хранить множество всех нажатых клавиш в классе Game в свойстве pressedKeys. Множество - потому что одновременно нажатых клавиш может быть несколько. Объвляем:

У каждой клавиши на компе есть свой код типа Integer, мы будем их использовать.

Теперь нам нужно добавить обработчик клавиатуры. Создадим метод initKeyListeners() и возовем его методе start():

Метод keyPressed вызывается когда клавиша зажимается, а метод keyReleased когда клавиша отпускается. Поэтому при зажатии мы добавляем код клавиши в множество, а при отпуске удаляем из множества. Таким образом всегда во множество pressedKeys у нас будут только зажатые в текущий момент клавиши.

Теперь нам нужно двигать кораблем на клавиши влево и вправо. У клавиши " " код 39, будем эти коды использовать, чтобы проверять зажаты ли стрелки.

Откройте класс Ship и переопределите метод update() так:

Как вы видите, если в нажатых клавишах есть код 37, мы меняем позицию корабля по X на -10, а если код 39, то на +10. Т.е. мы перемещаем корабль влево и вправо. Запустите класс Game и попробуйте нажать на стрелки вправо и влево, корабль должен двигаться. Разве не круто?!

Стрельба

Щас будем палить из всех оружий корабля. Давайте сделаем так, чтобы при нажатии на клавишу "Пробел", корабль выпускал пулю? Пуля тоже отдельный игровой объект, так как у него свои логика работы и внешний вид. Поэтому создаем еще один класс наследующий GameObject - класс Shot:

Класс Shot будет представлять пулю корабля. Он унаследовал свойство position от GameObject. В методе draw() мы рисуем небольшой прямоугольник. Так у нас будет выглядеть пуля. А в методе update() мы будем уменьшать позицию объекта по на -10, чтобы пуля поднималась вверх постоянно. Помните когда вызывается метод update() ? При каждом тике, т.е. постоянно через каждые 50 миллисекунд каждая пуля будет подниматься вверх на 10 пикселей.

Теперь нам нужно при нажатии на пробел, создавать новый объект пули и добавлять его и игровые объекты нашей игры. Откройте класс Ship и добавьте в методе update следующий код:

32 - код пробела. Создаем пулю, указываем его позиция выше текущей позиции кораблю. И добавляем в newGameObjects. Это еще одна переменная, которую нужно создать в классе Game:

newGameObjects - это новые объекты, которые нужно добавить в gameObjects при следующем цикле. Обновляем метод tick():

Теперь при нажатии на клавишу "Пробел" корабль создает игровой объект пули. Затем пуля уже сама по себе обновляется и отрисовывается как отдельный игровой объект. Запустите программу и постреляйте.

Текстуры

Текстура - это уже нарисованное изображение, которое накладывается на игровые объекты.

Давайте в конце попробуем вместе треугольника, показывать изображение корабля. Например:


Скачайте эту картинку и скопируйте в корень проекта. Затем откройте класс Ship. Картинку будем хранить в переменной texture типа BufferedImage и в конструкторе класса Ship считаем картинку из файла ship.jpg:

Теперь в методе draw() класса Ship,вместо треугольника будем рисовать эту текстуру:

Запустите игру и посмотрите на ваш красивый корабль!

Задание

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

Каждому из вас нужно ровно 100 раз повторить этот урок, каждый раз измеряя время выполнения. Вы должны уметь его написать закрытыми глазами в самом конце. Записывайте время каждого выполнения по порядку. Потом покажете мне и на следующей паре каждый из вас при мне должен написать эту игру.

Дело в том, что программа на Java исполняется не на прямую процессором компьютера, а виртуальной машиной Java (JVM). Это позволяет абстрагироваться от многих нюансов конкретных платформ. Программу, написанную на Java, можно без изменений кода запускать на Windows, Linux, MacOS и других операционных системах (если, конечно, программа не использует специфичные для ОС функции).

Кто застал начало 2000х, наверное помнит огромное количество мобильных телефонов (тогда еще они не были смартфонами), на каждом телефоне была по сути своя маленькая ОС, но при этом почти на каждом можно было запустить Java игру или приложение.

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

Итак, поехали. Надеюсь как установить java SDK ты уже разобрался. Мы будем писать код в IDE IntelliJ IDEA, но если у вас какая-то другая, например Eclipse, то разницы большой не будет.

Внутри нашего класса Main описана функция main(), в Java с этой функции начинается исполнение программы, это точка входа в наше приложение. Сейчас там написан только автоматический комментарий (комментарии в Java начинаются с двух символов //). Попробуем кое-что добавить в наш код и проверить работоспособность приложения. Внутри функции main() допишем две строки:

Встроенная функция println() просто выводит на экран текстовую информацию. Запустим наше приложение (нажимаем shift-F10 или зеленый треугольник). Внизу, во вкладке run появится вывод нашей программы:

Функция main() отработала и закончилась, вместе с ней закончилась наша программа.

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

Смысл большинства строк понятен из комментариев к ним, отдельно отмечу строку window.setLayout() — здесь устанавливается менеджер расположения, который будет применяется к компонентам, добавляемым в наше окно. Менеджер BorderLayout может располагать новые компоненты относительно сторон света (North(верх), West(слева), East(справа), South(низ)), Center (центр)). По умолчанию он располагает компоненты по центру. Подробнее с менеджерами расположения можно познакомиться в документации.

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

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

У нас в проекте появился еще один класс. В главное окно можно добавлять только объекты класса JComponent, кроме того, нам нужна область для рисования. Поэтому наследуем наш класс TicTacToe от JComponent. Ой сколько непонятных слов! Сейчас постараюсь пояснить.

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

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

Здесь же, наследуя класс JComponent, мы создадим свой компонент, в котором сможем рисовать то, что нам нужно.

Сегодня игрушку можно наваять на любом ЯП, и JS не исключение. Разработка игр по своей природе сложная задача – мы подскажем, с чего начать.

Разработка игр на JavaScript: реально и безболезненно

Масса людей думает, что все крутые игры (God Of War, Assassin's Creed, Skyrim, добавь по вкусу) созданы на C++. Это отчасти так. В проекте принимают участие сотни специалистов из разных отраслей, в том числе и разработчики, юзающие другой язык – обычная распространенная практика.

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

Существуют Unity, Unreal Engine, CryEngine и прочие классные решения для создания игрушек, и если тебе удобно развлекаться с ними – пожалуйста. Поэтому нет никакой разницы, на чем ты будешь кодить, но в нашем случае речь пойдет о JS-фреймворках.

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

Не нужно забывать о творении команды Khronos Group. WebGL – это веб-версия спецификации OpenGL ES, позволяющая разработчикам общаться с видеокартой через браузер (поверь, лучше не знать, как это работает).

Таким образом, можно создавать 2D и 3D сцены на GPU (что эффективнее, чем на CPU). Супер! Но если взглянуть на код JavaScript, использующий эти технологии, тебе поплохеет.

Поэтому давай разбираться с фреймворками, оберегающими нас от canvas и абстрагирующими от WebGL.

Разработка игр на JavaScript: реально и безболезненно

PixiJS

Этот инструмент можно назвать 2D-рендером WebGL. Это означает, что данная библиотека включает в себя множество функций, предназначенных для эффективной отрисовки 2D-сцен и объектов. Так проще сосредоточиться на создании программного кода, а хардкорные “низкоуровневые” вещи оставить разработчикам PixiJS.

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

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

ExcaliburJS

Здесь у нас полноценный игровой фреймворк, написанный на Typescript. Полная система сцен и камер, спрайты и анимации, звуки, физика и т. д. – все, что пожелаешь. Многим очень нравится API, предоставляемый ExcaliburJS, т. к. с ним уютнее.

Это связано с тем, что создатели продукта из мира веб (некоторые являются веб-разработчиками, другие — DevOps), поэтому большинство шаблонов и подходов – это штуки, которые уже популярны в веб-разработке. Если тебе близка веб-разработка, попробуй этот инструмент.

ImpactJS

ImpactJS начал свой путь со звания “Первый фреймворк для веб-игр”. Большинство фреймворков, рассмотренных ранее, были просто экспериментами, а не коммерческим продуктом. Этот опенсорсный претендент распространяется бесплатно и поставляется с хорошим редактором уровней.

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

CreateJS

CreateJS – это набор модульных библиотек и HTML5-инструментов, работающих асинхронно или параллельно в зависимости от ситуации.

Инструмент предоставляет все, что нужно для создания игры с нуля, с помощью отдельного модуля языка JavaScript. Например, для рендеринга можно взять PixiJS, а для работы со звуковыми материалами SoundJS и т. д.

PhaserJS

И напоследок самый популярный – PhaserJS. Это мощный набор инструментов для создания веб и мобильных игр. Этот фреймворк имеет огромное и активное сообщество – каждую неделю эти ребята выкладывают много новых статей, демо и туториалов, основанных на PhaserJS. Это обеспечивает отличное подспорье для людей, делающих свои первые шаги в геймдеве и нуждающихся в наставлениях. А еще, начиная с 3-й версии, это один из самых производительных игровых фреймворков.

Разработка игр на JavaScript: реально и безболезненно

ThreeJS

ThreeJs – самая популярная 3D-библиотека. Она предлагает наборы функций для выполнения общих операций, которые должны происходить в 3D-сцене. Все мероприятия происходят на более высоком уровне, чем raw WebGL, и не надо заморачиваться с горой низкоуровневых действий.

BabylonJS

Этот фреймворк похож на предыдущий, но имеются различия:

  • API меняется каждые 3 месяца, что помогает при поиске старых решений в интернете;
  • активное и полезное сообщество;
  • продуктивные и отзывчивые разработчики (у Three.js самый старый баг на GitHub датируется 2013 годом, в Babylon.js отмечен два дня назад);
  • The playground – это отличный инструмент для быстрого “опробования” кода, объяснения проблемы и оказания помощи.

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

Кстати, у нас есть очень крутая статья по книгам для геймдэва – рекомендуем!

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

Читайте также: