Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





IStuffDPF & DPF_BlockData (Tiles & Sprites structs)

Iniciado por Mikenoworth, 20 de Enero de 2007, 10:55:05 PM

« anterior - próximo »

Mikenoworth

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!

TheAzazel

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!

Mikenoworth

Thank you! There is also one more thing, very related, the DPF_BlockData::data structure for sprites as well. :)

Mikenoworth

[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]

TheAzazel

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?

Mikenoworth

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!

TheAzazel

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!

Mikenoworth

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]

TheAzazel

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!

Mikenoworth

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.

TheAzazel

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!

Mikenoworth

Oh man sweet! Now I can get sprite manager module up and running!!


 Thanks!!






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.