Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (120)
games submitted by our members
Games in WIP (577)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [Solved] Tiling in Java  (Read 2367 times)
0 Members and 1 Guest are viewing this topic.
Offline _Scyth_

Junior Duke





« Posted 2012-12-28 13: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()
{
// Reads the text file
try {
      tiles = getIntsFromTextFile(level1);
   } catch (IOException e) {
      // TODO Auto-generated catch block
      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) {
      // Iterate through all tiles:
      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) {
         // don't forget the breaks! :)
         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 {
      // Create a list of rows. It needs to be resizable, because
      // we don't know the number of rows the text file has in the
      // beginning.
      ArrayList<int[]> yList = new ArrayList<int[]>();
      // A bit try-finally stuff, so we can close the reader properly.
      BufferedReader reader = null;
      try {
         // We create a BufferedReader by putting InputStreamReader-
         // glue between the Reader and the FileInputStream.
         reader = new BufferedReader(new InputStreamReader(input));
         
         // This variable counts the y rows.
         int y = 0;
         // This variable will hold every newly read line
         String line = null;
         // This reads a line and puts it into "line".
         // line is then tested against null, because when
         // the line is null, then we reached the end of the
         // file.
         while ((line = reader.readLine()) != null) {
            // We parse the string into a int[] and put it
            // into the list of rows.
            yList.add(parseString(line));
         }
      } finally {
         // "finally" we close the reader ;)
         if (reader != null) {
            reader.close();
         }
      }
      // This now creates an int[][] out of the ArrayList<int[]>.
      // This can be done, since we know the number of rows
      // now. You can see ArrayList's as a resizable array.
      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) {
      // We can create a int[], since we know
      // the length of the incoming string,
      // which is for example: "00192773716749".
      int[] array = new int[str.length()];
     
      // We loop through each character in the string
      // and create an integer from the returned char
      // with Integer.parseInt(...);
      for (int i = 0; i < str.length(); i++) {
         char c = str.charAt(i);
         // I say "" + c to create a string
         // out of the char. I'm not sure if
         // it's needed. You could try it without.
         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) {
         // don't forget the breaks! :)
         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;
         }
      }
Offline gouessej
« Reply #1 - Posted 2012-12-28 13:27:04 »

Tiling is implemented in LibGDX, isn't it? What do you mean by tiling a map?

Offline _Scyth_

Junior Duke





« Reply #2 - Posted 2012-12-28 13: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!
Legends of Yore - The Casual Retro Roguelike
Offline matheus23

JGO Kernel


Medals: 109
Projects: 3


You think about my Avatar right now!


« Reply #3 - Posted 2012-12-28 13: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 {
   // Create a list of rows. It needs to be resizable, because
   // we don't know the number of rows the text file has in the
   // beginning.
   ArrayList<int[]> yList = new ArrayList<int[]>();
   // A bit try-finally stuff, so we can close the reader properly.
   BufferedReader reader = null;
   try {
      // We create a BufferedReader by putting InputStreamReader-
      // glue between the Reader and the FileInputStream.
      reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
     
      // This variable counts the y rows.
      int y = 0;
      // This variable will hold every newly read line
      String line = null;
      // This reads a line and puts it into "line".
      // line is then tested against null, because when
      // the line is null, then we reached the end of the
      // file.
      while ((line = reader.readLine()) != null) {
         // We parse the string into a int[] and put it
         // into the list of rows.
         yList.add(parseString(line));
      }
   } finally {
      // "finally" we close the reader ;)
      if (reader != null) {
         reader.close();
      }
   }
   // This now creates an int[][] out of the ArrayList<int[]>.
   // This can be done, since we know the number of rows
   // now. You can see ArrayList's as a resizable array.
   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) {
   // We can create a int[], since we know
   // the length of the incoming string,
   // which is for example: "00192773716749".
   int[] array = new int[str.length()];
   
   // We loop through each character in the string
   // and create an integer from the returned char
   // with Integer.parseInt(...);
   for (int i = 0; i < str.length(); i++) {
      char c = str.charAt(i);
      // I say "" + c to create a string
      // out of the char. I'm not sure if
      // it's needed. You could try it without.
      array[i] = Integer.parseInt("" + c);
   }
}

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline matheus23

JGO Kernel


Medals: 109
Projects: 3


You think about my Avatar right now!


« Reply #4 - Posted 2012-12-28 13:53:09 »

Mind the edit.

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline _Scyth_

Junior Duke





« Reply #5 - Posted 2012-12-28 13:57:54 »

thanks for commenting! didnt understand the last few parts of it! Thanks so much!
Online SHC
« Reply #6 - Posted 2012-12-28 14: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){
        // Error. exit. Should not happen
        e.printStackTrace();
        System.exit(-1);
    }
}

Offline _Scyth_

Junior Duke





« Reply #7 - Posted 2012-12-28 14: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"?
Offline matheus23

JGO Kernel


Medals: 109
Projects: 3


You think about my Avatar right now!


« Reply #8 - Posted 2012-12-28 14: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); // <- You have to create this method. I have no Idea about your codebase :)
      }
   }
}

Mind that I first iterate throught y (
for (int y = ...)
) and then through x (
for (int x = 0; x ...)
). This is needed, or else your map in the file will be rotated by 90° Wink
(Or probably not... if so, try swapping those variables Cheesy )

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline _Scyth_

Junior Duke





« Reply #9 - Posted 2012-12-28 14: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!
Legends of Yore - The Casual Retro Roguelike
Online SHC
« Reply #10 - Posted 2012-12-28 14: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.

Offline _Scyth_

Junior Duke





« Reply #11 - Posted 2012-12-28 15:05:40 »

EDIT : Too much code Tongue removed it
Offline Phibedy

Senior Duke


Medals: 9



« Reply #12 - Posted 2012-12-28 15: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
Offline matheus23

JGO Kernel


Medals: 109
Projects: 3


You think about my Avatar right now!


« Reply #13 - Posted 2012-12-28 15:24:02 »

Oh yes. I see Smiley

Better use our pastebin for such big codes. Just remember that for the next time Smiley
(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
Game
class to take another field:
int[][] tiles;


Then, when initializing (in the constructor) you load the text file into your tiles array:
// catch IOException here
tiles = getIntsFromTextFile(level1);


And now you have a wonderful
int[][] tiles
-array you can use to draw your tiles.

You can do this in the
render(Graphics)
method:
public void render(Graphics g) {
   renderTiles(g);
}

public void renderTiles(Graphics g) {
   // Iterate through all tiles:
   for (int x = 0; x < tiles.length; x++) {
      for (int y = 0; y < tiles[x].length; x++) {
         renderTile(x, y, tiles[x][y], g);
      }
   }
}

// These belong to the top of your class file :)
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) {
   // don't forget the breaks! :)
   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
getIntsFromTextFile
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 Cheesy I like to abuse your wonderful icodes Smiley I don't have line numbers anymore, but it's just so beautiful now Tongue

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline _Scyth_

Junior Duke





« Reply #14 - Posted 2012-12-28 19:39:08 »

Ok here's my code:
http://pastebin.java-gaming.org/fa43e1f6f31

technically it should work, but all I'm getting is a blank screen? Any suggestions. And thanks matheus for continually helping me  Smiley 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 Tongue
@Phibedy, if all else fails then i'll try that Sad
Offline HeroesGraveDev

JGO Kernel


Medals: 269
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #15 - Posted 2012-12-28 21:09:10 »

This:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
public Game(){
      // removed Java2D setup stuff
      try {
          createTiles(getIntsFromTextFile(level1));
       } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
       }
     
      try {
      tiles = getIntsFromTextFile(level1);
   } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   }
     
   }


is your problem.

In your
getIntsFromtextFile()
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
IOException
. Then the
tiles[][]
array is never created and causes the
render()
method to throw a
NullPointerException
.

To fix:

Remove this part:

1  
2  
3  
4  
5  
6  
try {
          createTiles(getIntsFromTextFile(level1));
       } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
       }


That should fix things.

EDIT: it seems matheus23 beat me to it.

Offline matheus23

JGO Kernel


Medals: 109
Projects: 3


You think about my Avatar right now!


« Reply #16 - Posted 2012-12-28 21:43:24 »

Yup. Do what HeroesGraveDev showed. You have to replace the code, it wasn't meant to be added Smiley

EDIT: it seems matheus23 beat me to it.

Huh?

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline HeroesGraveDev

JGO Kernel


Medals: 269
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #17 - Posted 2012-12-28 21:47:18 »


This:

...
It's important that you only load the tiles at the beginning! (only call
getIntsFromTextFile
once...)

EDIT: It appears you said that for performance reasons, not the stream closing and throwing the exception.  Pointing

Offline matheus23

JGO Kernel


Medals: 109
Projects: 3


You think about my Avatar right now!


« Reply #18 - Posted 2012-12-28 21:52:19 »

EDIT: It appears you said that for performance reasons, not the stream closing and throwing the exception.  Pointing

Yep. You're right Cheesy I didn't see it like that Smiley
InputStreams generally shouldn't be stored as fields, but requested everytime you need one.
Otherwise you "abuse" them just like that.

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline _Scyth_

Junior Duke





« Reply #19 - Posted 2012-12-28 23: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 Sad

Tongue

as you can probably see I'm new to game programming in java but I must say i appreciate your help Smiley
Offline HeroesGraveDev

JGO Kernel


Medals: 269
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #20 - Posted 2012-12-28 23: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++)
    {
    // rendering code
    }
}


Notice how you increment x in the y loop. There is the problem.

Offline _Scyth_

Junior Duke





« Reply #21 - Posted 2012-12-28 23:56:10 »

OMG! I can't believe I missed that, Thanks a ton, HeroesGraveDev
Offline _Scyth_

Junior Duke





« Reply #22 - Posted 2012-12-29 00: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
1  
tiles[x][y]
to
1  
tiles[y][x]
.

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!
Offline _Scyth_

Junior Duke





« Reply #23 - Posted 2012-12-29 00:35:43 »

Ignore the last post, I fixed it!
1  
2  
3  
4  
5  
6  
7  
8  
public void renderTiles(Graphics2D g) {
      // Iterate through all tiles:
      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
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (52 views)
2014-10-17 03:59:02

Norakomi (43 views)
2014-10-16 15:22:06

Norakomi (33 views)
2014-10-16 15:20:20

lcass (37 views)
2014-10-15 16:18:58

TehJavaDev (68 views)
2014-10-14 00:39:48

TehJavaDev (66 views)
2014-10-14 00:35:47

TehJavaDev (59 views)
2014-10-14 00:32:37

BurntPizza (73 views)
2014-10-11 23:24:42

BurntPizza (45 views)
2014-10-11 23:10:45

BurntPizza (86 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!