
So after a lot of procrastination I made some progress. I have basic scene logic, which is clearing up all resources and loading the resources needed for the next scene. A scene can be a game menu, or the game itself. As for finding out if it was possible to remove an image or view, its a big nope. Basically you'll have to reuse existing views you've already created and for images, just swap them out. This is a big issue, but if you think about it, at least your application will not crash because your trying to access an image that is not in memory.
The Map
After that I moved onto the map, which presented a bit of an issue. DragonFire SDK does not let you write a c structure to file. In fact it must be a char*, array of characters. So whats the problem? Well let say I have a map 4x4, this will be represented with 16 characters to save to file. Now think, how many letters can you fit inside a single character? Well, if you guess it, then its one character! The max range of one character is 0 to 255 in a decimal format. Oh wait, it can't be that because its not unsigned char* your working with, its (signed) char*. So the max range is -128 to 127, which is still 255 possible types of tiles. The most logical step is to just convert the tile id from an integer to a char*. So an unsigned short, let say 15,000 is 2 bytes, which will end up being 5 chars hence 5 bytes. Congratulations you just limited yourself to 2.5x smaller the size of possible max map size! I am not very happy with that result. Sticking with 255 possible tiles is not a solution for me. I want more then 512, 1,024, 5,000, heck 32,767 possible tiles would be a perfect number right? So here are the steps I took to at least write the map to file.
First I get the tile id, and convert it to a string. However when you convert an integer to a string you don't have a fixed string size. This becomes an issue when you want to have simple logic to grab the first 3 numbers in the integer, and then the last 3 numbers. So for now after the number is converted I force a length of 6 bytes to overcome this.
//-- Convert tile id to a string
short numberLength = 0;
std::stringstream out;
out << map[i];
tileString = out.str();
//-- This helps prevent an overflow of two chars
numberLength = tileString.length();
//-- If I don't resize to a fixed size, then substr will fall out of range
tileString.resize(6);
The basics are, split the one number into two numbers and if the first number is greater then 255, then push the remainder onto the second number. This becomes an issue with numbers like 999, as it will fall over to the second number with a value of 744 which is greater then 255. So to get around this, I just have some basic logic, if the number is smaller then 5 digits, then just chop the number in 2 digits each rather then 3 digits each. Limiting the char to 2 digits for number smaller then 10,000 allows me to utilize the full range of numbers up to 32,767. It could go even higher, but 32,767 is a very decent number that I will not hit any time soon.
//-- Split the string number into two parts, so they each fit in a char
//-- Part One
int one, two, placeholder;
int start, stop;
placeholder = 0;
start = 0;
stop = 3;
if (numberLength < 5) {
start = 0;
stop = 2;
}
if((std::istringstream (tileString.substr(start, stop).c_str()) >> one).fail()) {
one = 0;
}
//-- If this number is too big then add the remainder to the placeholder
if (one > 255) {
placeholder = one - 255;
one = 255;
}
//-- Part Two
start = 3;
stop = 3;
if (numberLength < 5) {
start = 2;
stop = 2;
}
if((std::istringstream (tileString.substr(start, stop).c_str()) >> two).fail()) {
two = 0;
}
//-- Apply any placeholder
two += placeholder;
//-- Save to map
mapStr[i * 2] = one - 128;
mapStr[(i * 2) + 1] = two - 128;
Other then that, this concludes another part into my iphone game progress. I have not had any more force quits when running on my iphone after compile by the DragonFire SDK build server. Oh I did notice there are a few undocumented functions like FileDelete. I am still a happy with DragonFire and can't wait to finish my map loader and saver. I think the next post will be my map editor, which will most likely be browser based, which PHP code on the backend to pack the binary maps.
Still reading? Probably a good reason why. This is because you want to tell me on how wrong I am about being able to get a short integer to fit into 2 bytes, and still being able to decompress it. Well my friend you are right. I have no way to read back a tile id, if the value was shifted between two bytes. And it took me a day to sleep on it to even think about this. So here is the resulting code to resolve this issue. I ended up having to use one extra byte.
//-- Convert tile id to a string
std::stringstream out;
out << map[i];
tileString = out.str();
//-- If I don't resize to a fixed size, then substr will fall out of range
tileString.resize(6);
//-- Split the string number into trhee parts, so they each fit in a char
int digits[3];
for (int d = 0; d < 3; d++) {
if((std::istringstream (tileString.substr(d * 2, 2).c_str()) >> digits[d]).fail()) {
digits[d] = -1;
}
//-- Save to map
mapStr[(i * 3) + d] = digits[d];
}
I instead need at least 3 chars, 3 bytes to compress a short into. Each byte will go up to 99, but no more, fitting perfectly into a single char, 3 times. This means I can have a max tile id of 999,999 tile ids. This much more then the 65,535 possible ids in a short, but again this will do. The resulting code is much more compact and well simple. This will make my maps 50% smaller then before but I still save 60% in memory compare to using one byte per number.
So the big question is how big of a map can I fit into memory before I need to read in a new map? Well as long as I keep the number of layers low, let say 5 layers. The first layer will be the ground tiles. The second layer will be decoration. The third layer will be characters / npc. The fourth layer will be walls and object the character will go behind and the last layer will be for clouds. I really don't need to describe the last layer in a map, this will be auto generated. So then, what will one map size be? Well let's try this:
x = (256 tiles * 3 bytes) // The x will always hold the tile id.
y = 256 // the y stuff?
z = 4 // layers
x * y * z = 768 kilobytes of memory