You're gonna kill me on sunday Azazel ;)
With IStuffDPF I want to Load a DPF, find all the tilesets in the DPF and list them, select them, use 'em, etc.. (in a map editor)
But I need to know what the format for DPF_BlockData::data is for a Tileset.
Thanks in advance!
Hi again Mike,
I have never thought someone will need to know the internal structure of the CTile resources but Im happy to know I was wrong :)
The tiles are stored with typeblock = "TILE2".
The struct is:
X surface size: 4 bytes
Y surface size: 4 bytes
X position: 4 bytes
Y position: 4 bytes
Tileset flag: 4 bytes
Tileset X offset: 4 bytes
SDL Pixel format (SDL_PixelFormat): 40 bytes
Raw pixels data: DPFBlockdata.size - 128.
Tileset Y offset: 4 bytes (this was added in the new tile v2)
Reserved data: 60 bytes to future improvements.
Well, hope this can help you, any other you need, please, let me know!
Cheers!
Thank you! There is also one more thing, very related, the DPF_BlockData::data structure for sprites as well. :)
[and again]
more changes to code. 8)
[/and again]
[edit again]
I forgot to get the tile offset info, updated the code to do that too. :)
[/edit again]
[edit]
Fixed - I accidentally coded it so it would quit out of the loop and the function and return NULL if the tileset wasn't found on the first loop every time.
It _IS_ and always has been creating the SDL_Surface properly.
Here's the fixed code if anyone is interested, but it has memory leaks:
// Loads (and creates) a Tileset and returns it's pointer. Returns NULL if Failed.
// You must delete the Tileset yourself when you are finished with it.
CRM32Pro_CTile* load_tileset(CRM32Pro_CTile* ptile, char* dpfname)
{
if(!sts_dpf_initialized) return NULL; // Always make sure a DPF was loaded, if not
// there's nothing here to do.
for(int i=0; i < sts_total_tilesets; ++i) // Now find dpfname in the tileset names list.
{
if(sts_tileset_names[i].compare(dpfname)==0) // If the Tileset asked for is in the array,
{ // we can begin to create that Tileset.
int dpfid = IStuffDPF->Open(sts_dpf_filename); // To get the Tileset's data, open the DPF.
if(dpfid<0) return NULL;
DPF_BlockData dpf_db; // If the data block has a size of 0 or less,
if(!IStuffDPF->LoadBlock(dpfid,"TILE2",dpfname,&dpf_db))// something went wrong and we must NULL out.
{
IStuffDPF->Close(dpfid);
return NULL;
}
SDL_Surface* tsurf = NULL; // Create some vars that will hold the data
long surf_x_size = 0; // used to create the Tileset's Surface (image),
long surf_y_size = 0; // and then to create the Tileset itself.
long pitch = 0; // sdl note: pitch is width of image in bytes
long x_off = 0;
long y_off = 0;
SDL_PixelFormat surf_pf;
int surf_pixels_size = dpf_db.size - 128;
char* surf_pixels = new char[ (surf_pixels_size) ];
// The following is a _guess_ on the methods of: how to get the data required to
// create a Tileset, and: How to, in return, create that Tileset.
/*CRM32Pro_*/ memcpy(&surf_x_size, &dpf_db.data[0], 4);
/*CRM32Pro_*/ memcpy(&surf_y_size, &dpf_db.data[4], 4);
/*CRM32Pro_*/ memcpy(&x_off, &dpf_db.data[20], 4);
/*CRM32Pro_*/ memcpy(&surf_pf, &dpf_db.data[24], 40);
pitch = surf_pf.BytesPerPixel * surf_x_size;
//pitch = surf_pixels_size / surf_y_size;
/*CRM32Pro_*/ memcpy(surf_pixels, &dpf_db.data[64], surf_pixels_size );
/*CRM32Pro_*/ memcpy(&y_off, &dpf_db.data[64 + surf_pixels_size], 4);
// Create SDL_Surface for Tileset.
tsurf = SDL_CreateRGBSurfaceFrom(surf_pixels, surf_x_size, surf_y_size, surf_pf.BitsPerPixel,
pitch, surf_pf.Rmask, surf_pf.Gmask, surf_pf.Bmask, surf_pf.Amask);
if(!tsurf) // If we failed to create the SDL_Surface for
{ // the Tileset we have to return NULL, there's
delete [] surf_pixels; // nothing else we can do to be successful.
IStuffDPF->Close(dpfid);
return NULL;
}
if(!ptile)
CRM32Pro_CTile* ptile = new CRM32Pro_CTile(); // Now we can create the Tileset, and set
ptile->Create(tsurf, dpfname); // it's data we just obtained.
ptile->SetTileSet(1, x_off, y_off); // Set Tileset flag and size per tile.
IStuffDPF->Close(dpfid);
//
// UNFREED MEMORY: (unintentional) tsurf, (unintentional) surf_pixels, (intentional) ptile
//
return ptile;
}
}
return NULL; // We've gone this far only if the Tileset
// dpfname we were searching for was not found.
}
[/edit]
Mike,
to create the SDL surface I use this way:
->get size_x and size_y with its memcpy
...
memcpy(&fmt,bqTile.data + 4 * 6,sizeof(SDL_PixelFormat));
image = SDL_CreateRGBSurface(SDL_SWSURFACE,size_x,size_y,fmt.BitsPerPixel,fmt.Rmask,
fmt.Gmask,fmt.Bmask,fmt.Amask);
if(image == NULL) {IStuffDPF->Close(idDPF); return 0;}
memcpy(image->pixels, bqTile.data + 4 * 6 + sizeof(SDL_PixelFormat),bqTile.size - 128);
Use it, it´s easier! :), if you have the right format...why not use it? :)
Last days Im too busy at work so as you can see Im quite slow answering you :).
Let me know if that works for you!
Cheers!
P.S.: do you need the sprite struct too?
YES! I would love the sprite structure too!!
Also, funny you should bring that code up :lol: - I just went through and made the exact same changes because the supplied color masks weren't working anyway!
I still use SDL_CreateRGBSurfaceFrom(), but I may change if I find any memory leaks because of it. My only concern after the "is everything working?" concern, is leaving allocated memory allocated.
Ah but I'm about back to where I was before I decided editor users shouldn't have to *know* what every tileset's name is in a DPF.
Now if I could just get that dpf block data sprite structure from ya. ;)
Thanks alot too!
Tomorrow(for me hehe, not for you), I will add the sprite struct using a few spare minutes on my job :)
Maybe this can help you, I have almost ready a DPF<->XML export/import but I dont what are you trying to do... and I would like to see it, remember, I will be your first betatester hehehe
cheers!
Cool! When I add the visual elements to show-off the new tileset system I'll send you a release build!
[edit]
I've sent you an email with the editor attached to it - As well as a big explanation of how to use the editor.
[/edit]
Wooww!!
it works for me and it is very cool! :)
at the beginning I was a little confused because I only got error messages but when I read your mail I understood how to use it :)
As I told you... BoundsChecker can help you :P
Well, let see if tomorrow I can show you the sprite structure.
I really hope you can release the editor to the whole community, it could help to other in theirs projects :)
Im longing for more news coming from you!
See you later!
Cheers!
I _could_ release it.. But weeks from now. There are plenty of features I still need to code for my project. Plus, the editor uses modules from my main game source - I don't want to release anything til it's ripe for the pickin'!
And, as you noticed, the GUI for the Editor leaves too much to the imagination when it comes to figuring out "what does what".
Ao so much to look forward to fixing.
Mike, I forgot to show you the sprite struct, let's go!
The sprites are stored with typeblock = "SPR2".
There are two internal structs:
typedef struct _sAnim
{
Uint16 type; // Animation type
Uint16 status; // Status: high and low.
Uint16 numFrames; // Total number of frame of this animation
Uint16 curFrame; // Current frame
sFrame *Frames; // Pointer to frames array
Uint16 startFrame; // Start frame in this animation. Usually is equal to 0
Uint16 endFrame; // End frame in this animation. Usually is equal to the numFrames
Sint16 hotx; // Hot X of this animation
Sint16 hoty; // Hot Y of this animation
char reserved[44]; // 44 reserved bytes
#define ANIM_RESERVED 44
} sAnim;
typedef struct _sFrame
{
Uint32 ms; // Frame duration in ms
char reserved [12]; // 12 reserved bytes
#define FRAME_RESERVED 12
} sFrame;
Now, the order you will find the bytes in the DPFblock.data:
X frame size: 4 bytes
Y frame size: 4 bytes
X position: 4 bytes (not very useful, but is there!)
Y position: 4 bytes (not very useful, but is there!)
Number of animations: 4 bytes
X surface size: 4 bytes
Anim 1
Frame 1
Frame 2
Frame N
Anim N
..
SDL Pixel format (SDL_PixelFormat): 40 bytes
Raw pixels data: DPFBlockdata.size - 24 - sizeof(sAnim) * numAnim - sizeof(sFrame) * nF(total number of frames) bytes
A bit of help loading animations and its frames...I use this piece of code:
tmp = bqSpr.data + 24;
nF = 0; // Total number of frames
AnimArray = new sAnim[numAnim];
for(i = 0; i < numAnim; i++)
{
memcpy(&AnimArray [i],tmp,sizeof(sAnim));
tmp = tmp + sizeof(sAnim);
AnimArray [i].Frames = new sFrame[AnimArray [i].numFrames];
for(j = 0; j < AnimArray [i].numFrames; j++)
{
memcpy(&AnimArray [i].Frames[j],tmp,sizeof(sFrame));
tmp = tmp + sizeof(sFrame);
nF++;
}
}
Note that is important to get the total number of frames to load the surface.
As usual, if you have any problem, please, let me know!
Cheers!
Oh man sweet! Now I can get sprite manager module up and running!!
Thanks!!