Using banks
Blitz3D Forums/Blitz3D Programming/Using banks
| ||
Hi there, Is it possible to use a bank to store pointers to type-instances? I'm working on a spacegame and each space-sector can have a different amount of spacestations in it. Right now I'm using an array of types (1 dimension) to store the pointers to the Sector-type-instances and another array (2 dimensions) to hold all pointers to all spacestation type-instances. Type Sector Field Name$ Field ... End Type Type Station Field Name$ Field ... End Type ArraySectors.Sector(5) ArrayStations.Station(5, 10) For the second array: the first dimension holds the SectorNumber (5 Sectors), the second one holds the StationNumber (10 Stations per sector). Actually 6 Sectors and 11 Stations, but I don't use index 0, because it's difficult as it is right now for me to keep things organised. This code shows the current setup (only an example), because the arrays are redimmed to hold all data, which is stored in a textfile (so the size of those arrays is based on the data in that file). But when a sector (say sector 3) only has 1 station in it, then the array DOES have 10 indexes available (which are not used at all) for that sector. When the universe is small (like in this example), then this will not be an issue for memory-usage, but when the universe has about 150 sectors and a maximum of 25 stations per sector, then it can lead to a lot of unused memory. And not all sectors will have those 25 stations inside it. The most populated sector will have 25 stations (as an example, don't know yet how many it will be eventually). I tried to include another field in the Sector-type, which hold the pointer to a bank. Type Sector Field Name$ Field SectorList = CreateBank(0) End Type After that, I've tried to assign a new Station-type-instance to this bank (after resizing it), but I got a "Illegal Type Conversion" error. So I wanted to have each Sector-type-instance have it's own bank, which would hold all pointers to all Station-type-instances in that sector. This could work as a linked-list of Stations per sector. It would be sort sort of private TList (like in BMax), but then with Banks. Then no memory is wasted, as the bank would only be as big as needed to hold all pointers. Is this possible? If it is possible, how can I do this? |
| ||
It seems I'm able to convert an type-pointer to an int and store that:Type Sector Field Name$ Field SectorList End Type Type Station Field Name$ End Type NewSector.Sector = New Sector NewSector\SectorList = CreateBank(4) PokeInt(NewSector\Sectorlist, 0, Int(New Station)) Print PeekInt(NewSector\SectorList, 0) WaitKey() End Can this be reverted (convert an Int back to a pointer)? When I try this before the Waitkey() statement: NewStation.Station = PeekInt(NewSector\SectorList, 0) I again get an "Illegal Type Conversion" error. |
| ||
Although I despise the Object/Handle Commands they may server your purpose well.Type Sector Field Name$ Field SectorList End Type Type Station Field Name$ End Type NewSector.Sector = New Sector NewSector\Name$="The Base" NewSector\SectorList = CreateBank(4) NewStation.Station=New Station NewStation\Name$="Alpha 1" PokeInt(NewSector\Sectorlist, 0, Handle(NewStation)) AStation.Station=Object.Station(PeekInt(NewSector\SectorList, 0)) Print AStation\Name$ WaitKey() End My approach would be different. I would use a Array of Types and add a Field ID to the Station Type. Theres a little more code, but, its faster and you have complete control over objects created. Type Sector Field Name$ Field SectorList End Type Type Station Field ID Field Name$ End Type Dim StationID.Station(100) ;<-- array of types Global Stations NewSector.Sector = New Sector NewSector\Name$="The Base" NewSector\SectorList = CreateBank(4) NewStation.Station=New Station Stations=Stations+1 NewStation\ID=Stations StationID(NewStation\ID)=NewStation NewStation\Name$="Alpha 1" PokeByte(NewSector\Sectorlist, 0, NewStation\ID) AStation.Station=StationID(PeekByte(NewSector\SectorList, 0)) Print AStation\Name$ WaitKey() End |
| ||
I will give your first idea a try (Object and Handle commands). I've rewritten the entire load-routines for this datafile, so now only if a station really exists, the type-instance will be created, it's pointer gets put inside the array and the data is loaded into the type-instance. This way only the 4 bytes (index of an array) are lost. First I had lots of unused type-instances (dim the array and fill it with pointers to new type-instances). Dim ArrayStations.Station(NumberOfSectors, MaxNumberOfStations) For i = 1 To NumberOfSectors For j = 1 To MaxNumberOfStations ArrayStations(i, j) = New Station Next Next At first, a few unused 100Kb did matter. Now, a few unused bytes won't matter, I think. I'll give it a try and decide which approach will be best for the game (and easiest). |
| ||
Object() and Handle() are really useful commands for a great number of things. You can even store the type handles in the entity name with NameEntity()/EntityName$(). I haven't read all of this, but why do you actually need to store all these type handles? Usually you only need a handle when you want to do something specific to one object, to update all of them you'd use For Each, and so on. The entity name trick usually removes the need for arrays indexing each type object. |
| ||
I'm using arrays to quickly pinpoint a specific type. Let's say I've got 200 sectors and 20 stations per sector. This is equal to 4000 type-instances. Now, the player can only be in one sector of space at any given time (like Freelancer). So, to loop through all stations in the sector where the player is located, I would only have to loop through all indexes of the array for that sector, instead of looping through all 4000 type-instances: ; this code print only the 20 stations inside the current sector ; where the player is located For i = 1 To 20 Print ArrayStations(CurrentSector%, i).Name$ Next The var "CurrentSector%" holds the current sectornumber where the player is located. Without using arrays (and need updating all stations inside the current sector), I would have to do something like this: For CurrentStation.Station = Each Station If CurrentStation\BelongsToSector$ = SectorName$ ... EndIf Next Looping through all stations (where 99.5% of them (3980 out of the total 4000) don't need to be checked) is a bit overkill when only updating 1 sector. But now I have succesfully converted my loading routines into BMax, using resizable arrays-of-types inside types. No more trouble about unused array-indexes. Now I have actually what I wanted, except a 3D module, to create an entire sector and fly through it, of course (which my B3D-version could do right now). Now I can add stations to a sector, without having to know the maximum number of stations that exist inside a given sector (the most populated one) to firstly dim the array to the proper size, before loading data into it. Each time a station is added now, the array-size is increased by 1 (the contents don't get lost in BMax) and the new station is added to the sector. |