Tile Map Thingy

So, I’ve been working on a crude tile map editor. Seems I have run into a snag, two actually. First one, involves the placement of the tile image. It only puts one tile on the screen, the moment I attempt to add another, the first is deleted. I know my draw code needs to be modified, bur for the life of me, can’t figure out how. Second, is placement of the tile. I have made several attempts to get the tile to fit inside the square in which the mouse is located. Unfortunately, I’ve deleted the attempted code because it was frustrating me. But what I essentially did, was create a Rectangle array and attempted to add to the array as I created the initial tiles. I then attempted to use a rectangle.contains(mouseX, mouseY) to place tile inside given rectangle. I would usually wind up with a java.awt.event error or the tile would be put in the bottom right corner square and none others(im guessing that was because I used for loops and just putting the rectangle inside the loop made the x,y values equal the last numbers of the loop). If I could get a pointer to the right direction, maybe certain specific things I should look up to have a better understanding of what i’m trying to do.


import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.awt.Rectangle.*;

class DrawPanel extends JPanel
{
	private Boolean isVisible = false;
	private Boolean isClicked = false;
	
	private int mouseX, mouseY;
	
	public void paintComponent(Graphics g)
	{
		
		Image image = new ImageIcon("GridTile.png").getImage();
		Image image2 = new ImageIcon("TestTile.gif").getImage();
		
		
		if(isVisible)
		{
			for(int y = 0; y < 15; y++)
			{
				for(int x = 0; x < 15; x++)
				{
					g.drawImage(image, x * image.getWidth(this), y * image.getHeight(this), this);
				}
			}
			
			if(isClicked)
			{
				g.drawImage(image2, mouseX, mouseY, this);
			}
		}
	}
	public Boolean getClick()
	{
		return isClicked;
	}
	
	void setClick(Boolean isClicked)
	{
		this.isClicked = isClicked;
	}
	
	public Boolean getBool()
	{
		return isVisible;
	}
	
	void setBool(Boolean isVisible)
	{
		this.isVisible = isVisible;
	}
	
	public int getMouseX()
	{
		return mouseX;
	}
	
	void setMouseX(int mouseX)
	{
		this.mouseX = mouseX;
	}
	
	public int getMouseY()
	{
		return mouseY;
	}
	
	void setMouseY(int mouseY)
	{
		this.mouseY = mouseY;
	}
}

public class FrameWork
{
	JFrame frame1;
	JFrame frame2;
	JButton panelButton;
	JButton imageButton;
	JButton removeButton;
	DrawPanel panel1;
	DrawPanel panel2;
	
	public int mouseX;
	public int mouseY;
	
	public static void main(String[] args)
	{
		FrameWork gui = new FrameWork();
		gui.go();
	}
	
	public void go()
	{
		frame1 = new JFrame("Pew Pew");
		frame2 = new JFrame();
		panel1 = new DrawPanel();
		panel2 = new DrawPanel();
		frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		
		panelButton = new JButton("Open other frame");
		imageButton = new JButton("Click me");
		removeButton = new JButton("Remove Pic");
		
		panelButton.addActionListener(new PanelListener());
		imageButton.addActionListener(new ImageListener());
		removeButton.addActionListener(new RemoveListener());
		panel1.addMouseListener(new MouseClick());
		
		frame1.getContentPane().add(panel1);
		frame2.getContentPane().add(panel2);
		
		frame1.getContentPane().add(BorderLayout.SOUTH, panelButton);
		frame2.getContentPane().add(BorderLayout.SOUTH, imageButton);
		frame2.getContentPane().add(BorderLayout.NORTH, removeButton);
		
		frame1.setSize(525, 525);
		frame2.setSize(300, 300);
		frame1.setVisible(true);
	}
	
	class PanelListener implements ActionListener
	{
		public void actionPerformed(ActionEvent event)
		{
			frame2.setVisible(true);
		}
	}
	class ImageListener implements ActionListener
	{
		public void actionPerformed(ActionEvent event)
		{
			panel1.setBool(true);
			frame1.repaint();
		}
	}
	class RemoveListener implements ActionListener
	{
		public void actionPerformed(ActionEvent event)
		{
			panel1.setBool(false);
			frame1.repaint();
		}
	}
	class MouseClick extends MouseAdapter
	{	
		public void mouseClicked(MouseEvent event)
		{
			panel1.setClick(true);
			panel1.setMouseX(event.getX());
			panel1.setMouseY(event.getY());
			frame1.repaint();
		}
	}
}

  1. The problem is that you’re only saving one position. Every time the panel is clicked, you should really be adding the point to a list of tiles to draw, like this:

private ArrayList<Point> points = new ArrayList<Point>();

public void paintComponent(Graphics g)
   {
      
      Image image = new ImageIcon("GridTile.png").getImage();
      Image image2 = new ImageIcon("TestTile.gif").getImage();
      
      
      if(isVisible)
      {
         for(int y = 0; y < 15; y++)
         {
            for(int x = 0; x < 15; x++)
            {
               g.drawImage(image, x * image.getWidth(this), y * image.getHeight(this), this);
            }
         }

         for(Point point : points) {
             g.drawImage(image2, point.getX(), point.getY(), this);
         }
         
         if(isClicked)
         {
            points.add(new Point(mouseX, mouseY));
            // make sure only one point is added
            isClicked = false;
         }
      }
   }

  1. This is something that you will have to fix every time you work with some sort of tile map. Here is one way to solve the problem:

// this will replace part of the code above
if(isClicked) {
    // get the index of the tile that was clicked
    int fX = (int)Math.floor(mouseX / image.getWidth(this));
    int fY = (int)Math.floor(mouseY / image.getHeight(this));

    // multiply the index by the tile size to get the actual world coordinates
    points.add(new Point(fX * image.getWidth(this), fY * image.getHeight(this));
}

Ex) These are just some of my thoughts about how your implementation is setup:

  • Instead of having to remember to set isClicked, mouseX, and mouseY every time the screen is clicked, you can just pass them into a function:

// In your DrawPanel class
public void mouseClicked(int mouseX, int mouseY) {
     // Add all the code that was originally in the if statement: isClicked
}

// Then in your main class
   class MouseClick extends MouseAdapter
   {   
      public void mouseClicked(MouseEvent event)
      {
         panel1.mouseClicked(event.getX(), event.getY());
      }
   }

- I’m not really sure how this compiled, but all your Boolean should be lowercased.

  • Don’t load images more than once! Load them in the constructor instead.

Boolean is a value class. http://docs.oracle.com/javase/7/docs/api/java/lang/Boolean.html

Oh yeah, forgot about those. :slight_smile: @OP: Still just use the boolean primitive, unless you really need to use features from the Boolean class (like .valueOf(String)), or need to use it as a type parameter in a Collection.

Wow, thank you. So simple, yet it seemed so complicated(for the first one, second one i’ll need to read over a few more times to understand what’s actually happening there). Didn’t know of the Point class, that’s helpful. Funny how two books and some minor tutorials failed to mention that class, I feel cheated :D. Also got a better understanding of the enhanced for loop, wasn’t entirely sure how that one worked, but now I know. As for the rest, i’ll tidy it up ^.^.