Type fields

BlitzMax Forums/BlitzMax Beginners Area/Type fields

I used to do the same for my game (in B3D).
I also have a massive Select statement for each type of object in the game (a 3D spacegame), one for loading waretypes, one for missiletypes, one for shieldtypes, ...

Since yesterday, I decided to use a binary file, where all fields are just written after eachother.
Now the file is much smaller (1.5Kb instead of 8Kb).
The file will be much bigger when the game is operational, I have only a few items in there right now for testing the loadroutines and such.
Afterwards, I can simply put in more objects and the game adapts automatically.

The editor for the game will be written in VB6.0 (right now, I'm using Notepad), which outputs a textfile, like this:

[WareType]
Name = Ore
Description = ...
DefaultPrice = 55
CargoSpace = 2
[EndWareType]

[WareType]
Name = Food
Description = ...
DefaultPrice = 24
CargoSpace = 1
[EndWareType]

[ShieldType]
Name = 5MW Shield
Description = ...
DefaultPrice = 25000
Strength = 5000000
[EndShieldType]

...

I could write the editor to output the binary file directly, but I don't really know if VB outputs integers as 4 bytes and with the LSB first.
And strings must be preceded by the number of characters, otherwise Blitz cannot read it correctly.
So it will output a textfile, which will be converted with a program in B3D (the converter).

The [WareType] and [EndWareType] are used to indicate the start and end of each block of data.
When a [WareType] is found, a new TWareType instance will be created, the fields will be loaded, until [EndWareType] is reached.
Unknown identifiers or simply text (or comments) is ignored.

Then I will have a converter that reads this file and converts it to a binary file.
It only writes the field-values in a binary format, without the identifiers.
This way, a large number (like 125000000) will be written using only 4 bytes instead of 9.
Then the game can simply load all fields right after eachother.
The converter writes this (pseudo-code):
WriteString(waretype\Name$)
WriteString(waretype\Description$)
WriteInt(waretype\DefaultPrice%)
WriteByte(waretype\CargoSpace%)

The cargospace uses only 1 byte, because none of the wares in my game will ever use more than 255 units of cargospace onboard a station or ship.

Then the game reads them using the same method.
It's still a long loadroutine, but much simpler, because all fields stay in the exact order, thanks to the way the converter writes the file.

All waretype-instances are written right after eachother, followed by the ShieldTypes.
After that, other data will come, defining the structure for my universe (not worked out yet).

Each big block of data is preceded by a Short (2 bytes), which indicates the number of objects of that kind.

So the game uses this to read the file (B3D code):

NumberOfWareTypes = ReadShort(file)

For i = 1 to NumberOfWareTypes
waretype.TWareType = New TWareType
waretype\Name$ = ReadString(file)
waretype\Description = ReadString(file)
waretype\DefaultPrice% = ReadInt(file)
waretype\CargoSpace% = ReadByte(file)
Next

NumberOfShieldTypes = ReadShort(file) ; Read the number of ShieldTypes in the file

For i = 1 to NumberOfShieldTypes
shieldtype.TShieldType = New TShieldType
shieldtype\Name$ = ReadString(file)
shieldtype\Description = ReadString(file)
shieldtype\DefaultPrice% = ReadInt(file)
shieldtype\Strength% = ReadInt(file)
Next

...


Or, if your fields in your datafile are all in the exact same order everytime, you could use arrays.
I helped another forum-user once who had trouble, because he uses massive amounts of fields and he wanted to clone an existing object with all field-values intact.
You could use this example and adapt it for loading data:
http://www.blitzbasic.com/Community/posts.php?topic=48391#538411


(pseudo code)
While Not Eof(dataFile)
i = i + 1
getFileOption(ReadLine(dataFile))
dat.Array$[i] = fopt.value$
Wend


This could work.
Afterwards, use constants to address the array's indexes.
Then it will be the same as addressing an instance's fields.
Before:

instance.fieldname = ...

Now:

instance.array[fieldname] = ...