- PVSM.RU - https://www.pvsm.ru -
В данном цикле статье я опишу как создать простейшую rogue-like игру с ascii графикой на java с использованием библиотеки libjcsi. Многие из вас когда то потратили немало времени на NetHack или ADOM, другим советую прочитать подробнее о жанре rogue-like(также рогалики)на вики.
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;
}
}
Скомпилим, порадуемся перемещающейся собачке.
Для генерации и отображения подземелий нам потребуются несколько вспомогательных классов.
Тайл — базовая единица карты, имеет два параметра: 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;
}
}
Для удобного оперирования прямоугольниками. Имеет параметры, в которых хранятся его углы.
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 проверяет пересечения двух прямоугольников.
Базовый класс, в будущем будет использоваться для монстров и предметов, пока только для объекта игрока.
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
Нажмите здесь для печати.