Найти тему
Sapphire

Создание игры на JAVA.

Оглавление

Введение и подготовка

Привет хаброжители. Данный пост является «рерайтом» моего поста для песочницы. На этот раз я постараюсь охватить больше тем, чем тогда.

Почему Java?

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

IDE

Начнем с выбора IDE. Я являюсь фанатом Eclipse и посоветую вам его.
Если же почему-то вам он не понравился, вы можете использовать NetBeans, Intellij IDEA или командную строку и ваш любимый редактор.

JDK

И скачаем JDK последней версии: JDK 7u4

Скорее всего проблем с установкой IDE у вас не возникнет, а если у вас 64-битная система, все же посоветую устанавливать 32-битный Eclipse, так как иногда бывают ошибки и Eclipse у вас просто не запустится.

Под катом мы приступим к созданию игры.

Класс Game

Итак, создаем проект, в нем класс Game(попутно создав в нем точку входа). Данный класс должен наследовать класс Canvas и реализовать интерфейс Runnable:

public class Game extends Canvas implements Runnable {
private static final long serialVersionUID = 1L;

public void run() {
//функция run появляется после того, как мы добавили "implements Runnable"
}

public static void main(String[] args) {
}
}

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

Создадим функцию start() и в ней мы будем создавать новый поток и переводить running в true:

public void start() {
running = true;
new Thread(this).start();
}

Создадим три функции — update(long delta), render() и init(). Я надеюсь что их значение вам понятно. В функции run() создадим главный игровой цикл, перед ним будем вызывать init(), а в нем самом render() и update(). Так же мы будем вычислять разницу между кадрами(delta time).

public void run() {
long lastTime = System.currentTimeMillis();
long delta;

init();

while(running) {
delta = System.currentTimeMillis() - lastTime;
lastTime = System.currentTimeMillis();
update(delta);
render();
}
}

public void init() {

}

public void render() {

}

public void update(long delta) {

}

Пока поработаем над функцией render().

public void render() {
BufferStrategy bs = getBufferStrategy();
if (bs == null) {
createBufferStrategy(2);
//создаем BufferStrategy для нашего холста
requestFocus();
return;
}

Graphics g = bs.getDrawGraphics();
//получаем Graphics из созданной нами BufferStrategy
g.setColor(Color.black);
//выбрать цвет
g.fillRect(0, 0, getWidth(), getHeight());
//заполнить прямоугольник
g.dispose();
bs.show();
//показать
}

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

public static int WIDTH = 400; //ширина
public static int HEIGHT = 300;
//высота
public static String NAME = "TUTORIAL 1";
//заголовок окна

public static void main(String[] args) {
Game game = new Game();
game.setPreferredSize(new Dimension(WIDTH, HEIGHT));

JFrame frame = new JFrame(Game.NAME);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//выход из приложения по нажатию клавиши ESC
frame.setLayout(new BorderLayout());
frame.add(game, BorderLayout.CENTER);
//добавляем холст на наш фрейм
frame.pack();
frame.setResizable(false);
frame.setVisible(true);

game.start();
}

Примерно вот так выглядит наш класс Game сейчас.

Класс Sprite

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

import java.awt.Graphics;
import java.awt.Image;

public class Sprite {
private Image image;
//изображение

public Sprite(Image image) {
this.image = image;
}

public int getWidth() {
//получаем ширину картинки
return image.getWidth(null);
}

public int getHeight() {
//получаем высоту картинки
return image.getHeight(null);
}

public void draw(Graphics g,int x,int y) {
//рисуем картинку
g.drawImage(image,x,y,null);
}
}

Сразу же проверим работоспособность. Возьмем эту картинку и скопируем ее в папку с нашим классом Sprite. Добавим функцию getSprite() в класс Game(временно).

public Sprite getSprite(String path) {
BufferedImage sourceImage = null;

try {
URL url = this.getClass().getClassLoader().getResource(path);
sourceImage = ImageIO.read(url);
} catch (IOException e) {
e.printStackTrace();
}

Sprite sprite = new Sprite(Toolkit.getDefaultToolkit().createImage(sourceImage.getSource()));

return sprite;
}

Добавим нашу картинку в папку assets(папку создать в корне проекта), саму папку надо добавить в build path.

Далее создаем переменную hero типа Sprite. В функции init() инициализируем ее. В Функции render() рисуем:

//в "шапку"
public static Sprite hero;

//в init()
hero = getSprite("man.png");

//в render() после g.fillRect(0, 0, getWidth(), getHeight());
hero.draw(g, 20, 20);

Результат:

Весь код Game.java

Input

Для обработки инпута мы создадим класс, наследующий KeyAdapter:

private class KeyInputHandler extends KeyAdapter {

}

Тут же и объявим две переменных в шапке класса Game:

private boolean leftPressed = false;
private boolean rightPressed = false;

Внутри класса KeyInputHandler создадим две функции:

public void keyPressed(KeyEvent e) { //клавиша нажата
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
leftPressed = true;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
rightPressed = true;
}
}
public void keyReleased(KeyEvent e) {
//клавиша отпущена
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
leftPressed = false;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
rightPressed = false;
}
}

Теперь в функции init() добавим следующее:

addKeyListener(new KeyInputHandler());

Создадим переменные x и y для героя(так как пока что мы еще не написали класс Entity). Сделаем чтобы герой всегда рисовался на этих координатах.

private static int x = 0;
private static int y = 0;

hero.draw(g, x, y);

А теперь в функции update() будем проверять нажаты ли клавиши и изменять x-координату.

public void update(long delta) {
if (leftPressed == true) {
x--;
}
if (rightPressed == true) {
x++;
}
}

Он двигается!

Спасибо за внимание.