_Scyth_
Senior Newbie 
|
 |
«
Posted
2012-12-28 14:24:32 » |
|
I have looked for days and days, but could not find a solution to my problem. How do you tile a map in java? When i worked with XNA the array.length gave me more or less an x and y, but java does not. If someone can post either source code or instructions on how to do this it would be extremely helpful. Thanks ~Scyth EDIT: Solved, for others this is the code: Class Variables Needed: 1 2 3 4 5 6 7
| public static final int BLACK = 0; public static final int GRASS = 1; public static final int Magenta = 2; int[][] tiles;
InputStream level1 = this.getClass().getResourceAsStream("level.txt"); |
Constructor must have this code: 1 2 3 4 5 6 7 8 9 10
| public Game() { try { tiles = getIntsFromTextFile(level1); } catch (IOException e) { e.printStackTrace(); } } |
Your Render Methods: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public void render(Graphics2D g) { renderTiles(g); }
public void renderTiles(Graphics2D g) { for (int y = 0; y < tiles.length; y++) { for (int x = 0; x < tiles[y].length; x++) { renderTile(x, y, tiles[y][x], g); } } } public void renderTile(int x, int y, int tileID, Graphics2D g) { switch (tileID) { case BLACK: g.setColor(Color.black); g.drawRect(x * 32, y * 32, 32, 32); break; case GRASS: g.setColor(Color.green); g.drawRect(x * 32, y * 32, 32, 32); break; case MAGENTA: g.setColor(Color.MAGENTA); g.drawRect(x * 32, y * 32, 32, 32); break; } } |
Your methods to read the text file: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| public int[][] getIntsFromTextFile(InputStream input) throws IOException { ArrayList<int[]> yList = new ArrayList<int[]>(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(input)); int y = 0; String line = null; while ((line = reader.readLine()) != null) { yList.add(parseString(line)); } } finally { if (reader != null) { reader.close(); } } int[][] ints = new int[yList.size()][]; for (int i = 0; i < ints.length; i++) { ints[i] = yList.get(i); } return ints; }
public int[] parseString(String str) { int[] array = new int[str.length()]; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); array[i] = Integer.parseInt("" + c); } return array; } |
Voila! You're done, all you have to do is create and edit a level.txt file and it will display the corresponding tiles in the correct position, if our tile are not 32x32 then you should change *32 in each of the cases: 1 2 3 4 5 6 7 8
| public void renderTile(int x, int y, int tileID, Graphics2D g) { switch (tileID) { case BLACK: g.setColor(Color.black); g.drawRect(x * 32, y * 32, 32, 32); break; case GRASS: g.setColor(Color.green); g.drawRect(x * 32, y * 32, 32, 32); break; case MAGENTA: g.setColor(Color.MAGENTA); g.drawRect(x * 32, y * 32, 32, 32); break; } } |
|
|
|
|
|
gouessej
|
 |
«
Reply #1 - Posted
2012-12-28 14:27:04 » |
|
Tiling is implemented in LibGDX, isn't it? What do you mean by tiling a map?
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #2 - Posted
2012-12-28 14:33:13 » |
|
like if i had a text file which was like:
111111111122222221111011123 115464531111112223333333111 222222221111111111100000000
etc and then in java i can read each number, and load paint an image in accordance to the number, eg: 1 would be dirt, 2 would be grass etc then i could use this to paint my map to the screen. however i do not know how to read each number and interpret there position to correspond to where i want them for example the first 1 in the first line would be painted at (0,0) and the first one on the second line would be painted at (0,32) etc
any ideas?
|
|
|
|
|
Games published by our own members! Check 'em out!
|
|
matheus23
|
 |
«
Reply #3 - Posted
2012-12-28 14:46:08 » |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| public int[][] getIntsFromTextFile(File file) throws IOException { ArrayList<int[]> yList = new ArrayList<int[]>(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(file))); int y = 0; String line = null; while ((line = reader.readLine()) != null) { yList.add(parseString(line)); } } finally { if (reader != null) { reader.close(); } } int[][] ints = new int[yList.size()][]; for (int i = 0; i < ints.length; i++) { ints[i] = yList.get(i); } return ints; }
public int[] parseString(String str) { int[] array = new int[str.length()]; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); array[i] = Integer.parseInt("" + c); } } |
|
|
|
|
matheus23
|
 |
«
Reply #4 - Posted
2012-12-28 14:53:09 » |
|
Mind the edit.
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #5 - Posted
2012-12-28 14:57:54 » |
|
thanks for commenting! didnt understand the last few parts of it! Thanks so much!
|
|
|
|
|
SHC
|
 |
«
Reply #6 - Posted
2012-12-28 15:04:20 » |
|
Contents of file "level.txt" 1 2 3
| 111111111122222221111011123 115464531111112223333333111 222222221111111111100000000 |
Load level method 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private void loadLevel(){ BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("level.txt"))); String line = null;
while ((line = reader.readLine())!=null){ for (int i=0; i<line.length; i++){ int c = Integer.parseInt("" + line.charAt(i)); switch (c){ case 0: Map.add(new Object0()); break; .... } } } } catch (Exception e){ e.printStackTrace(); System.exit(-1); } } |
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #7 - Posted
2012-12-28 15:10:02 » |
|
@matheus: so now, considering that we know how many rows there are file and we read each character one at a time, is there a way to interpret the row and "column" of each char? you probably already have it coded but I'm an amateur at java. @ SHC will that give both row and "column"?
|
|
|
|
|
matheus23
|
 |
«
Reply #8 - Posted
2012-12-28 15:40:00 » |
|
@matheus: so now, considering that we know how many rows there are file and we read each character one at a time, is there a way to interpret the row and "column" of each char? you probably already have it coded but I'm an amateur at java. @ SHC will that give both row and "column"?
My code is not really the best, because it's actually like DOM and SAX for xml, but that's another story. Short: It reads all data and then the data is parsed, instead of parsing all the data right away. Anyways. You'd need to create tiles from the int[][] array you got. You basically got an array of numbers reaching from 0 to 9, describing what tiles to put. So you'd just iterate through the array and create the tiles as you want them (you could also just use the array as an array of tile ID's and don't use classes for tiles at all, but yeah. Thats another story as well...) 1 2 3 4 5 6 7 8
| public void createTiles(int[][] dataArray) { for (int y = 0; y < dataArray.length; y++) { for (int x = 0; x < dataArray[y].length; x++) { int tileID = dataArray[x][y]; createTile(x, y, tileID); } } } |
Mind that I first iterate throught y ( ) and then through x ( ). This is needed, or else your map in the file will be rotated by 90°  (Or probably not... if so, try swapping those variables  )
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #9 - Posted
2012-12-28 15:46:14 » |
|
Thanks Matheus, i literally spent ages trying to work out how to use it so now i'll try this and if it works - then thank you so much, this has been my problem since i started game programming in java!
|
|
|
|
|
Games published by our own members! Check 'em out!
|
|
SHC
|
 |
«
Reply #10 - Posted
2012-12-28 15:54:23 » |
|
@ SHC will that give both row and "column"?
Yes. It reads each line i.e line and each character is a cell in the row.
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #11 - Posted
2012-12-28 16:05:40 » |
|
EDIT : Too much code  removed it
|
|
|
|
|
Phibedy
|
 |
«
Reply #12 - Posted
2012-12-28 16:20:44 » |
|
Are u using a "tile-editor"? If one line in the txt is one complete line of tiles, you could use .readline() ->after that u split it at the " " and parse it in the int[x (increasing)][y] -> next line int[x (increasing)][y+1] If you one line isn't one complete line of tiles, you could just read the whole file ->after that u split it at the " " and parse it in the int - [y] until the width is reached.
-> next line int[x (increasing)][y+1] Am I wrong or are you not able to create tiles with the id 10? In addition you could write a tile-mapeditor on your own, it's not that hard. To save the map afterwards, I would serialize it, especially if you have entities on it, it makes it much easier. best regards
|
|
|
|
|
matheus23
|
 |
«
Reply #13 - Posted
2012-12-28 16:24:02 » |
|
Oh yes. I see  Better use our pastebin for such big codes. Just remember that for the next time  (If you write a reply just like me right now, there is a link "our pastebin" at the bottom) You don't manage your tiles yourself right now. Okey. You need to change you class to take another field: Then, when initializing (in the constructor) you load the text file into your tiles array: tiles = getIntsFromTextFile(level1); |
And now you have a wonderful -array you can use to draw your tiles. You can do this in the method: public void render(Graphics g) { renderTiles(g); }
public void renderTiles(Graphics g) { for (int x = 0; x < tiles.length; x++) { for (int y = 0; y < tiles[x].length; x++) { renderTile(x, y, tiles[x][y], g); } } }
public static final int BLACK = 0; public static final int GRASS = 1; public static final int EARTH = 2;
public void renderTile(int x, int y, int tileID, Graphics g) { switch (tileID) { case BLACK: g.setColor(Color.black); g.drawRect(x * 32, y * 32, 32, 32); break; case GRASS: g.setColor(Color.green); g.drawRect(x * 32, y * 32, 32, 32); break; case EARTH: g.setColor(Color.brown); g.drawRect(x * 32, y * 32, 32, 32); break; } } |
And then it should work. It's important that you only load the tiles at the beginning! (only call once...) If you dlo that every time you want to render, you will waste lots of memory and it will be slow. Very slow. @Riven: Wuahaha  I like to abuse your wonderful icodes  I don't have line numbers anymore, but it's just so beautiful now 
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #14 - Posted
2012-12-28 20:39:08 » |
|
Ok here's my code: http://pastebin.java-gaming.org/fa43e1f6f31technically it should work, but all I'm getting is a blank screen? Any suggestions. And thanks matheus for continually helping me  I appreciate it I'm getting these errors and I don't know why: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| java.io.IOException: Stream closed at java.io.BufferedInputStream.getBufIfOpen(Unknown Source) at java.io.BufferedInputStream.read(Unknown Source) at sun.nio.cs.StreamDecoder.readBytes(Unknown Source) at sun.nio.cs.StreamDecoder.implRead(Unknown Source) at sun.nio.cs.StreamDecoder.read(Unknown Source) at java.io.InputStreamReader.read(Unknown Source) at java.io.BufferedReader.fill(Unknown Source) at java.io.BufferedReader.readLine(Unknown Source) at java.io.BufferedReader.readLine(Unknown Source) at com.epacgames.games.redxog.Game.getIntsFromTextFile(Game.java:185) at com.epacgames.games.redxog.Game.<init>(Game.java:70) at com.epacgames.games.redxog.Game.main(Game.java:161) Exception in thread "Thread-2" java.lang.NullPointerException at com.epacgames.games.redxog.Game.renderTiles(Game.java:145) at com.epacgames.games.redxog.Game.render(Game.java:140) at com.epacgames.games.redxog.Game.render(Game.java:123) at com.epacgames.games.redxog.Game.run(Game.java:99) at java.lang.Thread.run(Unknown Source) |
this is extremely frustrating  @Phibedy, if all else fails then i'll try that 
|
|
|
|
|
HeroesGraveDev
|
 |
«
Reply #15 - Posted
2012-12-28 22:09:10 » |
|
This: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public Game(){ try { createTiles(getIntsFromTextFile(level1)); } catch (IOException e) { e.printStackTrace(); } try { tiles = getIntsFromTextFile(level1); } catch (IOException e) { e.printStackTrace(); } } |
is your problem. In your method you close the stream at the end (like you should), which means that when you try to use that stream the second time, it is closed and throws the . Then the array is never created and causes the method to throw a . To fix:Remove this part: 1 2 3 4 5 6
| try { createTiles(getIntsFromTextFile(level1)); } catch (IOException e) { e.printStackTrace(); } |
That should fix things. EDIT: it seems matheus23 beat me to it.
|
|
|
|
matheus23
|
 |
«
Reply #16 - Posted
2012-12-28 22:43:24 » |
|
Yup. Do what HeroesGraveDev showed. You have to replace the code, it wasn't meant to be added  EDIT: it seems matheus23 beat me to it.
Huh?
|
|
|
|
HeroesGraveDev
|
 |
«
Reply #17 - Posted
2012-12-28 22:47:18 » |
|
EDIT: it seems matheus23 beat me to it.
Huh? This: ... It's important that you only load the tiles at the beginning! (only call once...) EDIT: It appears you said that for performance reasons, not the stream closing and throwing the exception. 
|
|
|
|
matheus23
|
 |
«
Reply #18 - Posted
2012-12-28 22:52:19 » |
|
EDIT: It appears you said that for performance reasons, not the stream closing and throwing the exception.  Yep. You're right  I didn't see it like that  InputStreams generally shouldn't be stored as fields, but requested everytime you need one. Otherwise you "abuse" them just like that.
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #19 - Posted
2012-12-29 00:45:25 » |
|
Ok, that has definitely worked! it has removed the IOException and the NullPointerException, however now it gives me a: 1 2 3 4 5 6
| Exception in thread "Thread-2" java.lang.ArrayIndexOutOfBoundsException: 2 at com.epacgames.games.redxog.Game.renderTiles(Game.java:139) at com.epacgames.games.redxog.Game.render(Game.java:133) at com.epacgames.games.redxog.Game.render(Game.java:116) at com.epacgames.games.redxog.Game.run(Game.java:92) at java.lang.Thread.run(Unknown Source) |
and i've tried to find what a ArrayIndexOutOfBoundsException is to try and tackle the problem, but i cant find it. Again, Google hs failed me  as you can probably see I'm new to game programming in java but I must say i appreciate your help 
|
|
|
|
|
HeroesGraveDev
|
 |
«
Reply #20 - Posted
2012-12-29 00:51:55 » |
|
It's when tou try to access a part of an array that is outside the limits. Either less than zero, or more than the size of the array will give this. I found the mistake: 1 2 3 4 5 6 7
| for(int x = 0; x tiles.length; x++) { for(int y = 0; y < tiles[x].length; x++) { } } |
Notice how you increment x in the y loop. There is the problem.
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #21 - Posted
2012-12-29 00:56:10 » |
|
OMG! I can't believe I missed that, Thanks a ton, HeroesGraveDev
|
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #22 - Posted
2012-12-29 01:04:02 » |
|
it works! success! Thank you all so much, its flipped to one side, i've tried iterating the y first and then x but that doesn't seem to work neither does swapping the to . i could work around it, but if others come looking for help with the same problem then it would probably be better to show them the complete code. thanks everyone for the help!
|
|
|
|
|
_Scyth_
Senior Newbie 
|
 |
«
Reply #23 - Posted
2012-12-29 01:35:43 » |
|
Ignore the last post, I fixed it! 1 2 3 4 5 6 7 8
| public void renderTiles(Graphics2D g) { for (int y = 0; y < tiles.length; y++) { for (int x = 0; x < tiles[y].length; x++) { renderTile(x, y, tiles[y][x], g); } } } |
Thanks to matheus, HeroesGraveDev, Phibedy and SHC, i'll edit the first post to show others what needs to be done for this tiling! Thanks again ~Scyth
|
|
|
|
|
|