- PVSM.RU - https://www.pvsm.ru -

Rogue-like на Java своими руками. Часть 1

В данном цикле статье я опишу как создать простейшую rogue-like игру с ascii графикой на java с использованием библиотеки libjcsi. Многие из вас когда то потратили немало времени на NetHack или ADOM, другим советую прочитать подробнее о жанре rogue-like(также рогалики)на вики.

Что за libjcsi?

Libjcsi — библиотека Java Console System Interface использует java.swing и позволяет выводить на экран символы аналогично консольной программе, что дает возможность добиться графике аналогичной другим представителям жанра рогаликов.
Скачать исходники libjcsi можно тут [1]. Рекомендую качать именно исходники, так как скомпиленный jar давно устарел.
Библиотекой пользоваться очень просто.Создается экземпляр класса и через него осуществляется весь вывод на экран:

Properties prop = new Properties();
prop.setProperty("fontSize", "15");
prop.setProperty("font", "Courier");

ConsoleSystemInterface csi = new WSwingConsoleInterface("RogueLike", prop);

csi.print(0,0,"Hello world!", CSIColor.WHITE);

Игровой цикл. Обработка клавиатуры

Не будем углубляться в изучение грамотных игровых циклов и сделаем простейший, который не зависит от fps и основывается на единственной булевской переменной stop. Заодно добавим на экран игрока с символом @ и координатами x,y;

public class MainGame
{
	private static MainGame instance;
	private static ConsoleSystemInterface csi;
	private boolean stop;
	private int x,y;
	public static void main(String[] args)
	{
		Properties text = new Properties();
		text.setProperty("fontSize", "15");
		text.setProperty("font", "roguelike.ttf");
		csi = new WSwingConsoleInterface("RogueLike", text);
		instance = new MainGame();
		instance.run();
	}

	public void run()
	{
		stop = false;
		x = 0; y = 0;
		while (!stop)
		{
			csi.cls();
			csi.print(x,y,'@', CSIColor.WHITE); // отрисовка игрока
			csi.refresh();
			handleKeys(); // обработка клавиатуры
		}
		System.exit(0);
	}

Не забудем про функцию handleKeys(), которая служит обработчиком нажатий клавиш. С ее помощью мы будем менять положение игрока на экране. Числа 80 и 25 — ширина и высота экрана соответственно. В коде класса WSwingConsoleInterface их можно изменить, параметры xdim и ydim (мне больше нравилось 80х45).

private void handleKeys(){
			CharKey dir = csi.inkey();
			if(dir.isUpArrow()&& (y-1 >= 0)){
				y--;
			}
			if(dir.isDownArrow() && (y+1 < 25)){
				y++;
			}
			if(dir.isLeftArrow() && (x-1 >= 0)){
				x--;
			}
			if(dir.isRightArrow() && (x+1 < 80)){
				x++;
			}
			if(dir.code == CharKey.Q){
				stop = true;
			}
}

Скомпилим, порадуемся перемещающейся собачке.

Вспомогательные классы

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

Первый класс — Tile

Тайл — базовая единица карты, имеет два параметра: wall — является ли тайл стеной, и blocked — является ли тайл проходимым.

public class Tile
{
	private boolean	blocked;
	private boolean	wall;	

	public boolean isBlocked(){
		return blocked;
	}
	public boolean isWall(){
		return wall;
	}
	public void setBlocked(boolean blocked){
		this.blocked = blocked;
	}
	public void setWall(boolean wall){
		this.wall = wall;
	}
	public Tile(boolean blocked){
		this.blocked = blocked;
		this.wall = false;
	}
	public Tile(boolean blocked, boolean blocked_sight){
		this.blocked = blocked;
		this.wall = false;
	}
}
Второй вспомогательный класс — Rect

Для удобного оперирования прямоугольниками. Имеет параметры, в которых хранятся его углы.

public class Rect
{
	int	x1, x2, y1, y2;
	public Rect(int x, int y, int w, int h){
		this.x1 = x;
		this.y1 = y;
		this.x2 = x + w;
		this.y2 = y + h;
	}
	public int getX1(){
		return x1;
	}
	public int getX2(){
		return x2;
	}
	public int getY1(){
		return y1;
	}
	public int getY2(){
		return y2;
	}
	public int getCenterX(){
		return (this.x1 + this.x2) / 2;
	}
	public int getCenterY(){
		return (this.y1 + this.y2) / 2;
	}
	public boolean intersect(Rect other){
		return (this.x1 <= other.x2 && this.x2 >= other.x1 && this.y1 <= other.y2 && this.y2 >= other.y1);
	}
}

Функции getCenter возвращают координаты центра прямоугольника, а intersect проверяет пересечения двух прямоугольников.

Третий класс — Entity.

Базовый класс, в будущем будет использоваться для монстров и предметов, пока только для объекта игрока.

public class Entity
{
	private int			x, y;	// position
	private char		key;	// char symbol
	private String		name;	// entity name
	private CSIColor	color;	// entity color
	private boolean		blocks; // blocks movement or not

	public Entity(int x, int y, char key, String name, CSIColor color, Boolean blocks){
		this.x = x;
		this.y = y;
		this.key = key;
		this.name = name;
		this.color = color;
		this.blocks = blocks;
	}
	public int getX(){
		return x;
	}
	public int getY(){
		return y;
	}
	public char getKey(){
		return key;
	}
	public boolean blocks(){
		return blocks;
	}
	public CSIColor getColor(){
		return color;
	}
	public String getName(){
		return name;
	}
	public void setX(int x){
		this.x = x;
	}
	public void setY(int y){
		this.y = y;
	}
	public void move(int dx, int dy){
	// перемещение
	}
	public void draw(){
	// отрисовка
	}
	public void clear(){
	// очистка
	}

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

Для статьи использовались:
Java Roguelike Tutorial [2]
Complete Roguelike Tutorial, using python+libtcod [3]
Библиотека libjcsi [4]

Ну и мой рогалик на гитхабе [5]

Автор: Prokky


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/java/16871

Ссылки в тексте:

[1] тут: http://code.google.com/p/libjcsi/

[2] Java Roguelike Tutorial: http://roguebasin.roguelikedevelopment.org/index.php/Java_Roguelike_Tutorial

[3] Complete Roguelike Tutorial, using python+libtcod: http://roguebasin.roguelikedevelopment.org/index.php/Complete_Roguelike_Tutorial,_using_python%2Blibtcod

[4] Библиотека libjcsi: http://slashie.net/libjcsi/

[5] мой рогалик на гитхабе: https://github.com/Prokky/Infinite-Cavy-Story