Jump to content
  • Advertisement
Sign in to follow this  
coderWalker

Saving gamedata

This topic is 2884 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a game that operates on a 3dtilemap. I need to be able to save the
data in the tilemap to a file and read it back in when the game
relaunches. I pasted the code below of the defines so you can see what
type of data I am dealing with.

The game is seperated into Chunks and each chunk having the 16x16x16 array.


struct Block
{
bool exists;
int tx,ty;
};

Block space[16][16][16];


Below is something that I have conjured up and It works, but there
has got to be a better way. Also each individual save file turns out to be
about 25kb kinda large where there will be 1000's of files.

Would binary writing be alot better for this?

Got to be a way to just copy the whole array to a file rather then what i'm
doing. I assume it would also be easier to read.

Hope someone has an idea.
Thanks in advance,
this has stumped me about a week.


void file::write(int x,int y,int z)
{
/*stringstream xStr,yStr,zStr;
if (x<100)
{
if (x<10)
{
xStr<<"0";
}
xStr<<"0";
}
xStr << x;
if (y<100)
{
if (y<10)
{
yStr<<"0";
}
yStr<<"0";
}
yStr << y;
if (z<100)
{
if (z<10)
{
zStr<<"0";
}
zStr<<"0";
}
zStr << z;*/
name.str(std::string());
//name << "save/" << x << "/" << y << "/" << z << ".txt";
//name << "save/" << xStr.str() << "x" << yStr.str() << "x" << zStr.str() << ".txt";
name << "save/" << x << "x" << y << "x" << z << ".txt";
temp = name.str();
fileStream.open(temp.c_str());
if (fileStream.is_open())
{
/*for (int i=100;i>=0;i-=2)
{
fileStream << i << endl;
}
cout << "Wrote " << temp.c_str() << "\n";*/
for (int tz=0;tz<16;tz++)
{
for (int ty=0;ty<16;ty++)
{
for (int tx=0;tx<16;tx++)
{
fileStream << Map->Chunk[x][y]->space[tx][ty][tz].tx;
fileStream << "\n";
fileStream << Map->Chunk[x][y]->space[tx][ty][tz].ty;
fileStream << "\n";
}
}
//fileStream << "\n";
}
}
else
{
//printf("/!\\ Cannot open \n");
cout << "/!\\ Cannot open " << temp.c_str() << "\n";
}
fileStream.close();
return;
}

Share this post


Link to post
Share on other sites
Advertisement
Two ints and a bool on a typical system will be, for example, 32+32+8, multiplied by your chunk of 16*16*16 would be 294912 bytes by my reckoning, so I doubt a binary file is going to save much space - if the majority of the numbers in your ints are below 1000, it could possibly be even bigger (e.g. 12 in text will be 2 bytes, but 12 in 32-bit binary will still be 4 bytes).

However, these are not really concerning file sizes for PC storage.

If you really need to save space, might be easier to run the files through a pre-tested compressor and de-compress as needed at runtime.

Share this post


Link to post
Share on other sites

Two ints and a bool on a typical system will be, for example, 32+32+8, multiplied by your chunk of 16*16*16 would be 294912 bytes by my reckoning, so I doubt a binary file is going to save much space - if the majority of the numbers in your ints are below 1000, it could possibly be even bigger (e.g. 12 in text will be 2 bytes, but 12 in 32-bit binary will still be 4 bytes).

However, these are not really concerning file sizes for PC storage.

If you really need to save space, might be easier to run the files through a pre-tested compressor and de-compress as needed at runtime.


Space is a concern, but not my main concern. Thanks for the information though :D
Is there a easier way to write this to a file then what I am doing?

Share this post


Link to post
Share on other sites
What's the actual code you're using, sans commented-out chunks of cruft?

Of the stuff you posted, most of it seems questionable at best - but it's also marked out, so I have no way of knowing what your intentions are as far as how the code is meant to work and what's supposed to be there vs. not.

Share this post


Link to post
Share on other sites

Two ints and a bool on a typical system will be, for example, 32+32+8, multiplied by your chunk of 16*16*16 would be 294912 bytes by my reckoning
294912 bits; that's 36 864 bytes. Still larger, but not an order of magnitude larger. The main benefit of saving things in a binary format though would be that it'd be quite a bit faster to load and save. Reading and writing ints in text mode is basically running your data through itoa/atoi every time. Of course, if there's a possibility that the code in question is going to run on systems with different endianness then you have to take that into account but that's not going to be slower than reading/writing in text mode (which has similar issues with line endings.)

Share this post


Link to post
Share on other sites

[quote name='Aardvajk' timestamp='1294885128' post='4758107']
Two ints and a bool on a typical system will be, for example, 32+32+8, multiplied by your chunk of 16*16*16 would be 294912 bytes by my reckoning
294912 bits; that's 36 864 bytes. Still larger, but not an order of magnitude larger. The main benefit of saving things in a binary format though would be that it'd be quite a bit faster to load and save. Reading and writing ints in text mode is basically running your data through itoa/atoi every time. Of course, if there's a possibility that the code in question is going to run on systems with different endianness then you have to take that into account but that's not going to be slower than reading/writing in text mode (which has similar issues with line endings.)
[/quote]

Doh! Quite correct of course. Silly old me.

Share this post


Link to post
Share on other sites
[color="#1C2837"][font="CourierNew, monospace"][color="#000088"]struct [color="#660066"]Block [color="#666600"]{ [color="#000088"]bool[color="#000000"] exists[color="#666600"]; [color="#000088"]int[color="#000000"] tx[color="#666600"],[color="#000000"]ty[color="#666600"]; [color="#666600"]}; [color="#660066"]Block[color="#000000"] space[color="#666600"][[color="#006666"]16[color="#666600"]][[color="#006666"]16[color="#666600"]][[color="#006666"]16[color="#666600"]];[/font]
[color="#1C2837"][font="CourierNew, monospace"] [/font]
[color="#1C2837"][font="CourierNew, monospace"] [/font]
[color="#1C2837"][font="CourierNew, monospace"][color="#666600"]Well, what are the max and min the tx and ty value could be? (f it's for a typical screen coordinate, can you get away with limiting tx and ty to 2048? If so, you can squeeze one Block into 3 bytes by writing 1 bit for the bool and 11 bits for x and y each, [/font][color="#666600"][font="CourierNew, monospace"]which would be 16*16*16*2= 12288 bytes per space[][][][/font][color="#666600"][font="CourierNew, monospace"]. So, you'd call some kind of convert function for each space[][][], which would do this:[/font]
[font="CourierNew, monospace"] [/font][color="#666600"][color="#1C2837"][font="Courier New"][color="#666600"]unsigned char *ConvertToSaveBlock(Block space[][][])
[color="#666600"]{
[color="#666600"]unsigned char *pStoreMemory;
[color="#666600"]unsigned char *pLoc;
[color="#666600"]pStoreMemory = malloc(3*16*16*16);
[color="#666600"]pLoc = pStoreMemory;

[color="#666600"]for (int i = 0; i < 16; i++)
[color="#666600"]{
[color="#666600"]for (int j = 0; j < 16; j++)
[color="#666600"]{
[color="#666600"]for (int k = 0; k < 16; k++)
[color="#666600"]{
[color="#666600"]/* store the exists bit at the left *.
[color="#666600"]*pLoc = (space[j][k].exists ? (1 << 7) : 0);
[color="#666600"]/* store high 7 bits of 11 from tx in rest of byte */
[color="#666600"]*pLoc |= (unsigned char)[color="#666600"]((space[j][k].tx & 0x7F0) >> 4);
[color="#666600"]pLoc++;
[color="#000000"][color="#666600"]/* store low 4 bits of 11 from tx in top of next byte */[color="#000000"] [/font]
[color="#666600"][color="#1C2837"][font="Courier New"][color="#000000"][color="#666600"]*pLoc = [color="#666600"](unsigned char)[color="#666600"]((space[j][k].tx & 0xF) << 4);
[color="#000000"][color="#666600"]/* store high 4 bits of 11 from ty in rest of byte */[color="#000000"] [/font]
[color="#666600"][color="#1C2837"][font="Courier New"][color="#000000"][color="#666600"]*pLoc |= [color="#666600"](unsigned char)[color="#666600"]((space[j][k].tY & 0x780) >> 7);[color="#000000"] [/font]
[color="#666600"][color="#1C2837"][font="Courier New"][color="#000000"][color="#666600"]pLoc++;
[color="#000000"][color="#666600"]/* store low 7 bits of 11 from tx in last byte */[color="#000000"] [/font]
[color="#666600"][color="#1C2837"][font="Courier New"][color="#000000"][color="#666600"]*pLoc = [color="#666600"](unsigned char)[color="#666600"](space[j][k].tx & 0x7F);[color="#000000"] [/font]
[color="#666600"][color="#1C2837"][font="Courier New"][color="#000000"][color="#666600"]}[color="#000000"] [/font]
[color="#666600"][color="#1C2837"][font="Courier New"][color="#000000"][color="#666600"]}[color="#000000"] [/font]
[color="#666600"][color="#1C2837"][font="Courier New"][color="#000000"][color="#666600"]} [/font]
[color="#666600"][color="#1C2837"][font="Courier New"] [color="#000000"][color="#666600"]return [color="#666600"]pStoreMemory;

[color="#666600"]}

[color="#666600"]//And you could do something like this:
[color="#666600"]unsigned char *pCompressedMem = ConvertToSaveBlock(space);
[color="#666600"]fwrite(pCompressedMem, 1, 16*16*16*3, fOutputFile);[/font]
[font="CourierNew, monospace"] [/font][font="CourierNew, monospace"] [/font]
[color="#666600"][font="CourierNew, monospace"][/font][font="CourierNew, monospace"][color="#666600"][size="4"]Edit: Frigging new gamedev screwed up my post majorly, O well.
[/font][font="CourierNew, monospace"] [/font]
[font="CourierNew, monospace"] [/font]

Share this post


Link to post
Share on other sites
Thanks for the responces!
I am still working on this, my internet has been down though what a drag.

Anyway, did I copy this correctly?

unsigned char *file::write2(Block space[][][])
{
unsigned char *pStoreMemory;
unsigned char *pLoc;
pStoreMemory = malloc(3*16*16*16);
pLoc = pStoreMemory;
for (int i = 0; i < 16; i++)
{
for (int j = 0; j < 16; j++)
{
for (int k = 0; k < 16; k++)
{
/* store the exists bit at the left *.
*pLoc = (space[j][k].exists ? (1 << 7) : 0);
/* store high 7 bits of 11 from tx in rest of byte */
*pLoc |= (unsigned char)((space[j][k].tx & 0x7F0) >> 4);
pLoc++;
/* store low 4 bits of 11 from tx in top of next byte */
*pLoc = (unsigned char)((space[j][k].tx & 0xF) << 4);
/* store high 4 bits of 11 from ty in rest of byte */
*pLoc |= (unsigned char)((space[j][k].tY & 0x780) >> 7);
pLoc++;
/* store low 7 bits of 11 from tx in last byte */
*pLoc = (unsigned char)(space[j][k].tx & 0x7F);
}
}
}
return pStoreMemory;
}


I am getting quite a few Errors:

declaration of `space' as multidimensional array must have bounds for all dimensions except the first
declaration of `space' as multidimensional array must have bounds for all dimensions except the first
In member function `unsigned char* file::write2()':
invalid conversion from `void*' to `unsigned char*'
`space' undeclared (first use this function)
(Each undeclared identifier is reported only once for each function it appears in.)
[/quote]
HERE is a picture with Line Numbers, a lot more helpful.
[attachment=1003:err1.png]

Share this post


Link to post
Share on other sites
Have all the errors but this one fixed now:
53 file.cpp invalid conversion from `void*' to `unsigned char*' [/quote]
Code:
53 pStoreMemory = malloc(3*16*16*16);

Share this post


Link to post
Share on other sites

Have all the errors but this one fixed now:
53 file.cpp invalid conversion from `void*' to `unsigned char*'

Code:
53 pStoreMemory = malloc(3*16*16*16);
[/quote]

You should be able to cast to (unsigned char*) and make the warning go away... But this is C++; why not use new? Edited by kiwibonga

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!