Jump to content

  • Log In with Google      Sign In   
  • Create Account

Rogue-like tile system display question


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 EpicWally   Members   -  Reputation: 282

Like
0Likes
Like

Posted 31 October 2012 - 07:34 PM

So I'm working on a roguelike, and I have a question about drawing the map and all the entities and items that reside on it. The way I have it programmed at the moment, is the board is a 2 dimensional array of tiles. Each Tile has its own char to represent it, and contains an Entity member. This way, when the draw method is called, each tile spits back either its own icon, or if it has an Entity, the Icon belonging to the entity. These chars are all concatenated into the string that is eventually thrown to the display. Needless to say, this works, though I'm not certain it's the best way to do it. 1.) From a coupling perspective, there's really no reason a tile should know the entity that is on top of it. and 2.) now for every tile, the if(Entity != null) is being checked to determine what char to display. When 99% of the tiles are empty, this seems like an unnecessary check. I don't imagine this is serious overhead, but it still doesn't feel clean to me.

All that said, I've been stewing on alternatives, and none of them sounds particularly appealing either. These are what I've come up with:

1.) Have a graphics manager class with a Board reference, and a list or hashmap of Entities. Then, for every x/y on the display, it checks to see if an entity resides there from the list/map, if so displays it, else displays the tile's icon. This just seems hideous to me, to have to iteratively go through a list for every tile? Though I suppose I could have Entity implement comparable, and make the natural sorting order go left to right, top to bottom, so that only the next entity in the list is being checked vs the coordinates you're drawing at. Still feels heavy...

2.) Same design as above, graphics manager with board and entity references. This time, take the board, and convert it to a char[][] array. Then go through the entity list, replacing the elements of that array with the entities icons. Finally convert the char[][] to a string and display it. This avoids a lot of the iteration problems that are encountered above, but it requires instantiating a temporary array, filling it, and then converting that array back to a string, which all of these steps are iterative in and of themselves, so this doesn't seem like it would end up saving anything.

I would love to be able to simply replace char at index in a string, but I haven't found that such a method exists. (Even if it does, are the underlying mechanics similarly iterative, so would it even save anything over the options described above?)

Either I'm over-thinking this, and one of the above approaches is fine/the best way to do it, or there's some other method that I am missing.

Thoughts and suggestions? Thank you in advance!

-Wally

Sponsor:

#2 EpicWally   Members   -  Reputation: 282

Like
1Likes
Like

Posted 02 November 2012 - 02:28 PM

I hate doing this, but bump? Anyone got thoughts on this one?

#3 SharkBaitHooHaHa   Members   -  Reputation: 271

Like
1Likes
Like

Posted 03 November 2012 - 06:00 PM

Hey! I'm not sure how much I can help here, but I know it's frustrating to not have anyone answer your questions so I'll do my best here. I'm also working on a Roguelike in Java so I'm in the same boat as you. I just have some questions to see if I can better help you.

1. Are you using any external libraries for your game?
2. Due to the wording, I wasn't entirely sure how you were handling your display. Are you going text based, graphic based, or hybrid?
3. What is the structure of your game?(Dungeon has Floors, Floors have Rooms, Rooms have.....etc)

Seeing as I can't contribute much until I know more about your game I'll assume that you have randomly generated one big map(or Floor) of interconnected Rooms. So in the class where you take care of the generation you populate the map with its respective tiles. Then you have an entity class that is randomly spawned on to the map. I agree with you when you say that the tile should not have to know which Entity it has on it, however each "Floor", if you will, should know all of its contents. Not necessarily all of the specifics of it, but it should know what it has. The way I see it(and again I am only assuming here) you're taking care of generating the map and then adding on the Entities, but shouldn't you just spawn each floor already knowing how many entities, items, and whatnot it should have and their locations?

That way you go like this

New Floor
+4 Monsters
-Bugbear(10,43)
-Harpie(20,16)
-Mimic(50,50)
-Kobold(3,32)
+2Items
-Greater Potion of Vitality(12,12)
-Lesser Potion of Mana(48,34)

Then inside of your code all you have to do is put in an order of precedence of what is displayed.
if(there's an item OR there's a monster)
{
Draw the item/monster
}
else
{
Draw the tile
}

This way you still have the tile there although it's not being drawn, allowing you to use its modifiers(ex.sludge tile slows your character if he's not a Ranger)

Also pertaining to the replacing char question, have you considered using a StringBuilder? Seeing as you mentioned overhead I'm assuming you're worried about performance(I'm making a lot of assumptions). String concatenation is far less efficient performance-wise than using a StringBuilder. Hopefully I've been able to help somewhat with my reply, and if not I at least hope I can keep your post up in vision for other people to give it a shot; hopefully people with a better understanding than me.

I'll do my best to work this out with you though :] in the meantime I'll be working on my RL on and off today so I'll be at the computer.

Best of luck!
-Adrian

P.S To mods or whoever comes by, if I flubbed on anything please correct me, I don't like giving misinformation, be it unintentional or not.

#4 EpicWally   Members   -  Reputation: 282

Like
0Likes
Like

Posted 04 November 2012 - 11:59 AM

Adrian,

Thank you for your response! In answer to your list of questions:

1.) No, no external libraries. I'm seeing what I can do entirely of my own efforts.
2.) I am doing text based. Not wanting to use the console, I am using a JTextPane to display the text of the game.
3.) I haven't even gotten that far yet, truthfully. At the moment, I am simply trying to figure out the best way to draw ____, be it a room, floor, etc. We'll just call it a map for the time-being. Once I get that figured out, I can get the overarching structure set for rooms/floors/dungeons, etc.

I agree with the rough structure and pseudo-code you posted, but I guess my big question is how to address that IF section at the front of it, and I guess equally importantly, how the map tracks the entities inside it, be it a list, or map, or what have you. My problem with the approach you outlined is in essence you are doing the following (or at least this is how I foresee implementing it, if you have a better alternative, I guess that is exactly what I'm looking for.)

for(i =0; i < map.height; i++{
for(j=0; j< map.width, j++{
**if(collection contains entity at (j,i)**
draw(entity)
else
draw(tile)

How do you implement this line without checking every entity on the map, for every tile on the map? If you have a 10x10 map, with 5 entities on it, you'll be making 500 different conditional checks, as the way I'm seeing it now, you'll have to iterate across your whole entity collection for every tile.

...Unless you were to keep entities in an array, rather than a list... That would give 2 arrays, one of tiles, and one of entities... the Entities array being null everywhere that there isn't an entity... then in the loop above you could have something like:

if(entities[j][i] != null
draw entities[j][i]
else
draw tiles[j][i]

This seems like it avoids basically all the iterative problems I was worried about, though I don't know much on the overhead of an array vs. that of a list. What are your thoughts on this approach, and how do you store entities in the one you are working on?

To your later comment, yes, I am worried about performance, not so much because of it's effect on this game that I'm programming now, but mostly to learn the most efficient structures for later in my programming career, when such things might matter more. I'd like to learn best practices from the get-go, rather than possibly get into bad habits. Also, thanks for the tip on using a StringBuilder, I will definitely look into this.

Thanks again for your response!
-Wally

#5 Lauris Kaplinski   Members   -  Reputation: 841

Like
2Likes
Like

Posted 04 November 2012 - 02:32 PM

So I'm working on a roguelike, and I have a question about drawing the map and all the entities and items that reside on it. The way I have it programmed at the moment, is the board is a 2 dimensional array of tiles. Each Tile has its own char to represent it, and contains an Entity member. This way, when the draw method is called, each tile spits back either its own icon, or if it has an Entity, the Icon belonging to the entity. These chars are all concatenated into the string that is eventually thrown to the display.


You are not actually appending data to string for each tile are you? This is probably quite slow operation...

I would love to be able to simply replace char at index in a string, but I haven't found that such a method exists. (Even if it does, are the underlying mechanics similarly iterative, so would it even save anything over the options described above?)


I suggest storing everything in byte[] array and building string to be displayed in one step later. You can reuse your array between display events, thus avoidng allocation and GC. And building string in one go should be A LOT faster than appending to it constantly (appending involves probably many reallocations).
Then you can iterate over tiles, set all icons in byte array, then iterate over entities and replace icons at their locations.
Lauris Kaplinski

First technology demo of my game Shinya is out: http://lauris.kaplinski.com/shinya
Khayyam 3D - a freeware poser and scene builder application: http://khayyam.kaplinski.com/

#6 SharkBaitHooHaHa   Members   -  Reputation: 271

Like
0Likes
Like

Posted 04 November 2012 - 07:54 PM

Hmmm..... I don't really know. Lemme tell you how I'm implementing mine to see if it might spark some thoughts for you.

My hierarchy is Dungeon>Floor>Rooms.
I create a Dungeon with a random number of Floors, the Dungeon then generates each of those Floors with a random number of Rooms. Floor keeps an array of Rooms stored and as it generates each Room, it provides a random number of monsters, items, and other things that it will contain.The way I'm representing my game is a hybrid. I have the console in the background since I'm still developing and I like seeing the information of what a Room is supposed to have amongst other things. I have a JPanel displaying buttons allowing the player to move forward,backward,left,and right to other rooms(should they exist). The Panel only displays one Room at a time. The granularity of Player movement is defined as one Room per move(I'm keeping it simple for now, later on the Player will actually be able to move inside of a Room once I get better at procedural generation).

So that's the gist of my game. The way I have it set up, each Room takes care of drawing it's own things. You want to actually implement Tiles, so your player movement has a far higher granularity than mine as it stands currently.

If I were to implement tiles inside of my Room so that the player could move around the Room and there would be items and monsters on the floor I think the way I would do it is just draw the entities. Have all the tiles draw themselves, and then loop through and draw the items or monsters. I don't think I would spawn items and monsters on the same tile, so I don't have to worry about that, since I would prevent that from happening in the code. The way you draw them though, monsters and items will always be drawn on top of the tiles. It doesn't matter what was there previously as it will be overwritten. Of course you have to prevent things from being drawn inside of walls, but you could take care of that in code restrictions.

Instead of having that character array that you send you would append characters to, wouldn't it be easier to have a 2D array of Room object that contains it's entities? That way you would have a more intuitive representation of your entities, and be able to manipulate them easier.

I'll come back later to see if I can help you out some more. Have you done any UML diagramming?

#7 EpicWally   Members   -  Reputation: 282

Like
0Likes
Like

Posted 05 November 2012 - 09:35 AM

Thanks again for the tips! I have changed the structure such that now the map contains 2 arrays, one of tiles, and one of entities. I have also replaced the looped string concatenation with a stringBuilder. Doing some reading, java inherently uses a stringbuilder when you need to concatenate strings, but in doing so in a loop it is creating a new stringbuilder for every loop, which is just ridiculous, so I now create one before the loop, and return its tostring after, yielding a significant optimization. I like the idea of the byte array. Saving the finished state of the board construction such that if nothing changes in a game loop, it doesn't have to completely reconstruct the board. Seems like a smart idea, I will have to play around with this.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS