Java Roguelike Tutorial Lesson One
This is part of a series of tutorials; the main page can be found here. |
Lesson One
The library choice
Before we start, let's talk about libraries. To be specific, user interface libraries. They have always been an important part of Roguelike development ever since Ken Arnold wrote curses, on which he later based the legendary ROGUE. What does such a library do? It allows you to place text on the screen. This is obviously very important, since you want to see something when playing.
Let's look at that a bit closer. What do we expect from a Roguelike UI library?
- It should provide us with a window or something similar where game stuff can be displayed.
- It should let us print single characters or text on that window, with different colors to make it pretty.
- It should handle key input.
That's all. That means, regardless of which library you want to use, it will probably do these things. I myself use Slash's libjcsi. It's a swing-based library that basically works like curses. So if you really don't like libjcsi, it won't be too hard to go and adapt this tutorial for another library. However, I would strongly recommend to use libjcsi if you are a beginner.
A libjcsi test run
So before we start chopping orcs to pieces, let's do a test run with libjcsi. Basically, what we want to see is some text in a little window. That's pretty straightforward, so let's just go ahead and take a look at the code. At the bottom of this page, there's a link where you can see and copy the entire code in one piece.
import net.slashie.libjcsi.wswing.WSwingConsoleInterface;
import net.slashie.libjcsi.ConsoleSystemInterface;
import net.slashie.libjcsi.CSIColor;
import java.util.Properties;
Before we go anywhere, we need to import some stuff from libjcsi and java.util. What these are, will be explained farther down.
public class HelloDungeon{
public static void main(String[] args){
Properties text = new Properties();
text.setProperty("fontSize","20");
text.setProperty("font", "Courier");
See that the class is called HelloDungeon? That means it's in a file named HelloDungeon.java. When you copy the code, don't forget that, or javac will complain.
Now the first thing we are doing here is creating a Properties object. Properties is a class from the java utilities library (java.util), it's a dictionary of key=value pairs, and usually it's used to pass ... properties. We do this by calling the setProperty method of the Properties object. In this case, we want to pass font and font size before we actually create the game window.
Don't be afraid to experiment with them! Any font you specify of course needs to be present on the system the game is supposed to run on, but if it can't be found, libjcsi will fall back to an available monospaced font.
ConsoleSystemInterface csi = null;
try{
csi = new WSwingConsoleInterface("My little Java Roguelike - Programming is fun", text);
}
catch (ExceptionInInitializerError eiie) {
System.out.println("*** Error: Swing Console Box cannot be initialized. Exiting...");
eiie.printStackTrace();
System.exit(-1);
}
I'll admit that this part of the code looks scary, but it's actually quite simple. libjcsi actually has two different libraries: a native one named JCurses and a swing-based one. Both of them implement the ConsoleSystemInterface. (It's an interface, meaning that it's a class with methods and attributes, but they're all empty. Every class that implements this interface MUST have at least the methods and attributes of the interface. It's an easy way to allow you to treat different, but similar classes like they are the same.)
What we do here is create a ConsoleSystemInterface variable named csi. Then we try to create an instance of WSwingConsoleInterface, the class that implements ConsoleSystemInterface, and assign it to csi. You can see that we are passing some text and our Properties object in the constructor. The text will be the title of our game window. This line essentially creates our game window, and the csi object will be our console.
Because the library uses swing, we have to expect the case that swing doesn't work for some reason. Therefore, we've embedded the creation of our game window in a try-catch block. If you aren't familiar with that, it tries to execute the code and catches any errors that code might throw, allowing you to handle them. In our case, we just want to print an error message, the stacktrace (so an experienced java programmer can look at it and see what's wrong) and exit our program. The method that closes the Java Virtual Machine is System.exit(n), with n being a status code. System.exit(0) means that everything is fine, while System.exit(-1) means there was an error of some kind.
csi.print(0,0, "Welcome to the Dungeons of Doom!", CSIColor.WHITE);
csi.refresh();
}
}
At the end, we use the ConsoleSystemInterface method print to put some text into our game window. 0,0, means that it's supposed to be printed in the upper left corner. The class we use to pass the color, CSIColor, contains a large number of predefined colors. I suggest you give CSIColor.BRIGHT_PINK, CSIColor.PSYCHEDELIC_PURPLE or CSIColor.COSMIC_LATTE a try. :D You can find a complete list in the documentation.
When we call refresh(), all printed stuff that might have been buffered by swing gets immediately written into the game window.
So now we are done with the first program, woohoo! Time to run it.
Open a console, go to the folder the HelloDungeon.java and libjcsi,jar are in and run
javac -cp libjcsi.jar;. HelloDungeon.java
java -cp libjcsi.jar;. HelloDungeon
Alright, I assume you know these, but the -cp looks funny to you. It means that your code uses classes that are in libjcsi.jar, not in the same directory as the HelloDungeon.java, and therefore you have to specify libjcsi.jar in the class path. The period means that you still want to look in your current directory. If you are using a unixoid system, you might have to use a colon instead of a period.
And now stare in awe as the words "Welcome to the Dungeons of Doom!" appear on your screen in a little black window. Congrats.
You may now proceed to the next lesson. :D
Code for this page here