Following the previous post, I’ll be sharing my notes while developing a Roguelike in Java. This is not a step by step tutorial, but just the code and some comments to clarify why I used something. This may change in future posts if the development requires it. First the final, graphical, result:

Notes:
Rogue.Java
public class Rogue {
public static void main(String[] args){
GameFrame frame = new GameFrame();
}
}
- Create the main() method as our unique point of entry to the application
- Instantiate the GameFrame
GameFrame.java
import javax.swing.*;
import java.awt.*;
public class GameFrame extends JFrame {
GamePanel panel;
GameFrame(){
panel = new GamePanel();
this.add(panel);
this.setTitle("Rogue");
this.setVisible(true);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setLocationRelativeTo(null);
}
}
- Instantiate the GamePanel
- Calling setVisible(true) on a JFrame which is already visible works for you because this ends up calling validate() internally, which in turn revalidates all subcomponents in the frame: https://stackoverflow.com/a/21187039
- this.setResizable(false); ensures that the graphical interface looks the way you intend by preventing the user from re-sizing it
- this.pack(); sets/fits/adjust the frame to the preferred size of the subcomponent, in this case the GamePanel because I don’t want extra buttons or UI elements. This may change in the future.
- this.setLocationRelativeTo(null); makes the UI appear in the middle of the screen, rather than in the corner
GamePanel.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.geom.Point2D;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
public class GamePanel extends JPanel {
// Panel-specific
static final int SCREEN_WIDTH = 600;
static final int SCREEN_HEIGHT = 600;
static final int UNIT_SIZE = 25;
static final int GAME_UNITS = (SCREEN_WIDTH*SCREEN_HEIGHT)/UNIT_SIZE;
private static final Dimension SCREEN_SIZE = new Dimension(SCREEN_WIDTH, SCREEN_HEIGHT);
// Player-specific
final int x[] = new int[GAME_UNITS];
final int y[] = new int[GAME_UNITS];
int bodyParts = 1;
int playerLocX;
int playerLocY;
char direction;
boolean canPlayerMove = true;
GamePanel(){
this.setPreferredSize(SCREEN_SIZE);
this.setBackground(Color.white);
this.setFocusable(true);
this.addKeyListener(new MyKeyAdapter());
startGame();
}
public void startGame(){
newPlayer();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
draw(g);
}
public void draw(Graphics g){
// Tile Matrix:
for(int i=0; i<(SCREEN_HEIGHT/UNIT_SIZE);i++){
g.drawLine(i*UNIT_SIZE, 0, i*UNIT_SIZE, SCREEN_HEIGHT);
g.drawLine(0, i*UNIT_SIZE, SCREEN_WIDTH, i*UNIT_SIZE);
}
// Player
for (int i = 0; i < bodyParts; i++){
g.setColor(Color.green);
g.setFont(new Font("Ink Free", Font.BOLD, 25));
g.drawString("@", x[i], y[i]);
}
}
public void newPlayer(){
playerLocX = 0;
playerLocY = 0;
}
public void move(){
switch (direction){
case 'U':
y[0] = y[0] - UNIT_SIZE;
break;
case 'D':
y[0] = y[0] + UNIT_SIZE;
break;
case 'L':
x[0] = x[0] - UNIT_SIZE;
break;
case 'R':
x[0] = x[0] + UNIT_SIZE;
break;
}
repaint();
}
public class MyKeyAdapter extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()){
case KeyEvent.VK_LEFT:
direction = 'L';
move();
break;
case KeyEvent.VK_RIGHT:
direction = 'R';
move();
break;
case KeyEvent.VK_UP:
direction = 'U';
move();
break;
case KeyEvent.VK_DOWN:
direction = 'D';
move();
break;
}
}
}
}
- We use .setPreferredSize() when a parent layout manager exists (GameFrame in this case), and .setSize() if doesn’t
- Upon keyPressed() event, we pass the direction char and call move(), which repaint() the player on its new position
- The name for
int bodyParts = 1;
is not the best, I know 🙂 This is just because the core game loop of the game will include a twist and will make sense in the future, otherwise can be refactored easily to a single unit.
Leave a Reply