Search code examples
javadictionarygraphics2dtile

Java - Creating a 2D tile map in a panel using Graphics2D Rectangles?


I'm trying to simulate a battle in a really basic program, but since this is my first time with a big program in Java I'm pretty much clueless on how to proceed. I was thinking I'd have a big 600-by-600 panel and use Graphics2D to just draw the terrain as 20x20 rectangles... Unfortunately even with several tutorials I have no idea what to do.

I have 10 different types of terrain to cycle through, and 5 different landscape profiles. Basically what I want the program to do is when I select a certain profile in a combobox, it paints the landscape and the two opposing sides in the battle (though I'm not quite there yet)

Honestly I haven't made very much progress in the program. Should I be using just Graphics2D and rectangles for something like this, or should I switch to OpenGL or something similar? Although with my current Java experience, I don't think I'd get very far with it without help. Anyways, here's what I have so far:

public class Map extends JPanel {
    int n = 1;
    int x; int y;
    int Area = 750;
    public Color City = new Color(214,217,223);
    public Color Desert = new Color(255,204,102);
    public Color DirtRoad = new Color(153,102,0);
    public Color Forest = new Color(0,102,0);
    public Color Hills = new Color(51,153,0);
    public Color Lake = new Color(0,153,153);
    public Color Mountains = new Color(102,102,255);
    public Color Ocean = new Color(0,0,153);
    public Color PavedRoad = new Color(51,51,0);
    public Color Plains = new Color(102,153,0);
    public Rectangle blocks[];
    public Map(){
        blocks = new Rectangle[750];
        if (n == 1) {
            setBackground(City);
            n = 2;
        } else if (n == 2) {
            setBackground(Desert);
            n = 3;
        } else if (n == 3) {
            setBackground(DirtRoad);
            n = 4;
        } else if (n == 4) {
            setBackground(Forest);
            n = 5;
        } else if (n == 5) {
            setBackground(Hills);
            n = 6;
        } else if (n == 6) {
            setBackground(Lake);
            n = 7;
        } else if (n == 7) {
            setBackground(Mountains);
            n = 8;
        } else if (n == 8) {
            setBackground(Ocean);
            n = 9;
        } else if (n == 9) {
            setBackground(PavedRoad);
            n = 10;
        } else if (n == 10) {
            setBackground(Plains);
            n = 1;
        } else {
        }
        for (int i = 1; i <= Area; i++) {
            blocks[i] = new Rectangle(x, y, 20, 20);
        }
    }

I got this far with several Youtube tutorials, so my code is a bit erratic. All I have in the main form code is a checkBox firing event. (GUI is pre-designed in Netbeans editor.)


Solution

  • 1) I would strongly suggest you stick with learning Java 2d before OpenGL.
    2) Ideally you would have some model view separation - you'd have one class representing the map contents and another one to actually render it.

    Here's some sample code that should get you a bit closer towards your goal. Please try to read through and understand it, not just copy paste and hack away at it.

    enter image description here

    import javax.swing.*;
    import java.awt.*;
    import java.util.Random;
    
    public class Map extends JPanel {
    
        public static final Color CITY = new Color(214,217,223);
        public static final Color DESERT = new Color(255,204,102);
        public static final Color DIRT_ROAD = new Color(153,102,0);
        public static final Color FOREST = new Color(0,102,0);
        public static final Color HILLS = new Color(51,153,0);
        public static final Color LAKE = new Color(0,153,153);
        public static final Color MOUNTAINS = new Color(102,102,255);
        public static final Color OCEAN = new Color(0,0,153);
        public static final Color PAVED_ROAD = new Color(51,51,0);
        public static final Color PLAINS = new Color(102,153,0);
    
        public static final Color[] TERRAIN = {
            CITY,
            DESERT,
            DIRT_ROAD,
            FOREST,
            HILLS,
            LAKE,
            MOUNTAINS,
            OCEAN,
            PAVED_ROAD,
            PLAINS
        };
    
        public static final int NUM_ROWS = 25;
        public static final int NUM_COLS = 30;
    
        public static final int PREFERRED_GRID_SIZE_PIXELS = 10;
    
        // In reality you will probably want a class here to represent a map tile,
        // which will include things like dimensions, color, properties in the
        // game world.  Keeping simple just to illustrate.
        private final Color[][] terrainGrid;
    
        public Map(){
            this.terrainGrid = new Color[NUM_ROWS][NUM_COLS];
            Random r = new Random();
            // Randomize the terrain
            for (int i = 0; i < NUM_ROWS; i++) {
                for (int j = 0; j < NUM_COLS; j++) {
                    int randomTerrainIndex = r.nextInt(TERRAIN.length);
                    Color randomColor = TERRAIN[randomTerrainIndex];
                    this.terrainGrid[i][j] = randomColor;
                }
            }
            int preferredWidth = NUM_COLS * PREFERRED_GRID_SIZE_PIXELS;
            int preferredHeight = NUM_ROWS * PREFERRED_GRID_SIZE_PIXELS;
            setPreferredSize(new Dimension(preferredWidth, preferredHeight));
        }
    
        @Override
        public void paintComponent(Graphics g) {
            // Important to call super class method
            super.paintComponent(g);
            // Clear the board
            g.clearRect(0, 0, getWidth(), getHeight());
            // Draw the grid
            int rectWidth = getWidth() / NUM_COLS;
            int rectHeight = getHeight() / NUM_ROWS;
    
            for (int i = 0; i < NUM_ROWS; i++) {
                for (int j = 0; j < NUM_COLS; j++) {
                    // Upper left corner of this terrain rect
                    int x = i * rectWidth;
                    int y = j * rectHeight;
                    Color terrainColor = terrainGrid[i][j];
                    g.setColor(terrainColor);
                    g.fillRect(x, y, rectWidth, rectHeight);
                }
            }
        }
    
        public static void main(String[] args) {
            // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frame = new JFrame("Game");
                    Map map = new Map();
                    frame.add(map);
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.pack();
                    frame.setVisible(true);
                }
            });
        }
    }