IntMaps creating junk
Monkey Forums/Monkey Programming/IntMaps creating junk
| ||
I've noticed that through XNA and Android, iterating through an IntMap causes a lot of junk. (I will say though, this is literally the only thing that causes junk when I run my game through XNA, which is pretty damn impressive :)For Local t:Int = EachIn ThisMap.Keys() ThisMap.Get(t).Draw(X,Y) Next Am I right in thinking that I can't really use any list type structures without creating junk? Is a 1d array the only real alternative? |
| ||
You could change the iterator so that you can hold a reference and reset it rather than creating a new one every loop via the EachIn. |
| ||
Ahh so have a field in the parent class that is "ThisMap.Keys" (whatever type of object that is)? |
| ||
One level down. You'd hold onto a KeyEnumerator returned by ThisMap.Keys().ObjectEnumerator(). You also need to change the KeyEnumerator code so that you can reset it back to the start before using it to loop. The enumerator will have to hold a reference to the map so it can call FirstNode(). |
| ||
Got ya :) I'll give this a look when I get home thanks! |
| ||
would like to see your code once you figure it out if thats alright. |
| ||
I've been thinking about it actually, and as the list doesn't change its size or order at all during run time, I think I probably only need to use a simple 1d array (that I resize as required during initialisation). As long as no junk gets created during the game, I am not fussed :) I just chucked this together quickly to be used with my code when I get home. [monkeycode] Import mojo Class TestApp Extends App Field NMData:MapUnit[][] Method OnCreate() SetUpdateRate(5) NMData = New MapUnit[10][] For Local y:Int = 0 To 9 NMData[y] = New MapUnit[20] For Local x:Int = 0 To 19 NMData[y][x] = New MapUnit() ' Randomly create between 1 and 7 layers ' for this specific map tile Local Target:Int = Rnd(1,8) For Local i:Int = 0 To Target NMData[y][x].SetTile(i,i,i) Next Next Next End Method OnUpdate() End Method OnRender() Cls For Local y:Int = 0 To 9 For Local x:Int = 0 To 19 SetColor(64,64,64) DrawRect(x*16,y*16,15,15) SetColor(255,255,255) NMData[y][x].Draw(x * 16,y * 16) Next Next End End Function Main() New TestApp End Class MapUnit Field MapUnitTiles:MapUnitTile[] ' Is this tile an obstacle or not? Field IsObstacle:Bool ' The main type this tile is (grass/sand/tress) Field MainType:Int ' How many tiles are to be drawn for this Map unit? Field MUTCount:Int Method New() MapUnitTiles = New MapUnitTile[0] MUTCount = 0 MainType = -1 IsObstacle = False End Method SetTile:Void(tT:Int,tX:Int,tY:Int) Local length:Int = MapUnitTiles.Length() MapUnitTiles = MapUnitTiles.Resize(length + 1) MapUnitTiles[length] = New MapUnitTile(tX,tY) MUTCount = length + 1 If tT > MainType MainType = tT End End Method Draw:Void(X:Int,Y:Int) For Local i:Int = 0 Until MUTCount MapUnitTiles[i].Draw(X,Y) Next End End Class MapUnitTile ' Will be used to hold the draw locations on the sprite atlas Field DX:Int Field DY:Int Method New(tX:Int,tY:Int) DX = tX DY = tY End Method Draw:Void(X:Int,Y:Int) ' Pixel drawn with an offset to demonstrate multiple layers DrawRect(X+(DX * 2),Y,1,1) End End [/monkeycode] |
| ||
Keeping a local copy of the enumerator will make it impossible to nest for-each loops of the same map. I would not recommend it. Maybe a reusable stack for iterators would be much safer, but a bit more complex |
| ||
Just got it running and for what I am doing a 1D array is absolutely fine :) Glad it was a relatively simple solution. Have to admit though, I slightly shamed myself because I then thought I had to do some quite elaborate coding to reverse the order of said arrays to make sure items are drawn correctly..... before realising I could just go through the array backwards... :B Very happy to have absolutely no garbage being created which is very important for Xbox releases |
| ||
Yeah, Arrays seems to be the way to go to avoid garbage. You can of course create your own "List" that wraps the Array to get a more dynamic and robust "ArrayList". The Diddy Framework has some great collection classes worth checking out :) |
| ||
Oh pants, I forgot about the ArrayList of Diddy! I did notice that performance on Android improved when I stopped using IntMaps and assume this is because of the garbage being created. |
| ||
Keeping a local copy of the enumerator will make it impossible to nest for-each loops of the same map. Not at all. You just have another enumerator instance for the nested loop if you need it. |
| ||
You can also keep the IntMap for quick lookups and use the array for iterating. Recently I have thought about replacing Lists with Stacks because they use arrays internally. Also you don't have to use an enumerator because there is the Get(index) method and they resize dynamically. |
| ||
The enumerator for ArrayList lets you go back and forward and has a Reset method. You can call Remove to delete the last call to NextObject or PreviousObject, and it keeps track of the state of the list so that you don't get weird concurrency issues. |