I am programming a small space-themed dungeon crawler game with a GUI made with Swing in Java. I am using the MVC programming paradigm. The game is represented as a grid on which buttons can be clicked to move the player over the board or attack enemies.
In the model/logic of the game I generate an abstract representation of the game environment using a 2D array by randomly assigning objects to x (column) and y (row) coordinates using the following method:
//methods
public void setGalaxy() {
galaxyArray = new GalacticObject[this.row][this.col];
//construct the array
Random rand = new Random();
int random;
for (int i = 0; i < this.row; i++) {
for (int j = 0; j < this.col; j++) {
GalacticObject obj = new GalacticObject(i,j);
random = rand.nextInt(100);
if (random < 5) {
//asteroid (5 percent chance)
obj.makeAsteroid();
} else if (random < 9) {
//blackhole (4 percent chance)
obj.makeBlackHole();
} else {
//rest is open (= empty)
obj.makeOpen();
}
galaxyArray[i][j] = obj;
}
}
}
Now I want to draw the actual GUI game board backed by this 2D array of objects in a JPanel container using a grid of JButtons. I want to basically call all the objects in the galaxyArray and draw a JButton with an corresponding image overlay at the corresponding coordinates in a ButtonGrid. What would be the best way to achieve this using Swing?
Currently, I also have written the following draft for a method that draws a JButtonGrid but I still fail to see what is the best strategy of having it backed by a 2D array of objects. Furthermore, adding the icon for the buttons is not working for reasons unclear to me. (I commented that part out.)
public JPanel makeGameBoard() {
/** This method makes a first version of the game board when the object is first called */
//create a new JPanel
JPanel boardPanel = new JPanel();
// create a gridButton of JButtons defined by the width and length
JButton[][] gridButton = new JButton[this.boardWidth][this.boardLength];
// set layout
boardPanel.setLayout(new GridLayout(this.boardWidth,this.boardLength));
//for-loops to place buttons in gridButton
for(int y = 0; y < this.boardLength; y++) {
for(int x = 0; x < this.boardWidth; x++){
// creates new button (with coordinates as string); gridButton[x][y] needs to be reused as coordinate system
gridButton[x][y]=new JButton(x+":"+y);
gridButton[x][y].setActionCommand(x+":"+y);
gridButton[x][y].setText("");
gridButton[x][y].addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
String com = e.getActionCommand();
System.out.println(com);
}
});
// add icon to every button
// try {
// Image img = ImageIO.read(getClass().getResource("resources/invisible.png"));
// gridButton[x][y].setIcon(new ImageIcon(img));
// }
// catch (IOException ex) {
// System.out.println("Image file for gridButton not found!");
// }
// add the gridButton to the panel
boardPanel.add(gridButton[x][y]);
}
}
//return boardPanel
return boardPanel;
}
Essentially I am wondering what is the best strategy to access the objects stored in the galaxyArray
from my makeGameBoard
method so that the variables of the objects in the array can be used to draw an image on the button with corresponding coordinates in the grid.
/*EDIT Thanks to the suggestion and linked tutorials from the friendly people below, I have made it work! Here is the code for the board View for anyone having similar questions:
public void updateGameBoard(Galaxy board) {
/** This method initializes the board when the galaxy is first created in the game logic and updates it throughout the game */
Galaxy galaxyArray = board;
for (int r = 0; r < this.boardWidth; r++) {
for (int c = 0; c < this.boardLength; c++) {
//make galactic object and extract info from Galaxy
GalacticObject temporary = new GalacticObject(r,c);
temporary = galaxyArray.getGalacticObject(r,c);
//check the object and set the corresponding tile image
if (temporary.isAsteroid()) {
gridButton[r][c].setText("A");
} else if (temporary.isAsteroidField()) {
gridButton[r][c].setText("AF");
} else if (temporary.isBlackHole()) {
gridButton[r][c].setText("BH");
} else if (temporary.isOpen()) {
gridButton[r][c].setText("");
}
}
}
}