9 Replies - 2500 Views - Last Post: 19 February 2012 - 05:02 PM Rate Topic: -----

#1 v0rtex  Icon User is offline

  • Caffeine: db "Never Enough!"
  • member icon

Reputation: 223
  • View blog
  • Posts: 773
  • Joined: 02-June 10

Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 05:10 AM

Okay so I am trying to draw a tiled map in Java. I am currently doing the following:

  • Loading mapData from a text file (level1.dat) which is then stored into a 2D Integer Array
  • Draw a BufferedImage dependant on the map data
  • Draw the BufferedImage to my JFrame.


I have four classes:

  • ArrayToImage - Class whereby I convert the Array to the Image
  • MapToArray - Class whereby I convert the level1.dat into the 2D Array
  • Main - Class that instantiates the MainFrame
  • MainFrame - JFrame to display the Image


I think the problem is in MainFrame (Perhaps I am drawing the Image wrong?) or in ArrayToImage as the double for loop might not be working properly?

Here is the code I have worked on so far:

ArrayToImage
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;


public class ArrayToImage {
	Image image;
	   //ignore this part
	private Image wall = null;
	 private Image table = null;
	 private Image floor = null;
	   int x,y,temp=0;
	   //nothing here yet
	   
	   public void loadImages() {
		 
		 wall = Toolkit.getDefaultToolkit().getImage("Tree.bmp");
			 table = Toolkit.getDefaultToolkit().getImage("Icicle.bmp");
			floor = Toolkit.getDefaultToolkit().getImage("floor.bmp");
		   
	   }
	   public ArrayToImage(){
		   loadImages();
	   }
	   //This function will return an BufferedImage with all the tiles drawn on it
	   public BufferedImage getMap(int[][] map){
		   loadImages();
	      BufferedImage bufferedImage = new BufferedImage(map.length*4, (map[0].length)*15, BufferedImage.TYPE_INT_BGR);
	      Graphics2D g2d = bufferedImage.createGraphics();
	      g2d.setColor(Color.green);
	      g2d.fillRect(0, 0, map.length*4, (map[0].length)*15);
	      for(int height= 0; height<map[0].length; height++){
	      for(int length = 0; length<map.length; length++) {
              switch(map[length][height]){
case 0:
g2d.drawImage(floor, length*15, height*15, null);
                                break;
case 1:
g2d.drawImage(wall, length*15, height*15, null);
break;
case 2:
g2d.drawImage(table, length*15, height*15, null);
break;
}
           }
	      }

	      g2d.finalize();
	      g2d.dispose();
	      return bufferedImage;
	   }
	}



MapToArray:



import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
public class MapToArray {

	private final String fileName;
	public int length;
	public int height;
	//simple constructor, Sets the map
	MapToArray(String fileName) {
		this.fileName = fileName;
	}
	
	//returns the 2D array of the map in INT[] []
	public int[] [] getArray() throws IOException {
		ArrayList<String> array = new ArrayList<String>();
		 length = getLength();
		 height = getHeight();
		
		LineNumberReader reader = new LineNumberReader (new FileReader(fileName));
		for (int i = 0; i < height; i++) {
		array.add(reader.readLine());
		}
		
		if (array.size() == 0) {
			System.out.println("Empty map");
	}
		int[][] numbers = new int [length][height]; //reserve space in memory
	int r= 0; 
	//now that we have the size of our array and the data, we fill it in
	for (String s : array) {
		toArray(s, r, numbers);
		r++;
	}
	return numbers; //return map
	}
		
	//returns the map's Length
	private int getLength() throws IOException {
		int countChar = 0;
		try {
			LineNumberReader reader = new LineNumberReader (new FileReader(fileName));
		String lineRead = reader.readLine();
		int length = 0;
		while (countChar < lineRead.length()) {
			if (!(lineRead.charAt(countChar) == ',')) {
				length++;
			}
			countChar++;
		}
		reader.close();
		return length;
		} catch (IOException e) {
			throw e;
		}
	}
	
	//returns height of map (number of lines)
	public int getHeight() throws IOException {
		int height = 0;
		try {
			LineNumberReader reader = new LineNumberReader(new FileReader(fileName));
			String lineRead;
			while ((lineRead = reader.readLine()) != null) {
			}
			//loops to last line of file}
				height = reader.getLineNumber();
				reader.close();
				return height;
			
		} catch (IOException e) {
			throw e;
		}
	

	}
	
	//This function will fill an entire row with the numbers from String s.
    private void toArray(String s, int row, int[][] numbers) {
        String match = ",";
        String[] veld = s.split(match);
        
        for(int i = 0; i<veld.length;i++)
           veld[i] = veld[i].replaceAll(" ","");
        
        for (int i = 0; i < veld.length; i++) {
            try {
                numbers[i][row] = Integer.parseInt(veld[i]);
            } catch (NumberFormatException e) {
                System.out.println("Not a valid map!");
            }
        }
    }

}



MainFrame

import javax.swing.*;

import java.awt.*;
import java.io.IOException;
public class MainFrame extends JFrame{
	int[][] array_map1;
	MapToArray map1;
	Image bckground_1;
	ArrayToImage draw = new ArrayToImage();

public void init() throws IOException {
	map1 = new MapToArray("level1.dat"); //sets the current map
	array_map1 = map1.getArray(); // grabs the map data and stores it in a 2D integer Array.
	bckground_1 = draw.getMap(array_map1); //draws the "Map" by creating a BufferedImage dependant on the 2D Array.
	}

	MainFrame() throws IOException {
		setSize(640,480);
		setTitle("MapLoad Demo");
	init();
	setVisible(true);
	
	}
	public void paint (Graphics g) {
		Graphics2D g2d = (Graphics2D) g;
	g2d.drawImage(bckground_1, 0, 0 ,null);
	}
	
	
	
}



Main

public class Main {
	public static void main(String[] args) throws IOException {
		new MainFrame();
}
}



The problem is when I run main.java ; A 15 * 15 Image loads in the top right (only 1 tile?) so I think It might not be looping properly in ArrayToImage.java. The problem can be seen in the screenshot below:

Spoiler


I also think that all the Images are loading correctly as I painted one Image.
I am pretty sure that I am drawing the images incorrectly in MainFrame.java
Any help is appreciated, Thanks
v0rtex

P.S.: Here is the map Data for level1.dat
Spoiler


Credit goes to elamre to whom provided most of the code through this tutorial.

Attached File(s)

  • Attached File  Tree.bmp (774bytes)
    Number of downloads: 58
  • Attached File  Icicle.bmp (774bytes)
    Number of downloads: 48
  • Attached File  floor.bmp (774bytes)
    Number of downloads: 51

This post has been edited by v0rtex: 19 February 2012 - 07:46 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Loading a 2D Array into a Image. Drawing not working!

#2 CasiOo  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 1379
  • Posts: 3,042
  • Joined: 05-April 11

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 07:08 AM

Your tiles are 15*15, so why are you making the width of the BufferedImage map.length * 4?

You could always make unit tests to check if your units are doing what you expect them to do. First I would make sure that MapToArray class was loading in the map correctly.
Was This Post Helpful? 0
  • +
  • -

#3 v0rtex  Icon User is offline

  • Caffeine: db "Never Enough!"
  • member icon

Reputation: 223
  • View blog
  • Posts: 773
  • Joined: 02-June 10

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 07:19 AM

I fixed that, that just expands the width,length. It is there so that if a tile cannot be drawn, there is a green tile.

I do check if the level1.dat was not loaded correctly. I think the problem may be that I am not returning the BufferedImage correctly or that the for loops are not looping. I tried forcing them to loop like so :


	      for(int height= 0; height<5; height++){
	      for(int length = 0; length<5; length++) {
              switch(map[length][height]){
case 0:
g2d.drawImage(floor, length*15, height*15, null);
                                break;
case 1:
g2d.drawImage(wall, length*15, height*15, null);
break;
case 2:
g2d.drawImage(table, length*15, height*15, null);
break;
}
           }
	      }



With no change.

It is looping correctly as I can see here:

    BufferedImage bufferedImage = new BufferedImage(map.length*15, (map[0].length)*15, BufferedImage.TYPE_INT_BGR);
	      Graphics2D g2d = bufferedImage.createGraphics();
	      g2d.setColor(Color.green);
	      g2d.fillRect(0, 0, map.length*15, (map[0].length)*15);
	      System.out.println( map[0].length + " : " + map.length);
	      for(int height= 0; height<map[0].length; height++){
	      for(int length = 0; length<map.length; length++) {



With the System.out.println( map[0].length + " : " + map.length);
I get the results 5 : 5 which is what it should be. I definitely think the error is either in my Drawing of the Image or how the tiles are being added to the BufferedImage
Was This Post Helpful? 0
  • +
  • -

#4 elamre  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 3
  • Joined: 19-February 12

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 07:36 AM

I STRONLGY dislike the way how you are trying to solve your problem.
First of all, you took all my code from another website without giving me credit here (Only 1 referall to the site).
Secondly you ask for both my help, and post it on a forum. Why should i bother answering your mail then? And thirdly, you ask it on a totally different forum then the one you got it from.

@Cassio
The green tile is there so i can see whether the map suits well. Also the *4 is because there is a bug in my script somewhere which im trying to fix, so it doesnt really belong there.
Was This Post Helpful? 1
  • +
  • -

#5 v0rtex  Icon User is offline

  • Caffeine: db "Never Enough!"
  • member icon

Reputation: 223
  • View blog
  • Posts: 773
  • Joined: 02-June 10

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 07:44 AM

Wow elamre, I apologize If I have offended you then. I will edit the original post, I did refer to your tutorial I am sorry if you thought this was not enough. Reply to the email or the forum post or pm me If you wish. Thanks. I will continue trying to solve this problem.

This post has been edited by v0rtex: 19 February 2012 - 07:47 AM

Was This Post Helpful? 0
  • +
  • -

#6 elamre  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 3
  • Joined: 19-February 12

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 07:47 AM

But why post it on another site then? Why not simply reply to the other forums? And yeah im kind of offended by this, seeing how much research i had to put in this. Then the fact that you mail me the problem. Sure i can do that, but again on another forum.
I do not see why you are doing this?

Also are you sure the images are getting loaded correctly? And try to repaint it a couple of times (just make a while loop in which you are repainting it).
But i do remember this problem, somebody else had it as well. I will do some research on it and post it.
Was This Post Helpful? 1
  • +
  • -

#7 elamre  Icon User is offline

  • New D.I.C Head

Reputation: 3
  • View blog
  • Posts: 3
  • Joined: 19-February 12

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 08:30 AM

I have no clue why it isnt working. Its something with the drawing, my classes seem to be fine. Use this for debugging:
		public BufferedImage getMap(int[][] map){
			int largestRow = 0;
			for(int i = 0; i<map.length;i++){
				if(map[i].length>largestRow)
					largestRow = map[i].length;
			}
			int tileSize = 15;
			//TODO fix the map.length*tileSize. Too large maps will not be showing up!!
			BufferedImage bufferedImage = new BufferedImage(map.length*tileSize ,largestRow*tileSize, BufferedImage.TYPE_INT_BGR);
			Graphics2D g2d = bufferedImage.createGraphics();
			
			for(int heigth = 0; heigth<map[0].length; heigth++){
				for(int length = 0; length<map.length; length++){
		              switch(map[length][heigth]){
						case 0:
							System.out.print("0");
							g2d.setColor(Color.black);
							g2d.fillRect(length*15,heigth*15*15,15,15);
							break;
						case 1:
							System.out.print("1");
							g2d.setColor(Color.blue);
							g2d.fillRect(length*15,heigth*15*15,15,15);
						break;
						case 2:
							System.out.print("2");
							g2d.setColor(Color.red);
							g2d.fillRect(length*15,heigth*15*15,15,15);
						break;
					}
				}
				System.out.println();
			}
			g2d.finalize();
			g2d.dispose();
			return bufferedImage;
		}



Now sorry im not able to solve this today, i have got a busy schedule. But i reckon you can finish it from here.
Was This Post Helpful? 1
  • +
  • -

#8 v0rtex  Icon User is offline

  • Caffeine: db "Never Enough!"
  • member icon

Reputation: 223
  • View blog
  • Posts: 773
  • Joined: 02-June 10

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 08:36 AM

Thanks elamre for your time. Great tutorial btw, will try to solve it. I think its the drawing directly onto a JFrame that's messing it up. Going to draw to a JPanel and add that to the JFrame.
Was This Post Helpful? 0
  • +
  • -

#9 v0rtex  Icon User is offline

  • Caffeine: db "Never Enough!"
  • member icon

Reputation: 223
  • View blog
  • Posts: 773
  • Joined: 02-June 10

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 09:48 AM

Got it working, for some reason returning an ImageIcon when loading the Image corrected the Image, I also added a boolean check on whether the Images were loaded correctly.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;

import javax.swing.ImageIcon;

public class ArrayToImage {
	Image image;

	private Image wall = null;
	private Image table = null;
	private Image floor = null;
	int x, y, temp = 0;
	private boolean imagesLoaded = false;

	public void loadImages() {
		wall = loadImage("wall.jpg");
		table = loadImage("Icicle.jpg");
		floor = loadImage("Floor.jpg");

		imagesLoaded = true;
	}

	private Image loadImage(String fileName) {
		return new ImageIcon(fileName).getImage();
	}

	public void drawImage(Graphics g, Image image, int x, int y) {
		g.drawImage(image, x, y, null);
	}

	public ArrayToImage() {
	}

	// This function will return an BufferedImage with all the tiles drawn on it
	public BufferedImage getMap(int[][] map) {
		loadImages();
		int largestRow = 0;
		for (int i = 0; i < map.length; i++) {
			if (map[i].length > largestRow)
				largestRow = map[i].length;
		}
		int tileSize = 32;

		BufferedImage bufferedImage = new BufferedImage(map.length * tileSize,
				largestRow * tileSize, BufferedImage.TYPE_INT_BGR);
		Graphics2D g2d = bufferedImage.createGraphics();
		g2d.setColor(Color.white);
		if (imagesLoaded) {
			for (int heigth = 0; heigth < map[0].length; heigth++) {
				for (int length = 0; length < map.length; length++) {
					switch (map[length][heigth]) {
					case 0: {
						g2d.drawImage(floor, length * tileSize, heigth
								* tileSize, null);
						break;
					}
					case 1: {
						g2d.drawImage(wall, length * tileSize, heigth
								* tileSize, null);
						// g2d.setColor(Color.red);
						// g2d.fillRect(length*tileSize, heigth*tileSize, 32,
						// 32);
						break;
					}
					case 2: {
						g2d.drawImage(table, length * tileSize, heigth
								* tileSize, null);
						break;
					}
					}
				}
			}
			if (imagesLoaded == false) {
				System.out.println("Error Loading Images!");
			}
		}
		g2d.finalize();
		g2d.dispose();
		return bufferedImage;
	}

}



Thanks again all!
Was This Post Helpful? 0
  • +
  • -

#10 CasiOo  Icon User is online

  • D.I.C Lover
  • member icon

Reputation: 1379
  • Posts: 3,042
  • Joined: 05-April 11

Re: Loading a 2D Array into a Image. Drawing not working!

Posted 19 February 2012 - 05:02 PM

This is how I would have done the loading of a tile map.
I think it is best to just read in the file once, and then close the reader instead of reading through the file multiple times.

Since I am going to need somewhat the same later, I just made my own version of loading in a tile map. I haven't tested any of it (not even checked for compilation errors).

Also there is a little change to the tile map file. It would look like:
5 <-- width of map
5 <-- height of map
0 0 0 0 0
0 1 1 3 0
0 2 1 1 0
0 1 1 1 0
0 0 0 0 0

private Tile[][] map;

public void loadMap(File file) throws IOException {
	ArrayList<String> lines = getLines(file);
	
	if (isValidMap(lines)) {
		int width = Integer.parseInt(lines.get(0));
		int height = Integer.parseInt(lines.get(1));
		map = new Tile[width][height];
		
		int linesIndex = 2;
		for (int y=0; y<map.length; y++) {
			for (int x=0; x<map[y].length; x++) {
				//We are still having tiles specified in this map row
				if (linesIndex < lines.size() && x < tiles.length) { 
					String[] tiles = lines.get(linesIndex).split(" ");
					int tile = Integer.parseInt(tiles[x]);
				
					switch (tile) {
						case 1:
							map[y][x] = new GrassTile();
							break;
						default :
							map[y][x] = new DefaultTile();
							break;
					}
				} 
				else //No more tiles in this row, fill up with default
					map[y][x] = new DefaultTile();
			}
			linesIndex++;
		}
	}
	else {
		throw new MapException("Invalid map");
		return;
	}
}

private ArrayList<String> getLines(File file) throws IOException {
	BufferedReader reader = new BufferedReader(new FileReader(file));
	ArrayList<String> lines = new ArrayList<String>();
	String line;
	while ((line = reader.readLine()) != null)
		lines.add(line);
	reader.close();
	return lines;
}

private boolean isNumber(String text) {
	for (int i=0; i<text.length; i++)
		if (!text.charAt(i).isDigit())
			return false;
}

private boolean isValidMap(ArrayList<String> map) {
	if (map.size() < 2) //Two first lines are used for width and height of the map
		return false;
		
	for (int i=0; i<map.size(); i++) {
		String line = map.get(i);
		switch (i) {
			case 0:
			case 1:
				if (!isNumber(line))
					return false;
				break;
			default :
				String[] tokens = line.split(" ");
				for (String token : tokens)
					if (!isNumber(token))
						return false;
				break;
		}
	}
	return true;
}

public class MapException extends RuntimeException {
	
	public MapException(String message) {
		super(message);
	}
}


This post has been edited by CasiOo: 19 February 2012 - 05:34 PM

Was This Post Helpful? 1
  • +
  • -

Page 1 of 1