Are Collections this slow?
VBBRI am developing VB Adventure Maker, as you know. In the current time I need to set a way to store the map data. I already decided it will be stored in a 2D grid style, but the question that is bugging me is: Which are better, Arrays or Collections? I know collections are slower, but they can be a lot more flexible. Arrays are fast but harder to deal with. So what do I use? Arrays? Collections? Or maybe should I create a map class myself that wrappers an array of data?
Eric ColemanYou should use an array for map data. A Collection is better for unorganized data, such as reading the settings from and .INI file where you have "Key = Value." The power of a collection is that you can read the file line by line and simply split the string at the first "=" sign and add them to your collection as a Key, Value pair. Once that is done your program can easily get information by reading settings by using the Key to get the Value. For example, Debug.Print MyCollection("HitPoints"), MyCollection("GoldInBank"). The order of the data in the INI doesn't matter in this case, which is really neat because you can easily manually edit the files without having to worry about the location of the data. For arrays, data order is important. If the first line of the INI file is HitPoints = 5, and the second line is GoldInBank = 450, then when searching for that information, you will either have to go through the entire array looking for the correct key, or you'll need to know the exact index of the data. Knowing the extact index is a lot faster than having to go through a loop each and every time you need get information from the array, so you would probably predefine a structure for the INI file that says the HitPoints value is always on the first line, and GoldInBank is always on the second line. This would allow you to define some constants in the program to help speed up data retrieval. Const GoldInBank = 2, Debug.Print MyArray(GoldInBank). Now, for a Map, the order is very important. When drawing tiles on the screen, you need to know the order in which to draw them. The easiest way is to index them into a 2D array. Instead of having a collection that looks like MyCollection("TileOne"), MyCollection("TileTwo"), you could use an array, MyArray(0,0), MyArray(1,0). If given a position on the map, you need to be able to get any surrounding tiles, and the easiest way is with a coordinate system, which is how Arrays work. If your character is on the tile MyMap(340, 240), then it's very easy to find surrounding tiles by drawing in different directions. For Y = (240-10) to (240+10) For X = (340-10) to (340+10) DrawTile X,Y Next Next
Almar JolingI do ahve to add that a collection of objects -when compiled- is quite fast. The difference between compiled and non compiled is, if I recall right quite huge :)
VBBRThanks, now I see. Arrays are the way to go then. I'm also creating a Map class that will handle everything and use arrays internally. (expect to see a small demo of the VB Adventure maker quite soon... I say, very small, but something at least... [:D])
DanYes, An array is the way forward because the dimensions of the map are known (Well they should be). It's important to remember that when declaring and array, it is possible to add additional dimensions. [code] Dim Map (50,50) as integer [/code] Would give you a grid 50 x 50 to add yout tile references, If you wanted to have a map with multiple layers you could have [code] Dim Map_Layer1 (50,50) as integer Dim Map_Layer2 (50,50) as integer Dim Map_Layer3 (50,50) as integer [/code] But a tidier way would simply be [code] Dim Map (50,50,3) as integer [/code] You could add some constants to describe the layers, or if your wrapping it all up as a class then an enumeration for the layer could be added. I'm sure you are already aware that the array should contain a pointer to a tile and not the tile it'self. Describing the array as integer over a long will almost half the amount of space required to store the array. And unless you need more than 32,767 tiles is more than adequete. The use of the Redim within your game loop should be avoided. In such a case a collection would be more desirable. A collection object does have a .toarray method - which could be useful in combing the flexibility of a collection with the performance of an array. but I have yet to find a use for it. p.s, Eric - Havn't gone to lunch - Am still playing red dragon.
VBBRYeah I'm aware of all that, and have already implemented everything, including the pointer-to-tile thing. Also the ReDim's only happen at load time (when the array is created, that is, just once per map) At the moment the map has only one layer, the visual (background one), that can only have visual tiles (duh), which means, only visual, not object actions, animations and such (so it saves memory). It is pretended to have a 2nd layer as soon as I finish working on the 1st (the runtime part is almost ready; I will work on the creator part now) I also have a "model bank" (I call it this way) system ready, that stores the models. The map data only references them (with an integer), so it won't be needed 400 models for a 20x20 map for example.
CodeImpIf you want to use something like Collections, take a look at the Dictionary object (include reference "Microsoft Scripting Runtime"). It is much faster than the Collection. The only downside compared to the Collection is that you cannot simply get an item by index such as MyItems(34). You have to give each item a key. Example: MyItems.Add "key", "value". To get the item back you simply do MyItems("key"). Value can, like with Collections, be anything except a UDT. Ofcourse, if an array does the job for you, then an array is probably still faster. However, I think its not a real big difference.
Almar Joling
quote:
Originally posted by Dan
Yes, An array is the way forward because the dimensions of the map are known (Well they should be). It's important to remember that when declaring and array, it is possible to add additional dimensions. [code] Dim Map (50,50) as integer [/code] Would give you a grid 50 x 50 to add yout tile references, If you wanted to have a map with multiple layers you could have [code] Dim Map_Layer1 (50,50) as integer Dim Map_Layer2 (50,50) as integer Dim Map_Layer3 (50,50) as integer [/code] But a tidier way would simply be [code] Dim Map (50,50,3) as integer [/code] You could add some constants to describe the layers, or if your wrapping it all up as a class then an enumeration for the layer could be added. I'm sure you are already aware that the array should contain a pointer to a tile and not the tile it'self. Describing the array as integer over a long will almost half the amount of space required to store the array. And unless you need more than 32,767 tiles is more than adequete. The use of the Redim within your game loop should be avoided. In such a case a collection would be more desirable. A collection object does have a .toarray method - which could be useful in combing the flexibility of a collection with the performance of an array. but I have yet to find a use for it. p.s, Eric - Havn't gone to lunch - Am still playing red dragon.
Multi-dimensional arrays are slow, though :)
Dan
quote:
Multi-dimensional arrays are slow, though :)
Slow compared with what? collections or seperataly declared arrays?