1

So I'm just exploring java and trying to make a procedural map for fun but when I started picking random spots in my array to set as a certain image it will no longer paint. The problem only occurs in the last for loop and occurs on:

if(world[c][r] == 2)

or

mountain.paintIcon(this, g, r*Run2.distBetweenTiles, c*Run2.distBetweenTiles);

I removed the starting grass and water to see if it was getting painted under but that's not the case, it's just never getting painted. If anyone could enlighten me that'd be great!

Pics Used: enter image description here, enter image description here, enter image description here P.S. Run2.rowSize, Run2.colSize, Run2.distBetweenTiles = 20 (All Static)

import java.io.IOException;
import java.util.Properties;

import javax.swing.JFrame;

public class Run2
{
    public static final int rowSize = 20;
    public static final int colSize = 20;
    public static final int distBetweenTiles = 20;

    public static void main (String [] args) throws IOException
    {
        JFrame frame = new JFrame();

        WorldCreation2 panel = new WorldCreation2();
        frame.add(panel);

        frame.setTitle("RandomScape");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1280, 720);
        frame.setVisible(true);
        frame.setResizable(false);

        Properties properties = new Properties();
        properties.setProperty("Health", "20");
        System.out.println(properties.getProperty("Health"));
    }
}

import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JComponent;

public class WorldCreation2 extends JComponent
{
    private static final long serialVersionUID = 1L;

    int rowAmount, colAmount;
    int[][] world;
    int islandAmount = 3;
    ArrayList<Point> islandStartingPositions = new ArrayList<Point>();
    protected void paintComponent(Graphics g) 
    {
        super.paintComponent(g);

        int width = getWidth(); 
        int height = getHeight();
        int rowAmount, colAmount;
        int randomRow, randomCol;

        ImageIcon water = new ImageIcon("C:\\Users\\CJ Petruzzelli\\Pictures\\Water 20x20.jpg");
        ImageIcon grass = new ImageIcon("C:\\Users\\CJ Petruzzelli\\Pictures\\Grass 20x20.jpg");
        ImageIcon mountain = new ImageIcon("C:\\Users\\CJ Petruzzelli\\Pictures\\Mountain 20x20.jpg");

        colAmount = height/Run2.colSize;
        rowAmount = width/Run2.rowSize;
        world = new int[colAmount][rowAmount];
        //System.out.println(rowAmount + " , " + colAmount);

        Random rand = new Random();

        //Initialize all values to default 0
        for(int r = 0; r < rowAmount; r++)
        {
            for(int c = 0; c < colAmount; c++)
            {
                //Sets tiles to 0 so full array is instantiated
                world[c][r] = 0;
                grass.paintIcon(this, g, r*Run2.distBetweenTiles, c*Run2.distBetweenTiles);
            }
        }
        ////Puts water on all edges of the map
        for(int r = 0; r < rowAmount; r++)
        {
            for(int c = 0; c < colAmount; c++)
            {
                //Left Side, Right Side, Top Side, Bottom Side
                if(r == 0 && c < colAmount || r == rowAmount-1 && c < colAmount || r < rowAmount && c == 0 || r < rowAmount && c == colAmount-1)
                {
                    world[c][r] = 1;
                    water.paintIcon(this, g, r*Run2.distBetweenTiles, c*Run2.distBetweenTiles);
                }
            }
        }

        //Pick starting points
        int islandStartingPointNum = 0;
        for(int t = islandAmount; t > 0; t--)
        {
            //Pick a random square (Cannot be an edge tile)
            randomRow = rand.nextInt(rowAmount-1)+1;
            randomCol = rand.nextInt(colAmount-1)+1;
            String rowString = String.valueOf(randomRow);
            String colString = String.valueOf(randomCol);
            if(world[randomCol][randomRow] == 1)
            {
                System.out.println(colString + " , " + rowString + " This is an edge tile");
                islandAmount++;
            }
            else
            {
                System.out.println(colString + " , " + rowString + " This is a grass tile, turning to mountain");
                world[randomCol][randomRow] = 2;
                islandAmount--;
                //Store it
                islandStartingPositions.add(new Point(randomCol, randomRow));
            }
            System.out.println(islandStartingPositions.get(islandStartingPointNum));
            islandStartingPointNum++;
        }

        //Turn starting points into something
        for(int r = 0; r < rowAmount; r++)
        {
            for(int c = 0; c < colAmount; c++)
            {
                if(world[c][r] == 2) // Checking number of location not current locations number?
                {
                    System.out.println("This is a mountain tile");
                    mountain.paintIcon(this, g, r*Run2.distBetweenTiles, c*Run2.distBetweenTiles);
                }
            }
        }
    }
}
c0der
  • 18,467
  • 6
  • 33
  • 65
  • 1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). E.G. [This answer](https://stackoverflow.com/a/10862262/418556) hot links to an image embedded in [this question](https://stackoverflow.com/q/10861852/418556). 3) Application resources will become embedded resources by the time of deployment, so it is wise to start accessing them as if they were, right now. .. – Andrew Thompson Nov 03 '18 at 01:13
  • .. An [tag:embedded-resource] must be accessed by URL rather than file. See the [info. page for embedded resource](http://stackoverflow.com/tags/embedded-resource/info) for how to form the URL. 4) Don't attempt long running tasks (like loading images) in a paint method! These methods are supposed to finish quickly. Instead declare the icons as class attributes and load them on construction. – Andrew Thompson Nov 03 '18 at 01:13
  • 1&2) I'm assuming you were missing the pictures, so I put them in. 3) I implemented the example you linked to getting the pictures through a package so they're accessed as if they were there. Same problem still. 4) Can I get an example of how I am supposed to do it then? I learn better that way and don't know how to do it any other way. – General Cman Nov 03 '18 at 01:49
  • `4) Can I get an example of how I am supposed to do it then?` - you load the images in the constructor of your class. Also same with your "random" logic. Don't generate random values in the painting method. You can't control how frequently the paintComponent() method will be called and you don't want the random values to be regenerated every time Swing determines the panel needs to be repainted. Your "static variables" should be instance variables in your WorldCreation class so they are available for the painting method. Maybe they should be passed as parameters to make the logic dynamic. – camickr Nov 03 '18 at 02:14
  • `world[c][r] = 1;` - a painting method is for painting only. It should NOT be used to change the state of the class. So once again you should be initialize the 2D array in the constructor of your class to the appropriate value. Then in the painting method you simply iterate through the array and paint the Icon associated to the value in the array. Also don't create an ImageIcon. You add Icons to Swing components. Instead use "ImageIO` to read the images and the use the Graphics.drawImage(...) method. – camickr Nov 03 '18 at 02:17
  • *"1&2) I'm assuming you were missing the pictures, so I put them in."* You should then have hot-linked to them by URL. I could, but if you couldn't be bothered, why should I (or anyone else). It's your problem after all, and our interest is purely academic. But it runs much deeper than just 'missing images'. Consider theses points. 1) The extra class is irrelevant. Just put the `main` method in `WorldCreation2`. 2) The problem is about overlaying two images. So a third is redundant. 3) Columns, rows, distance between tiles. How is any of this relevant to the stated problem? .. – Andrew Thompson Nov 03 '18 at 02:51
  • .. **Get rid of it** & simplify the code down to the minimum it takes to reproduce the error! Either you did not read, or completely misunderstood the two linked documents. Go back & read them carefully. If you have any confusion regarding them, ask. I'm well placed to explain any specific thing in either document that you have trouble understanding. – Andrew Thompson Nov 03 '18 at 02:54

1 Answers1

2

Here is a quick example of adding tiles to a JComponent.
If you need more help, post an MCVE of you problem. It should be something like this:

import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Run2
{

    public static void main (String [] args) throws IOException
    {
        JFrame frame = new JFrame();
        frame.add( new WorldCreation2());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}


class WorldCreation2 extends JComponent
{

    private int rows = 15, cols = 10;
    private URL[] urls = { //use embedded resources for posting question
            getUrl("http://static.coach.com/aapz_prd/on/demandware.static/-/Library-Sites-globalLibrary/default/dw1777ce46/201708/canada-wwcm/close_grey.png"),
            getUrl("https://s7d2.scene7.com/is/image/JCPenney/DP0423201517014421S.jpg?wid=20&hei=20&op_usm=.4,.8,0,0&resmode=sharp2"),
            getUrl("https://i2.wp.com/www.todaytells.com/wp-content/uploads/2018/07/new-and-ongoing-cinema-releases-uk-ire-from-thu-jul-12.jpg?fit=20%2C20&ssl=1")
    };

    public WorldCreation2() {

        setLayout(new GridLayout(rows, cols));
        for(int row = 0; row < rows; row++) {
            for(int col = 0; col < cols; col++) {
                if(row < 5)
                {
                    add(getTile(urls[0]));
                }else if (row < 10) {
                    add(getTile(urls[1]));
                }else {
                    add(getTile(urls[2]));
                }
            }
        }
    }

    private JLabel getTile(URL url){

        return new JLabel(new ImageIcon(url));
    }

    private URL getUrl(String path) {

        URL url = null;
        try {
            url =   new URL(path);
        } catch (MalformedURLException ex) {    ex.printStackTrace();   }

        return url;
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
c0der
  • 18,467
  • 6
  • 33
  • 65
  • @Andrew Thompson thanks for the edit. I always wondered if I should write _a mcve_ because it starts with m, or _an mcve_ because it stands for an Example. I tend to write an, but I am not sure about it. – c0der Nov 06 '18 at 09:07
  • I would use 'an MCVE' or 'a [mcve]'. Since 'example' is longer than '`[mcve]`' I'd never use it. (shrug) – Andrew Thompson Nov 06 '18 at 09:58