Создание игры на LWJGL #1


Написание игры — сложный и интересный процесс, который требует много времени. В данном цикле статей я расскажу, как создать простую 3D игру на Java с использование библиотеки LWJGL.


Для создания своей игры необходимо следующее:


  • Умения писать код на Java (необходимый минимум: понимание работы условий, циклов, строк, массивов, функций, классов)
  • Среда разработки (я буду использовать Eclipse)
  • Библиотека LWJGL
  • Видеокарта, поддерживающая OpengGL версии не ниже 3.3
  • Свободное время
  • Идея

Кому интересно, прошу под кат.

Шаг первый, подготовка


Как установить Eclipse.

Скачать LWJGL 2.9.3, библиотеку 3D графики, добавить её в свой проект.

Скачать slick-util, библиотеку, упрощающую загрузку текстур, добавить её в проект.

Шаг второй, проверка


Первым делом создадим класс Main в пакете main, поместим в него следующий код:



Если строка с input не подсвечивается красным — значит всё ок (на скрине подсвечивается желтым, т.к. данная библиотека ещё не используется в коде).

Шаг третий, дисплей


Наполним класс Main следующим кодом:

Начальный код
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;

public class Main {
	static int width = 800, height = 600;
	static DisplayMode mainDisplayMode = new DisplayMode(width, height);
	static boolean running = true;
	
	static void update() {
		if (Display.wasResized()) {
			width = Display.getWidth();
			height = Display.getHeight();
        	}
		Display.update();	    	
    		Display.sync(60);
    	
		if (Display.isCloseRequested()) {
        		running = false;
        	}
	}
	
	public static void main(String[] args) {
		try {
		Display.setLocation(
		(Display.getDesktopDisplayMode().getWidth() - mainDisplayMode.getWidth()) / 2, 
		Display.getDesktopDisplayMode().getHeight() - mainDisplayMode.getHeight()) / 2);
    		Display.setResizable(true);
            	Display.setVSyncEnabled(true);
        	Display.setDisplayMode(mainDisplayMode);
            	Display.create();
            
        } catch (LWJGLException ex) {
            	System.err.println(ex.getStackTrace().toString());
            	Display.destroy();
            	System.exit(1);
        }
		
		while (running) {
			
			update();
        	}
        
        	Display.destroy();
        	System.exit(0);
	}
}


Итак, что здесь происходит:

Display.setLocation(
(Display.getDesktopDisplayMode().getWidth() - mainDisplayMode.getWidth()) / 2, (Display.getDesktopDisplayMode().getHeight() - mainDisplayMode.getHeight()) / 2);

Display.setResizable(true);
Display.setVSyncEnabled(true);
Display.setDisplayMode(mainDisplayMode);
Display.create();

В этих строчках:

  1. задаётся положение дисплея (по центру экрана)
  2. разрешается изменять его размер
  3. включается вертикальная синхронизация
  4. устанавливается DisplayMode в котором хранятся размеры экрана и некоторые другие параметры
  5. в последней строчке дисплей создаётся и показывается на экране.

static void update() {
	if (Display.wasResized()) {
		width = Display.getWidth();
		height = Display.getHeight();
        }
	Display.update();	    	
    	Display.sync(60);
    	
	if (Display.isCloseRequested()) {
        	running = false;
        }
}

В функции update, которая вызывается в бесконечном цикле:

  1. Проверка изменения размеров окна
  2. Обновление дисплея
  3. В строке Display.sync(60) происходит синхронизация дисплея с 60 герцами (если у Вас другая частота обновлений экрана, например 59, 76, 120, 144 и т.д., выставите свою частоту).
  4. Проверка закрытия окна

Заметьте, как происходит окончание работы программы, когда пользователь нажал на крестик, флаг закрытия окна, Display.isCloseRequested(), становится true, а переменная running становится false, и при следующей итерации цикл while(running) не выполнится и произойдёт переход к строчкам Display.destroy(), которая уничтожит дисплей и System.exit(0), вызов которой завершит программу.

Шаг четвёртый, OpenGL


Чтобы инициализировать OpenGL в функцию main перед циклом while(running) нужно добавить следующий код:

if (!GLContext.getCapabilities().OpenGL33) {
        System.err.println("Ваша видеокарта не поддерживает OpenGL 3.3.");
        System.exit(0);
}

Данный код проверяет, что видеокарта поддерживает OpenGL 3.3, если видеокарта не поддерживает данную версию, попробуйте обновить драйвера или переключиться на другую видеокарту (если у Вас их более одной).

Итак, проверка сделана, если всё хорошо, видеокарта поддерживает OpenGL 3.3, то двигаемся дальше. После кода проверки, до цикла добавим следующий код:

glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glClearColor(1f, 0f, 0f, 1f);

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

  1. Включит в шейдерах мягкое освещение
  2. Включит текстуры
  3. Включит проверку глубины (чтобы ближние объекты перекрывали дальние)
  4. Установит цвет очистки

В цикл while(running), до вызова функции update(), добавим строчку

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

Которая будет очищать буфер цвета и буфер глубины при каждом обновлении экрана.

Итоговый код


Нажмите, чтобы посмотреть
import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.GL_SMOOTH;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glShadeModel;

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GLContext;


public class Main {
	static int width = 800, height = 600;
	static DisplayMode mainDisplayMode = new DisplayMode(width, height);
	static boolean running = true;
	
	static void update() {
		if (Display.wasResized()) {
			width = Display.getWidth();
			height = Display.getHeight();
        }
		Display.update();	    	
    	Display.sync(60);
    	
		if (Display.isCloseRequested()) {
        	running = false;
        }
	}
	
	public static void main(String[] args) {
		try {
    		Display.setLocation((Display.getDesktopDisplayMode().getWidth() - mainDisplayMode.getWidth()) / 2, (Display.getDesktopDisplayMode().getHeight() - mainDisplayMode.getHeight()) / 2);
    		Display.setResizable(true);
            Display.setVSyncEnabled(true);
        	Display.setDisplayMode(mainDisplayMode);
            Display.create();
            
        } catch (LWJGLException ex) {
            System.err.println(ex.getStackTrace().toString());
            Display.destroy();
            System.exit(1);
        }
		
		if (!GLContext.getCapabilities().OpenGL33) {
        	System.err.println("Ваша видеокарта не поддерживает OpenGL 3.3.");
            System.exit(0);
        }
		
		glShadeModel(GL_SMOOTH);
        glEnable(GL_TEXTURE_2D);
        glEnable(GL_DEPTH_TEST);
        glClearColor(1f, 0f, 0f, 1f);
        
		
		while (running) {
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			
			update();
        }
        
        Display.destroy();
        System.exit(0);
	}
}


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

Комментарии (7)


  1. vlanko
    28.10.2018 12:16

    Если кому интересно, OpengGL версии не ниже 3.3 это минимум
    GeForce 8000;
    Radeon HD 2000.


  1. ThisMan
    28.10.2018 12:26

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


  1. ExplosiveZ
    28.10.2018 15:09
    +1

    LWJGL 2 давно не поддерживается и не получает фиксы / патчи безопасности.


  1. Helgen
    28.10.2018 18:47

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

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


  1. Xilarom
    28.10.2018 22:15

    Только не забрасывайте! Во всем рунете уроки по LWJGL кончаются на одном-двух.
    Будут ли уроки по 3 части библиотеки?


  1. Threew82
    29.10.2018 15:56

    Если кому интересно, то вот нормальный гайд по геймдеву на Java
    legacy.gitbook.com/book/lwjglgamedev/3d-game-development-with-lwjgl/details
    Возможно немного устарел, но лучше чем ждать перевода.
    Ну и ссылка на гугл www.google.ru/search?newwindow=1&ei=Q7bWW4_VDoWosAGk2pHwBQ&q=lwjgl+tutorial&oq=lwjgl+tu&gs_l=psy-ab.3.0.0j0i203k1l4j0i22i30k1l5.1680.5354.0.6977.9.9.0.0.0.0.83.692.9.9.0....0...1c.1.64.psy-ab..0.8.606...35i39k1j0i67k1j0i20i263k1j33i160k1.0.JjRJmp9Q1wc


  1. MisterParser
    29.10.2018 21:38

    Было интересно прочитать, но нужно более обстоятельно и с картинками.