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

в 15:02, , рубрики: java, roguelike, метки: ,

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

Что за libjcsi?

Libjcsi — библиотека Java Console System Interface использует java.swing и позволяет выводить на экран символы аналогично консольной программе, что дает возможность добиться графике аналогичной другим представителям жанра рогаликов.
Скачать исходники libjcsi можно тут. Рекомендую качать именно исходники, так как скомпиленный 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
Complete Roguelike Tutorial, using python+libtcod
Библиотека libjcsi

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

Автор: Prokky

  1. mr. Max:

    Огромное спасибо, это то, что я безуспешно ищу уже часа полтора )

  2. Dario:

    Вместо этой наркоманской библиотеки (на кой черт здесь нужен Swing?) используйте jansi. Она выводит в консоль текст с использованием ANSI-кодов в UNIX (Linux/FreeBSD/MacOS) и Windows. Цвета, установка позиции курсора, очистка экрана – т.е. весь необходимый минимум.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js