Jump to content

Actor sprites file: Difference between revisions

Rename animation file -> actor sprites file
m (Raphi moved page Animation file to Actor sprites file without leaving a redirect)
(Rename animation file -> actor sprites file)
 
Line 1: Line 1:
Animations are similar to [[Sprite set file|sprite sets]], but they are (slightly) simpler in structure. Animations are used for "small" enemies (like boks or mummies), while sprite sets are used for "large" enemies (bosses and minibosses). Both animations and sprite sets can store static and animated sprites as well.
Actor sprite files are similar to [[Sprite set file|sprite sets]], but they are (slightly) simpler in structure. Actor sprites are used for "small" enemies (like boks or mummies) and most map objects (e.g. levers, candles, etc.), while sprite sets are used for "large" enemies (bosses and minibosses) and UI elements. Both actor sprites and sprite sets can store static and animated sprites as well.


= Differences compared to sprite sets =
= Differences compared to sprite sets =
* Each object in a sprite set sprite can have a different palette, whereas each animation frame must use the same palette for each object.
* Each object in a sprite set sprite can have a different palette, whereas every actor sprite must use the same palette for each object.
* Each game has multiple sprite set files, but only one animation file. However, the animation file has an internal structure instead that allows one to reference specific animations in the file.
* Each game has multiple sprite set files, but only one actor sprites file. However, the actor sprites file has an internal structure instead that allows one to reference specific actors in the file.
* Sprites use [https://problemkaputt.de/gbatek-lcd-obj-vram-character-tile-mapping.htm 2D character mapping], animations use 1D character mapping (for sprite objects, consecutive rows of tiles are always stored 16 tiles apart, whereas for animations consecutive rows follow immediately after the preceding row).
* Sprites use [https://problemkaputt.de/gbatek-lcd-obj-vram-character-tile-mapping.htm 2D character mapping], actor sprites use 1D character mapping (for sprite set objects, consecutive rows of tiles are always stored 16 tiles apart, whereas for actor sprites consecutive rows follow immediately after the preceding row).


= File format =
= File format =
The animation file stores multiple animations, and each animation can have multiple frames (a frame is similar to a sprite in a sprite set file). Each frame can be made up of multiple GBA objects.
The actor sprite file stores multiple actors, and each actors can have multiple sprites. Each sprite can be made up of multiple GBA objects.


<syntaxhighlight lang="c">
<syntaxhighlight lang="c">
struct AnimationFile {
struct ActorSpritesFile {
   /* offset 0x00 */ u32 unknown_0x00;
   /* offset 0x00 */ u32 unknown_0x00;
   /* offset 0x04 */ u32 animationCount;  // Number of animations in the animations[] array
   /* offset 0x04 */ u32 actorCount;  // Number of elements in the actors[] array
   /* offset 0x08 */ u32 unknown_0x08;
   /* offset 0x08 */ u32 unknown_0x08;


Line 18: Line 18:
   /* offset 0x0c */ u32 offsetToTiles;
   /* offset 0x0c */ u32 offsetToTiles;


   // Byte offset from start of the file to the frames[] array
   // Byte offset from start of the file to the sprites[] array
   /* offset 0x10 */ u32 offsetToFrames;
   /* offset 0x10 */ u32 offsetToSprites;


   // Byte offset from start of the file to the objects[] array
   // Byte offset from start of the file to the objects[] array
   /* offset 0x14 */ u32 offsetToObjects;
   /* offset 0x14 */ u32 offsetToObjects;


   Animation animations[animationCount];
   ActorSpritesActor actors[actorCount];
   GBA_Tile tiles[];
   GBA_Tile tiles[];
   AnimationFrame frames[];
   ActorSprite sprites[];
   AnimationObject objects[];
   ActorObject objects[];
};
};


struct Animation {
struct ActorSpritesActor {
   /* offset 0x00 */ u16 id;      // ID of this animation, used for loading it
   /* offset 0x00 */ u16 id;      // ID of this actor, used for loading it
   /* offset 0x02 */ u16 unknown_0x02;
   /* offset 0x02 */ u16 unknown_0x02;
   /* offset 0x04 */ u8 widthPx;  // Width of every animation frame in pixels
   /* offset 0x04 */ u8 widthPx;  // Width of every sprite in pixels
   /* offset 0x05 */ u8 heightPx;  // Height of every animation frame in pixels
   /* offset 0x05 */ u8 heightPx;  // Height of every sprite in pixels
   /* offset 0x06 */ i8 offsetX;  // X pixel offset of the animation, relative to the position provided by the game
   /* offset 0x06 */ i8 offsetX;  // X pixel offset of the actor, relative to the position provided by the game
   /* offset 0x07 */ i8 offsetY;  // Y pixel offset of the animation, relative to the position provided by the game
   /* offset 0x07 */ i8 offsetY;  // Y pixel offset of the actor, relative to the position provided by the game


   // Byte offset from start of the frames[] array to the first frame of the animation
   // Byte offset from start of the sprites[] array to the first sprites of the actor
   /* offset 0x08 */ u32 frameOffset;
   /* offset 0x08 */ u32 spritesOffset;
};
};


struct AnimationFrame {
struct ActorSprite {
   /* offset 0x00 */ u8 objectCount;  // Number of objects in this frame
   /* offset 0x00 */ u8 objectCount;  // Number of objects in this sprite
   /* offset 0x01 */ u8 unknown_0x01;
   /* offset 0x01 */ u8 unknown_0x01;


Line 49: Line 49:
   /* offset 0x02 */ u16 palette;
   /* offset 0x02 */ u16 palette;


   // Byte offset from start of the tiles[] array to the first tile of this frame
   // Byte offset from start of the tiles[] array to the first tile of this sprite
   /* offset 0x04 */ u16 tileOffset;
   /* offset 0x04 */ u16 tileOffset;


   // Byte offset from start of the objects[] array to the first object of this frame
   // Byte offset from start of the objects[] array to the first object of this sprite
   // The objectCount field determines how many objects should be drawn
   // The objectCount field determines how many objects should be drawn
   /* offset 0x06 */ u16 objectOffset;
   /* offset 0x06 */ u16 objectOffset;
};
};


struct AnimationObject {
struct ActorObject {
   // Same as the shape field in https://boktaihacking.net/wiki/Sprite_set_file
   // Same as the shape field in https://boktaihacking.net/wiki/Sprite_set_file
   /* offset 0x00 */ u8 shape;
   /* offset 0x00 */ u8 shape;
Line 67: Line 67:


= Tiles =
= Tiles =
Each animation frame only stores the ''first'' tile that should be drawn for this frame. The remaining tiles follow the first tile, in order, and using [https://problemkaputt.de/gbatek-lcd-obj-vram-character-tile-mapping.htm 1D character mapping]. Example: Assume that we have an AnimationFrame with two objects, one 16x16 px object, followed by one 8x16 px object:
Each sprite only stores the ''first'' tile that should be drawn for this sprite. The remaining tiles follow the first tile, in order, and using [https://problemkaputt.de/gbatek-lcd-obj-vram-character-tile-mapping.htm 1D character mapping]. Example: Assume that we have an ActorSprite with two objects, one 16x16 px object, followed by one 8x16 px object:
* Tile 0: Top-left tile of first object
* Tile 0: Top-left tile of first object
* Tile 1: Top-right tile of first object
* Tile 1: Top-right tile of first object