2

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("");
            }
        }
    }   
}
GJacobs
  • 109
  • 1
  • 10
  • 2
    Like [this](http://stackoverflow.com/a/7706684/230513)? – trashgod Dec 23 '14 at 11:10
  • In this example there is no higher level representation of the board as a 2D array of objects that is separate from the View. What I'm essentially asking is how to best access the objects stored in the galaxyArray from my makeBoard 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. – GJacobs Dec 23 '14 at 12:34
  • 1
    The code in [Making a robust, resizable Swing Chess GUI](http://stackoverflow.com/q/21142686/418556) stores an array of buttons.. – Andrew Thompson Dec 23 '14 at 13:52

1 Answers1

3

The exact details depend on how you implement the observer pattern. Following this outline, the example game cited here simply lets the main view, RCView, keep a private reference to the array named board, which is maintained by the game model, RCModel. Because RCView implements the Observer interface, the view's update() implementation simply iterates through the board and updates its array of tiles in response. Note that the update() method signature includes a reference to the Observable requesting the update. In your example,

public void update(Observable model, Object arg) {
    GalacticObject galaxyArray = ((GameModel) model).getGalaxyArray();
    //loop though model, updating view components
    this.repaint();
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045