Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (516)
Games in Android Showcase (122)
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  
  Fast way of rendering Tiles.  (Read 733 times)
0 Members and 1 Guest are viewing this topic.
Offline roseslayer

Junior Duke


Medals: 2



« Posted 2013-09-26 15:54:16 »

Hello there again JGO,

Currently I am working on an infinite map-generator, or atleast trying to. But evrytime I want to test/try something it will take a BIG, I mean a very BIG part of the CPU :/. I am without my code running on 60 ticks, 200 frames, but with the infinite Tile-rendering codes it is going to be 60ticks, 39frames (And this is with almost no tiles, around 200, while I was running the old code 50*50 tiles = 2500tiles..) My rendering code is just a simple arrayList with some if's and looping throught all the tiles :/ not the greates.. while my other code was just searching for that tile and not looping over the arrayList like 1000times more then is needed...

1  
2  
3  
4  
5  
6  
7  
       for (LevelTile t : tiles) {
           if(t.y >=  (yOffset >> 3) && t.y  <= (yOffset + screen.height >> 3) + 1){
              if(t.x >= (xOffset >> 3) && t.x <=  (xOffset + screen.width >> 3) + 1){
                 t.render(screen, this);
              }
           }
       }


Is there a way for searching x's and y's better then this? Like:
1  
2  
3  
4  
5  
       for (int y = (yOffset >> 3); y < (yOffset + screen.height >> 3) + 1; y++) {
           for (int x = (xOffset >> 3); x < (xOffset + screen.width >> 3) + 1; y++) {
              //Searching in the ArrayList tiles to x and y and then just .render(); it
           }
       }


Is the example possible? Or another solution? Just say it!
-RoseSlayer, and yes I didn't found anthing on java.docs

Fundamentum W.I.P.
Offline Gjallar

JGO Coder


Medals: 13
Projects: 1


Follower of Nurgle


« Reply #1 - Posted 2013-09-26 16:28:59 »

If you are doing tile-based rendering I would suggest using an Array instead of an ArrayList. That way you can access the tiles via an index and do not have to loop through every single one of them, Just the ones that are currently visible on the screen.
Offline drabla

Junior Duke


Medals: 5



« Reply #2 - Posted 2013-09-26 16:54:53 »

I suggest while you are working on the map generator you immediately set it up to seperate your map into chunks/rooms.

1  
2  
Chunk[][] chunks; // Your World / Level / Map
Tile[][] tiles; // One Room/Chunk of the Map


First you would need to check in which chunk you are:
1  
int currentChunkLeftX = (int) playerPositionInWorld / MAP.CHUNK_WIDTH // Do this for all 4 edges of your camera. You might be in 2 chunks at the same time. 


For each chunk you are in you calculate the 4 edges again (yTop, yBottom, xLeft, xRight) and only render the part visible for the user
1  
2  
3  
4  
5  
6  
7  
foreach chunk you are in do:
    for(int x = leftEdgeX - 1; x < rightEdgeX + 1; x++{
        for(int y = bottomEdgeY; y < topEdgeY; y++ {
           tiles[x][y].render();
        }
    }
}


As Gjallar stated this will save you a lot of computation time  ( O(n) versus O(x) where x = numberOfVisibleTilesToRender)
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Danny02
« Reply #3 - Posted 2013-09-26 16:55:39 »

The simple answer is to store the tiles in a data structure which enables you to query specific regions.

If you have a static World(fixed size) you could store the tiles in an array like Gjallar suggests. While rendering you could calculate the array indices which hold tiles which are in view.

In your case it seems that you have a dynamic world, means you stream the world content in some way. My suggestion would be to load the world into chunks which are hold in a simple data structure like an array. So for example you could have always nine chunks in memory, where the chunks are located like this:

x x x
x v x
x x x

When the view moves out of the center chunk deallocate the more far away chunks and load new chunks which are in the direction of where the view is going. With this system you only iterate over all active chunks and for each chunk you can quickly access the needed tiles.

 ->
d x x a
d v v a
d x x a

Offline roseslayer

Junior Duke


Medals: 2



« Reply #4 - Posted 2013-09-26 17:41:07 »

I tried to make Chunks with fixed Tile Arrays, and so far so good. I've added alot of code that should work fine etc. but I can't seem to make this part correct (if the chunk excist and must be loaded):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
boolean loaded = false;
      try {
         FileInputStream loadFile = new FileInputStream(levelDirectory + "/chunks/chunk[" + x + "," + y + "].dat");
         ObjectInputStream load = new ObjectInputStream(loadFile);
         this.tiles = (LevelTile[][]) load.readObject();
         load.close();
         loaded = true;
      } catch (Exception e) {
         e.printStackTrace();
      }
      if(!loaded)
         generateChunk();


[edit]
It is now working correctly! The only thing I don't know how to do is creating a new chunk if he is not in the ChunksList.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
        if(currentViewedChunkX != viewedChunkX || currentViewedChunkY != viewedChunkY){
           chunksOpen.clear();
           for(Chunks c: chunksList){
              if(c.x >= currentViewedChunkX - 1 && c.x <= currentViewedChunkX + 1){
                  if(c.y >= currentViewedChunkY - 1 && c.y <= currentViewedChunkY + 1){
                     chunksOpen.add(c); //So if this one doesn't excist it needs to create a new Chunk, but because it is a forloop the not-excisted coords won't come here....
                  }
              }
           }
           viewedChunkX = currentViewedChunkX;
           viewedChunkY = currentViewedChunkY;
        }


[edit]
Found a simple solution that doesn't seems to work:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
for(int x = cx - 1; x <= cx + 1; x++){
           for(int y = cy - 1; y <= cy + 1; y++){
              boolean opened = false;
              for(Chunks c : chunksOpen){
                 if(c.x == x && c.y == y){
                    opened = true;
                    break;
                 }
              }
              if(!opened)
                 createChunk(x, y);
           }
       }

It is drawing more then 9 at the time, don't know how that is even possible but yeah....
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
       System.out.println(chunksOpen.size());
        screen.setOffset(xOffset, yOffset);
        int currentViewedChunkX = (((screen.xOffset + 4 + screen.width/2)>>3)>>4);
        int currentViewedChunkY = (((screen.yOffset + 4 + screen.height/2)>>3)>>4);
        if(currentViewedChunkX != viewedChunkX || currentViewedChunkY != viewedChunkY){
           chunksOpen.clear();
           for(Chunks c: chunksList){
              if(c.x >= currentViewedChunkX - 1 && c.x <= currentViewedChunkX + 1){
                  if(c.y >= currentViewedChunkY - 1 && c.y <= currentViewedChunkY + 1){
                     chunksOpen.add(c);
                  }
              }
           }
           if(chunksOpen.size() != 9)
              generateNewChunks(currentViewedChunkX, currentViewedChunkY);
           viewedChunkX = currentViewedChunkX;
           viewedChunkY = currentViewedChunkY;
        }
       
        for(Chunks c: chunksOpen){
           c.render(screen);
        }


[edit]
The only thing I needed to do was after creating new chunks, adding them to the chunksOpen ArrayList.... Thanks for all the help!

-RoseSlayer

Fundamentum W.I.P.
Offline opiop65

JGO Kernel


Medals: 156
Projects: 7
Exp: 3 years


JumpButton Studios


« Reply #5 - Posted 2013-09-27 02:47:42 »

I dont quite understand your problem. When you scroll and need a new chunk, look up your chunks that you stored in a file and load them from there, and if no chunk exists in the file, create a new chunk, fill it, add it to the open list and then hen it disappears off the screen, remove it from the list and write it to your hard drive.

Offline SHC
« Reply #6 - Posted 2013-09-27 03:51:22 »

What about using a Grid for tiles?

1  
2  
Grid tiles = new Grid(TILE_SIZE * numTilesX, TILE_SIZE * numTilesY, TILE_SIZE);
tiles.insert(tilesList);

And to get the tiles visible, you need a screen rectangle.

1  
Rectangle SCREEN = new Rectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

You need to update this rectangle every time the view changes. So when updating,

1  
2  
SCREEN.x = -offSetX;
SCREEN.y = -offSetY;

Now draw everything which are likely to be collided with the screen rectangle.

1  
2  
3  
4  
5  
6  
List<Tile> visible = tiles.retrieve(SCREEN);

for (Tile t: visible)
{
    t.render();
}

This is what I use. Hope it helps.

Offline roseslayer

Junior Duke


Medals: 2



« Reply #7 - Posted 2013-09-28 06:52:18 »

I dont quite understand your problem. When you scroll and need a new chunk, look up your chunks that you stored in a file and load them from there, and if no chunk exists in the file, create a new chunk, fill it, add it to the open list and then hen it disappears off the screen, remove it from the list and write it to your hard drive.

But if there are entities outside a chunk, that I want to use all have the methode tick() in them. And if I don't render that Chunk it will not "tick" correctly as there is nothing out there... Do I need to open that chunks aswell? and if I have a minimap, it needs to find also the chunks outside the rendered chunks?
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
    public Tile getTile(int x, int y) {
       int chunkX = x >> 4;
       int chunkY = y >> 4;
       for(Chunks c : chunksOpen)
          if(c.x == chunkX && c.y == chunkY)
             return c.getTile(x - chunkX*16, y - chunkY*16);
       for(Chunks c : chunksList)
          if(c.x == chunkX && c.y == chunkY)
             return c.getTile(x - chunkX*16, y - chunkY*16);
       return Tile.VOID;
    }


What about using a Grid for tiles?
That's a very good idea! I honestly forgot about grids (I thaught grids are also fixes size?). and using a rectangle is a good idea, but I think I prefer the forloop to do it.. I also don't know what is faster.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
public void render(Screen screen){
       for(int y = 0; y < 16; y++){
          if(y + this.y * 16 >= (screen.yOffset >> 3) && y + this.y * 16 <= (screen.yOffset + screen.height >> 3) + 1){
              for(int x = 0; x < 16; x++){
                 if(x + this.x * 16 >= (screen.xOffset >> 3) && x + this.x * 16 <= (screen.xOffset + screen.width >> 3) + 1){
                     tiles[x][y].render(screen, level);
                 }
              }
          }      
       }
    }



Thanks for all the help!
-RoseSlayer

Fundamentum W.I.P.
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.

TehJavaDev (31 views)
2014-10-27 03:28:38

TehJavaDev (26 views)
2014-10-27 03:27:51

DarkCart (41 views)
2014-10-26 19:37:11

Luminem (21 views)
2014-10-26 10:17:50

Luminem (26 views)
2014-10-26 10:14:04

theagentd (33 views)
2014-10-25 15:46:29

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

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

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

lcass (43 views)
2014-10-15 16:18:58
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!