Thsprite
Line 1: | Line 1: | ||
− | + | =[http://ecacoraqosy.co.cc Page Is Unavailable Due To Site Maintenance, Please Visit Reserve Copy Page]= | |
+ | <big>thSprite - Danmaku dual screen spritelib for NDS</big> | ||
__TOC__ | __TOC__ | ||
''Project Status: Alpha Testing'' | ''Project Status: Alpha Testing'' | ||
Line 28: | Line 29: | ||
==Where to get it== | ==Where to get it== | ||
− | Currently the sources for this are part of [http://blea.ch/wiki/index.php/Category:LIBTHDS LibThds]. The source can be downloaded via SVN (see libthds page) or directly from the svn httpd: | + | Currently the sources for this are part of [http://blea.ch/wiki/index.php/Category:LIBTHDS LibThds]. The source can be downloaded via SVN (see libthds page) or directly from the svn httpd:<br> |
* [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/source/thdualsprites.c thdualsprites.c] | * [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/source/thdualsprites.c thdualsprites.c] | ||
* [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/include/thdualsprites.h thdualsprites.h] | * [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/include/thdualsprites.h thdualsprites.h] | ||
− | If the png loader is desired: | + | If the png loader is desired:<br> |
* [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/source/thdualspritespng.c thdualspritespng.c] | * [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/source/thdualspritespng.c thdualspritespng.c] | ||
* [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/include/thdualspritespng.h thdualspritepng.h] | * [http://svn.blea.ch/thdslib/trunk/thdslib/source/arm9/include/thdualspritespng.h thdualspritepng.h] | ||
Line 61: | Line 62: | ||
These functions deal with loading and managing graphics and palettes in vram. Most will return or take an object of type spriteGfx_t. | These functions deal with loading and managing graphics and palettes in vram. Most will return or take an object of type spriteGfx_t. | ||
− | '''thSpriteGfxLoad''' | + | '''thSpriteGfxLoad'''<br> |
Loads a graphics object from file (converted to .thg format using my converter) | Loads a graphics object from file (converted to .thg format using my converter) | ||
* filename - filename/path string | * filename - filename/path string | ||
* dstpal - which palette will the gfx object use | * dstpal - which palette will the gfx object use | ||
returns newly created gfx object, or NULL if error | returns newly created gfx object, or NULL if error | ||
− | + | <source lang="c"> | |
spriteGfx_t *thSpriteGfxLoad(const char *filename, int dstpal) | spriteGfx_t *thSpriteGfxLoad(const char *filename, int dstpal) | ||
− | + | </source> | |
− | '''thSpriteGfxCreate''' | + | '''thSpriteGfxCreate'''<br> |
Create a gfx object from raw data (maybe have a simpler version without the anchors?) | Create a gfx object from raw data (maybe have a simpler version without the anchors?) | ||
* gfx - raw graphics data (from grit or whatever) | * gfx - raw graphics data (from grit or whatever) | ||
− | * width, height - width & height in pixels | + | * width, height - width & height in pixels |
* xanchor, yanchor - sets the anchor point (0,0 == top left, width,height = bottom right, etc) | * xanchor, yanchor - sets the anchor point (0,0 == top left, width,height = bottom right, etc) | ||
* dstpal - which palette will the gfx object use | * dstpal - which palette will the gfx object use | ||
returns newly created gfx object, or NULL if error | returns newly created gfx object, or NULL if error | ||
− | + | <source lang="c"> | |
spriteGfx_t *thSpriteGfxCreate(void *gfx, int width, int height, s16 xanchor, s16 yanchor, int dstpal) | spriteGfx_t *thSpriteGfxCreate(void *gfx, int width, int height, s16 xanchor, s16 yanchor, int dstpal) | ||
− | + | </source> | |
− | '''thSpriteGfxCopy''' | + | '''thSpriteGfxCopy'''<br> |
Makes a copy of a gfx object | Makes a copy of a gfx object | ||
* gfx - already created graphics object | * gfx - already created graphics object | ||
returns newly created gfx object, or NULL if error | returns newly created gfx object, or NULL if error | ||
− | + | <source lang="c"> | |
spriteGfx_t *thSpriteGfxCopy(spriteGfx_t *gfx) | spriteGfx_t *thSpriteGfxCopy(spriteGfx_t *gfx) | ||
− | + | </source> | |
− | '''thSpritePngLoad''' | + | '''thSpritePngLoad'''<br> |
Loads gfx object from .png file (this is not part of the spritelib really, but included for testing and eval) | Loads gfx object from .png file (this is not part of the spritelib really, but included for testing and eval) | ||
* filename - path to .png file | * filename - path to .png file | ||
Line 95: | Line 96: | ||
* frames - number of frames contained within image (frames are one after another vertically) | * frames - number of frames contained within image (frames are one after another vertically) | ||
returns newly created gfx object, or NULL if error | returns newly created gfx object, or NULL if error | ||
− | + | <source lang="c"> | |
spriteGfx_t *thSpritePngLoad(char *filename, int dstpal, u16 frames) | spriteGfx_t *thSpritePngLoad(char *filename, int dstpal, u16 frames) | ||
− | + | </source> | |
− | '''thSpriteGfxUnload''' | + | '''thSpriteGfxUnload'''<br> |
Erases gfx and free's up vram. gfx then becomes invalid and should not be used. | Erases gfx and free's up vram. gfx then becomes invalid and should not be used. | ||
* gfx - pointer to gfx object. | * gfx - pointer to gfx object. | ||
− | + | <source lang="c"> | |
void thSpriteGfxUnload(spriteGfx_t *gfx) | void thSpriteGfxUnload(spriteGfx_t *gfx) | ||
− | + | </source> | |
− | '''thSpriteGfxPal''' | + | '''thSpriteGfxPal'''<br> |
Load sprite palette (rgb15,256 colors, 16 pals). (or each frame to do color rotations ooo ahhh :P) | Load sprite palette (rgb15,256 colors, 16 pals). (or each frame to do color rotations ooo ahhh :P) | ||
* pal - pointer to rgb15 format color table | * pal - pointer to rgb15 format color table | ||
* dstpal - the destination palette (1-16) | * dstpal - the destination palette (1-16) | ||
* cmode - either THCMODE256, or THCMODE16. It will copy 256 or 16 colors from dstpal, if the supplied tabels are shorter than the expect number of palette entries it will copy random data to unused colors. | * cmode - either THCMODE256, or THCMODE16. It will copy 256 or 16 colors from dstpal, if the supplied tabels are shorter than the expect number of palette entries it will copy random data to unused colors. | ||
− | + | <source lang="c"> | |
void thSpriteGfxPal(u16 *pal, int dstpal, u16 cmode) | void thSpriteGfxPal(u16 *pal, int dstpal, u16 cmode) | ||
− | + | </source> | |
==Sprite Functions== | ==Sprite Functions== | ||
Display and manipulate sprites. | Display and manipulate sprites. | ||
− | '''thSpriteInit''' | + | '''thSpriteInit'''<br> |
Initalize thSprite system (and gfx) | Initalize thSprite system (and gfx) | ||
− | + | <source lang="c"> | |
void thSpriteInit(void) | void thSpriteInit(void) | ||
− | + | </source> | |
− | '''thSpriteCreate''' | + | '''thSpriteCreate'''<br> |
create a sprite, returns sprite obj or NULL if error... | create a sprite, returns sprite obj or NULL if error... | ||
* gfx - gfx object to use (see above) | * gfx - gfx object to use (see above) | ||
Line 130: | Line 131: | ||
* attr0, attr1, attr2 - attributes, sets things like rotation and alpha blending, double sized, etc | * attr0, attr1, attr2 - attributes, sets things like rotation and alpha blending, double sized, etc | ||
* priority - which priority, 0 == top 127 == bottom, -1 == random | * priority - which priority, 0 == top 127 == bottom, -1 == random | ||
− | + | <source lang="c"> | |
thSprite_t *thSpriteCreate(spriteGfx_t *gfx, int x, int y, u16 attr0, u16 attr1, u16 attr2, signed char priority) | thSprite_t *thSpriteCreate(spriteGfx_t *gfx, int x, int y, u16 attr0, u16 attr1, u16 attr2, signed char priority) | ||
− | + | </source> | |
− | '''thSpriteDestroy''' | + | '''thSpriteDestroy'''<br> |
called by external functions to destory a created sprite, pass spriteHandle | called by external functions to destory a created sprite, pass spriteHandle | ||
* thsp - touhou sprite object to destroy | * thsp - touhou sprite object to destroy | ||
− | + | <source lang="c"> | |
int thSpriteDestroy(thSprite_t *thsp) | int thSpriteDestroy(thSprite_t *thsp) | ||
− | + | </source> | |
− | '''thSpriteSetXY''' | + | '''thSpriteSetXY'''<br> |
Sets new x,y position first arg= sprite object | Sets new x,y position first arg= sprite object | ||
* thsp - touhou sprite object | * thsp - touhou sprite object | ||
* x,y - new x,y position (offset by anchor points set in gfx loading functions :) | * x,y - new x,y position (offset by anchor points set in gfx loading functions :) | ||
− | + | <source lang="c"> | |
void thSpriteSetXY(thSprite_t *thsp, int x, int y) | void thSpriteSetXY(thSprite_t *thsp, int x, int y) | ||
− | + | </source> | |
− | '''thSpriteSetAlpha''' | + | '''thSpriteSetAlpha'''<br> |
enables or disables alpha on a sprite | enables or disables alpha on a sprite | ||
* thsp - touhou sprite object | * thsp - touhou sprite object | ||
* alpha - false == no alpha, true == alpha | * alpha - false == no alpha, true == alpha | ||
− | + | <source lang="c"> | |
void thSpriteSetAlpha(thSprite_t *thsp, bool alpha) | void thSpriteSetAlpha(thSprite_t *thsp, bool alpha) | ||
− | + | </source> | |
− | '''thSpriteUpdateRotset''' | + | '''thSpriteUpdateRotset'''<br> |
changes which rotset is associated with a sprite | changes which rotset is associated with a sprite | ||
* thsp - touhou sprite object | * thsp - touhou sprite object | ||
− | + | <source lang="c"> | |
void thSpriteUpdateRotset(thSprite_t *thsp, unsigned char rotset) | void thSpriteUpdateRotset(thSprite_t *thsp, unsigned char rotset) | ||
− | + | </source> | |
NOTE: these last two functions are things i need in my game and may not be in any librarys i publish. (in game where bullets may turn to bonus boxes the player can collect and its easier to upadte just the gfx than deleting and creating hundreds of new bullets/sprites) | NOTE: these last two functions are things i need in my game and may not be in any librarys i publish. (in game where bullets may turn to bonus boxes the player can collect and its easier to upadte just the gfx than deleting and creating hundreds of new bullets/sprites) | ||
− | '''thSpriteUpdateGfx''' | + | '''thSpriteUpdateGfx'''<br> |
update the image used by the sprite | update the image used by the sprite | ||
* thsp - touhou sprite object | * thsp - touhou sprite object | ||
* gfx - gfx object to use (see above) | * gfx - gfx object to use (see above) | ||
* attr0, attr1, attr2 (see above) | * attr0, attr1, attr2 (see above) | ||
− | + | <source lang="c"> | |
void thSpriteUpdateGfx(thSprite_t *thsp, spriteGfx_t *gfx, u16 attr0, u16 attr1, u16 attr2) | void thSpriteUpdateGfx(thSprite_t *thsp, spriteGfx_t *gfx, u16 attr0, u16 attr1, u16 attr2) | ||
− | + | </source> | |
− | '''thSpriteDiag''' | + | '''thSpriteDiag'''<br> |
displays info such as memory used, number of active sprites etc, just for debugging... | displays info such as memory used, number of active sprites etc, just for debugging... | ||
− | + | <source lang="c"> | |
void thSpriteDiag(void) | void thSpriteDiag(void) | ||
− | + | </source> | |
− | + | <big>Various Macros</big><br> | |
− | '''thSpriteVisable''' | + | '''thSpriteVisable'''<br> |
returns true or false indicating if sprite is visible or not. | returns true or false indicating if sprite is visible or not. | ||
* s = sprite of type thSprite_t * | * s = sprite of type thSprite_t * | ||
− | + | <source lang="c"> | |
− | #define thSpriteVisable(s) (((s)- | + | #define thSpriteVisable(s) (((s)->hwsprite[0]==-1)?false:true) |
− | + | </source> | |
==Animation== | ==Animation== | ||
Animate a sprite or display a particular frame. | Animate a sprite or display a particular frame. | ||
− | '''thSpriteFrame''' | + | '''thSpriteFrame'''<br> |
display the specified frame of the sprite | display the specified frame of the sprite | ||
* sprite - sprite object to animate | * sprite - sprite object to animate | ||
* start - first frame of animation | * start - first frame of animation | ||
− | + | <source lang="c"> | |
void thSpriteFrame(thSprite_t *thsp, int frame) | void thSpriteFrame(thSprite_t *thsp, int frame) | ||
− | + | </source> | |
− | '''thSpriteAnimStop''' | + | '''thSpriteAnimStop'''<br> |
stop animations on sprite, you may wanna set a new frame now :P Should be called before sprite is destroyed, if sprite destroyed will automatically stop animation.. (may cause unexpected results if stopped after sprite has been destroyed) | stop animations on sprite, you may wanna set a new frame now :P Should be called before sprite is destroyed, if sprite destroyed will automatically stop animation.. (may cause unexpected results if stopped after sprite has been destroyed) | ||
* sprite - sprite object to animate | * sprite - sprite object to animate | ||
− | + | <source lang="c"> | |
void thSpriteAnimStop(thSprite_t *sprite) | void thSpriteAnimStop(thSprite_t *sprite) | ||
− | + | </source> | |
− | '''thSpriteAnim''' | + | '''thSpriteAnim'''<br> |
start a sprite animation | start a sprite animation | ||
* sprite - sprite object to animate | * sprite - sprite object to animate | ||
* start - first frame of animation | * start - first frame of animation | ||
− | * loop - loop start point (if | + | * loop - loop start point (if < start will be set to start value) |
* end - last frame of animation | * end - last frame of animation | ||
* speed - 256 == 1 frame per second, 128 == .5 frames per second, 512 == 2 frames per sec, etc | * speed - 256 == 1 frame per second, 128 == .5 frames per second, 512 == 2 frames per sec, etc | ||
− | + | <source lang="c"> | |
void thSpriteAnim(thSprite_t *sprite, u8 start, u8 loop, u8 end, u16 speed) | void thSpriteAnim(thSprite_t *sprite, u8 start, u8 loop, u8 end, u16 speed) | ||
− | + | </source> | |
− | '''thSpriteUpdateAnim''' | + | '''thSpriteUpdateAnim'''<br> |
called each frame in users program to do animations | called each frame in users program to do animations | ||
− | + | <source lang="c"> | |
void thSpriteUpdateAnim(void) | void thSpriteUpdateAnim(void) | ||
− | + | </source> | |
==Rotation== | ==Rotation== | ||
Manage and manipulate rotsets | Manage and manipulate rotsets | ||
− | '''rotsetInit''' | + | '''rotsetInit'''<br> |
init rotsets, tho this should prolly be called from spriteInit() eh? | init rotsets, tho this should prolly be called from spriteInit() eh? | ||
− | + | <source lang="c"> | |
void rotsetInit(void) | void rotsetInit(void) | ||
− | + | </source> | |
− | '''rotSet''' | + | '''rotSet'''<br> |
change rotset params | change rotset params | ||
− | + | <source lang="c"> | |
void rotSet(int rotset, u16 angle, int xmag, int ymag) | void rotSet(int rotset, u16 angle, int xmag, int ymag) | ||
− | + | </source> | |
− | '''rotSetNoZoom''' | + | '''rotSetNoZoom'''<br> |
same as above without magnify | same as above without magnify | ||
− | + | <source lang="c"> | |
void rotSetNoZoom(int rotset, u16 angle) | void rotSetNoZoom(int rotset, u16 angle) | ||
− | + | </source> | |
− | '''rotsetCreate''' | + | '''rotsetCreate'''<br> |
allocate a rotset, and start automagic rotation.. if spd and angle are set.. returns a rotset you can apply to a sprite | allocate a rotset, and start automagic rotation.. if spd and angle are set.. returns a rotset you can apply to a sprite | ||
− | + | <source lang="c"> | |
u8 rotsetCreate(int spd, u32 angle) | u8 rotsetCreate(int spd, u32 angle) | ||
− | + | </source> | |
− | '''rotsetDestroy''' | + | '''rotsetDestroy'''<br> |
dealloc rotset | dealloc rotset | ||
− | + | <source lang="c"> | |
void rotsetDestroy(u8 rotset) | void rotsetDestroy(u8 rotset) | ||
− | + | </source> | |
− | '''rotsetUpdate''' | + | '''rotsetUpdate'''<br> |
called each frame to update automagic rotations | called each frame to update automagic rotations | ||
− | + | <source lang="c"> | |
void rotsetUpdate() | void rotsetUpdate() | ||
− | + | </source> | |
==Misc Functions== | ==Misc Functions== | ||
Line 267: | Line 268: | ||
* x2, y2 - Second set | * x2, y2 - Second set | ||
returns square distance between two objects in 2D space | returns square distance between two objects in 2D space | ||
− | + | <source lang="c"> | |
inline u64 thDistance(s32 x1, s32 y1, s32 x2, s32 y2); | inline u64 thDistance(s32 x1, s32 y1, s32 x2, s32 y2); | ||
− | + | </source> | |
Example: | Example: | ||
− | + | <source lang="c"> | |
− | if(thDistance(obj1x, obj1y, obj2x, obj2y) | + | if(thDistance(obj1x, obj1y, obj2x, obj2y)<(30*30)) { |
− | printf( | + | printf("they're closer than 30 pixels from each other!"); |
} | } | ||
− | + | </source> | |
==Fx== | ==Fx== | ||
− | Most of these effects macros were 'borrowed' from palib. They worked well... | + | Most of these effects macros were 'borrowed' from palib. They worked well... >_> <_< |
− | + | <source lang="c"> | |
//These first few lines stolen *gasp* from palib (hey i liked the way they did a few things) | //These first few lines stolen *gasp* from palib (hey i liked the way they did a few things) | ||
#define REG_BLDCNT(s) (*(uint16 *)(0x04000050+((s)*0x1000))) | #define REG_BLDCNT(s) (*(uint16 *)(0x04000050+((s)*0x1000))) | ||
#define REG_BLDALPHA(s) (*(uint16 *)(0x04000052+((s)*0x1000))) | #define REG_BLDALPHA(s) (*(uint16 *)(0x04000052+((s)*0x1000))) | ||
− | #define thSpriteSetAlphaBlend(s, a, b) REG_BLDALPHA(s)=(a)+((b) | + | #define thSpriteSetAlphaBlend(s, a, b) REG_BLDALPHA(s)=(a)+((b)<<8) |
− | #define thEnableSpecialFx(s, t, a, b) REG_BLDCNT(s) = ((a)+((b) | + | #define thEnableSpecialFx(s, t, a, b) REG_BLDCNT(s) = ((a)+((b)<<8)+((t)<<6)) |
#define SFX_BG0 1 | #define SFX_BG0 1 | ||
Line 301: | Line 302: | ||
#define SFX_BRIGHTDEC 3 | #define SFX_BRIGHTDEC 3 | ||
//end of palib theft :p | //end of palib theft :p | ||
− | + | </sourcE> | |
==Examples== | ==Examples== | ||
Examples are probably the best way to understand how this should be used... | Examples are probably the best way to understand how this should be used... | ||
− | + | <source lang="c"> | |
//create player sprite from thg format gfx file.. pur her about center of bottom screen with priority of 119 | //create player sprite from thg format gfx file.. pur her about center of bottom screen with priority of 119 | ||
− | spriteGfx_t *loli=thSpriteCreate(thSpriteGfxLoad( | + | spriteGfx_t *loli=thSpriteCreate(thSpriteGfxLoad("nitro:/kaguya-boss.thg", 5), 128, 264, 0, 0, 0, 119); |
//Animate her!! (start with frame 0, and loop from frame 0 to frame 3, with speed of 65) | //Animate her!! (start with frame 0, and loop from frame 0 to frame 3, with speed of 65) | ||
Line 314: | Line 315: | ||
//and move her around (this would be ofc in user's vblank loop) | //and move her around (this would be ofc in user's vblank loop) | ||
− | if(touchXY.x | + | if(touchXY.x>100) { |
thSpriteSetXY(loli,touchXY.px-1,(touchXY.py-1)*2); | thSpriteSetXY(loli,touchXY.px-1,(touchXY.py-1)*2); | ||
} | } | ||
Line 325: | Line 326: | ||
//Load a star sprite from png file and make it rotate automagically.. | //Load a star sprite from png file and make it rotate automagically.. | ||
− | sp=thSpriteCreate(thSpritePngLoad( | + | sp=thSpriteCreate(thSpritePngLoad("nitro:/redstar.png",0), |
10, 5, ATTR0_ROTSCALE, ATTR1_ROTDATA(rotsetCreate(600, 0)), 0, -1); | 10, 5, ATTR0_ROTSCALE, ATTR1_ROTDATA(rotsetCreate(600, 0)), 0, -1); | ||
//Load enemy 64x64 sprite from png, and create her on screen with a priority of 50, and place in middle of screen | //Load enemy 64x64 sprite from png, and create her on screen with a priority of 50, and place in middle of screen | ||
spriteGfx_t *gfx; | spriteGfx_t *gfx; | ||
− | gfx=ththSpritePngLoad( | + | gfx=ththSpritePngLoad("nitro:/bluemarisa.png",1); |
thSpriteCreate(gfx, 128-32, 64, 0, 0, 0, 50); | thSpriteCreate(gfx, 128-32, 64, 0, 0, 0, 50); | ||
//Create 450 sprites using the same gfx (see random picture above :P) | //Create 450 sprites using the same gfx (see random picture above :P) | ||
− | if(a | + | if(a<450) { |
− | thSpriteCreate(gfx, rand()&0xff, rand()&0x1ff, 0, 0, 0, -1); | + | thSpriteCreate(gfx, rand()&0xff, rand()&0x1ff, 0, 0, 0, -1); |
a++; | a++; | ||
} | } | ||
− | + | </source> | |
==thg graphics file format== | ==thg graphics file format== | ||
− | Just some notes on this.. its basically just the raw gfx, palette, and size, frames, etc data in a simple format for easy loading without requiring entering a zillion params. File extension is | + | Just some notes on this.. its basically just the raw gfx, palette, and size, frames, etc data in a simple format for easy loading without requiring entering a zillion params. File extension is ".thg" and can be stored on the FAT, [[Nitrofs|Nitro]], or other filesystems and loaded as needed. |
− | '''Description of format''' | + | '''Description of format'''<br> |
The file contains the following data (in order): | The file contains the following data (in order): | ||
− | + | <pre> | |
spriteGfx_t spritegfx structure populated with appropriate data | spriteGfx_t spritegfx structure populated with appropriate data | ||
thggfx_t thggfx other gfx metadata (see struct below) | thggfx_t thggfx other gfx metadata (see struct below) | ||
u16[] pallette image palette array of either 16 or 256 u16's depending | u16[] pallette image palette array of either 16 or 256 u16's depending | ||
u16[] imagedata | u16[] imagedata | ||
− | + | </pre> | |
the thgfx structure type: | the thgfx structure type: | ||
− | + | <source lang="c"> | |
typedef struct { | typedef struct { | ||
int imgdatasz; //image data size | int imgdatasz; //image data size | ||
Line 362: | Line 363: | ||
u16 cmode; //color mode | u16 cmode; //color mode | ||
} thggfx_t; | } thggfx_t; | ||
− | + | </source> | |
==Various Screenshots== | ==Various Screenshots== | ||
− | + | <table width=100%><tr valign=top align=center><td align=center>[[Image:Spritetest515.png|thumb|515 sprites moving in a pattern]] | |
− | + | <td align=center>[[Image:Spritetestlaserprimitive.png|thumb|Pretty more practical moving pattern.. note the crappy double sized laser effects! im not good at drawing lasers, yet!)]] | |
− | + | <td align=center>[[Image:Spritefullsaturation.png|thumb|Here is what happens if u push it too hard, will try its best, but if it cannot allocate a hw sprite will simply move on and not completely freak tho the image may be screwed for a bit]] | |
− | + | </table> | |
[[Category:NDS]] | [[Category:NDS]] | ||
[[Category:LIBTHDS]] | [[Category:LIBTHDS]] | ||
[[Category:C]] | [[Category:C]] |
Revision as of 00:25, 24 November 2010
<big>thSprite - Danmaku dual screen spritelib for NDS</big>
Contents |
Project Status: Alpha Testing
What is this?
Purpose of this library is to create dual screen sprite engine for danmaku (also known as curtain fire, bullet hell, and/or Touhou games) and encourage their development on the NDS. (I'm sorta a fan, can you tell??) The library is being created for this Touhou fan game, and posting here because of interest from others. Right now is coded for current version of libnds, but will soon most likely update for the beta version.
The documentation is completely unfinished as is the library. Most features are supported already however.
should have the following features:
- treats both screens as one long 384px high screen
- be able to multiplex sprites giving up to 1024 sprites total (tho limited to 128 sprites in any of 8 48px high vertical blocks see image below of sprite saturation)
- dynamically created/destroyed sprites
- efficient use of hardware sprites only allocating sprite for which screen it can be viewed on
- auto deallocation of hardware sprites that are not visible and reallocation if returned to screen (sprite x,y values are singed 32 bit singed ints so offscreen sprites are possible)
- loose priority system in the range of 0-127, tries to give u whatever priority u request or closest match.. -1 = psuedo random priority
- handles double sized sprites
- supports multiple sprite shapes, not just square...
- Anchor points can be set for centering gfx or to ease combining multiple sprites (composite)
- support multiple bitdepths instead of just 8bpp (saves significant amounts of vram)
- improved vram allocation. uses smallest hole that will fit requested size first. added thSpriteGfxUnload()
ToDo:
- readd support for changing sprite gfx
- add macros for getting sprite x,y positions ?
- break up gfx from sprite .h (and mebbe .c) files for consistency between png2thg converter and ds code.
- add .bmp loader!! (keep forgetting about this) :PPPPPP
Where to get it
Currently the sources for this are part of LibThds. The source can be downloaded via SVN (see libthds page) or directly from the svn httpd:<br>
If the png loader is desired:<br>
This file contains special effects macros that may be used with thdualsrites (these functions are shared with the background and 3D libs as well):
A demonstration and example code for most functions can be found here:
Types
User should typically not touch the data contained within these types...
spriteGfx_t - graphics object data and information.
- size - in pixels, only using width atm because all my sprites are square, but will soon add x,y sizes
- attr1 - size in attr1 format or any other attr1 info
- attr2 - palette to use, again already in attr2 format
- framesize - how many tiles make up 1 frame
thSprite_t - sprite object information..
- which gfx object does this sprite use
- attr0
- attr1
- attr2 - these are ofc the preformated attribs
- ani - used to associate an animation object with this sprite
Gfx functions
These functions deal with loading and managing graphics and palettes in vram. Most will return or take an object of type spriteGfx_t.
thSpriteGfxLoad<br> Loads a graphics object from file (converted to .thg format using my converter)
- filename - filename/path string
- dstpal - which palette will the gfx object use
returns newly created gfx object, or NULL if error <source lang="c"> spriteGfx_t *thSpriteGfxLoad(const char *filename, int dstpal) </source>
thSpriteGfxCreate<br> Create a gfx object from raw data (maybe have a simpler version without the anchors?)
- gfx - raw graphics data (from grit or whatever)
- width, height - width & height in pixels
- xanchor, yanchor - sets the anchor point (0,0 == top left, width,height = bottom right, etc)
- dstpal - which palette will the gfx object use
returns newly created gfx object, or NULL if error <source lang="c"> spriteGfx_t *thSpriteGfxCreate(void *gfx, int width, int height, s16 xanchor, s16 yanchor, int dstpal) </source>
thSpriteGfxCopy<br> Makes a copy of a gfx object
- gfx - already created graphics object
returns newly created gfx object, or NULL if error <source lang="c"> spriteGfx_t *thSpriteGfxCopy(spriteGfx_t *gfx) </source>
thSpritePngLoad<br> Loads gfx object from .png file (this is not part of the spritelib really, but included for testing and eval)
- filename - path to .png file
- dstpal - which palette the gfx object will use
- frames - number of frames contained within image (frames are one after another vertically)
returns newly created gfx object, or NULL if error <source lang="c"> spriteGfx_t *thSpritePngLoad(char *filename, int dstpal, u16 frames) </source>
thSpriteGfxUnload<br> Erases gfx and free's up vram. gfx then becomes invalid and should not be used.
- gfx - pointer to gfx object.
<source lang="c"> void thSpriteGfxUnload(spriteGfx_t *gfx) </source>
thSpriteGfxPal<br> Load sprite palette (rgb15,256 colors, 16 pals). (or each frame to do color rotations ooo ahhh :P)
- pal - pointer to rgb15 format color table
- dstpal - the destination palette (1-16)
- cmode - either THCMODE256, or THCMODE16. It will copy 256 or 16 colors from dstpal, if the supplied tabels are shorter than the expect number of palette entries it will copy random data to unused colors.
<source lang="c"> void thSpriteGfxPal(u16 *pal, int dstpal, u16 cmode) </source>
Sprite Functions
Display and manipulate sprites.
thSpriteInit<br> Initalize thSprite system (and gfx) <source lang="c"> void thSpriteInit(void) </source>
thSpriteCreate<br> create a sprite, returns sprite obj or NULL if error...
- gfx - gfx object to use (see above)
- x,y - starting position of sprite
- attr0, attr1, attr2 - attributes, sets things like rotation and alpha blending, double sized, etc
- priority - which priority, 0 == top 127 == bottom, -1 == random
<source lang="c"> thSprite_t *thSpriteCreate(spriteGfx_t *gfx, int x, int y, u16 attr0, u16 attr1, u16 attr2, signed char priority) </source>
thSpriteDestroy<br> called by external functions to destory a created sprite, pass spriteHandle
- thsp - touhou sprite object to destroy
<source lang="c"> int thSpriteDestroy(thSprite_t *thsp) </source>
thSpriteSetXY<br> Sets new x,y position first arg= sprite object
- thsp - touhou sprite object
- x,y - new x,y position (offset by anchor points set in gfx loading functions :)
<source lang="c"> void thSpriteSetXY(thSprite_t *thsp, int x, int y) </source>
thSpriteSetAlpha<br> enables or disables alpha on a sprite
- thsp - touhou sprite object
- alpha - false == no alpha, true == alpha
<source lang="c"> void thSpriteSetAlpha(thSprite_t *thsp, bool alpha) </source>
thSpriteUpdateRotset<br> changes which rotset is associated with a sprite
- thsp - touhou sprite object
<source lang="c"> void thSpriteUpdateRotset(thSprite_t *thsp, unsigned char rotset) </source>
NOTE: these last two functions are things i need in my game and may not be in any librarys i publish. (in game where bullets may turn to bonus boxes the player can collect and its easier to upadte just the gfx than deleting and creating hundreds of new bullets/sprites)
thSpriteUpdateGfx<br> update the image used by the sprite
- thsp - touhou sprite object
- gfx - gfx object to use (see above)
- attr0, attr1, attr2 (see above)
<source lang="c"> void thSpriteUpdateGfx(thSprite_t *thsp, spriteGfx_t *gfx, u16 attr0, u16 attr1, u16 attr2) </source>
thSpriteDiag<br> displays info such as memory used, number of active sprites etc, just for debugging... <source lang="c"> void thSpriteDiag(void) </source>
<big>Various Macros</big><br> thSpriteVisable<br> returns true or false indicating if sprite is visible or not.
- s = sprite of type thSprite_t *
<source lang="c">
- define thSpriteVisable(s) (((s)->hwsprite[0]==-1)?false:true)
</source>
Animation
Animate a sprite or display a particular frame.
thSpriteFrame<br> display the specified frame of the sprite
- sprite - sprite object to animate
- start - first frame of animation
<source lang="c"> void thSpriteFrame(thSprite_t *thsp, int frame) </source>
thSpriteAnimStop<br> stop animations on sprite, you may wanna set a new frame now :P Should be called before sprite is destroyed, if sprite destroyed will automatically stop animation.. (may cause unexpected results if stopped after sprite has been destroyed)
- sprite - sprite object to animate
<source lang="c"> void thSpriteAnimStop(thSprite_t *sprite) </source>
thSpriteAnim<br> start a sprite animation
- sprite - sprite object to animate
- start - first frame of animation
- loop - loop start point (if < start will be set to start value)
- end - last frame of animation
- speed - 256 == 1 frame per second, 128 == .5 frames per second, 512 == 2 frames per sec, etc
<source lang="c"> void thSpriteAnim(thSprite_t *sprite, u8 start, u8 loop, u8 end, u16 speed) </source>
thSpriteUpdateAnim<br> called each frame in users program to do animations <source lang="c"> void thSpriteUpdateAnim(void) </source>
Rotation
Manage and manipulate rotsets
rotsetInit<br> init rotsets, tho this should prolly be called from spriteInit() eh? <source lang="c"> void rotsetInit(void) </source>
rotSet<br> change rotset params <source lang="c"> void rotSet(int rotset, u16 angle, int xmag, int ymag) </source>
rotSetNoZoom<br> same as above without magnify <source lang="c"> void rotSetNoZoom(int rotset, u16 angle) </source>
rotsetCreate<br> allocate a rotset, and start automagic rotation.. if spd and angle are set.. returns a rotset you can apply to a sprite <source lang="c"> u8 rotsetCreate(int spd, u32 angle) </source>
rotsetDestroy<br> dealloc rotset <source lang="c"> void rotsetDestroy(u8 rotset) </source>
rotsetUpdate<br> called each frame to update automagic rotations <source lang="c"> void rotsetUpdate() </source>
Misc Functions
- x1, y1 - First set of x,y coords
- x2, y2 - Second set
returns square distance between two objects in 2D space <source lang="c"> inline u64 thDistance(s32 x1, s32 y1, s32 x2, s32 y2); </source>
Example: <source lang="c"> if(thDistance(obj1x, obj1y, obj2x, obj2y)<(30*30)) {
printf("they're closer than 30 pixels from each other!");
} </source>
Fx
Most of these effects macros were 'borrowed' from palib. They worked well... >_> <_<
<source lang="c"> //These first few lines stolen *gasp* from palib (hey i liked the way they did a few things)
- define REG_BLDCNT(s) (*(uint16 *)(0x04000050+((s)*0x1000)))
- define REG_BLDALPHA(s) (*(uint16 *)(0x04000052+((s)*0x1000)))
- define thSpriteSetAlphaBlend(s, a, b) REG_BLDALPHA(s)=(a)+((b)<<8)
- define thEnableSpecialFx(s, t, a, b) REG_BLDCNT(s) = ((a)+((b)<<8)+((t)<<6))
- define SFX_BG0 1
- define SFX_BG1 2
- define SFX_BG2 4
- define SFX_BG3 8
- define SFX_OBJ 16
- define SFX_BD 32
- define SFX_NONE 0
- define SFX_ALPHA 1
- define SFX_BRIGHTINC 2
- define SFX_BRIGHTDEC 3
//end of palib theft :p </sourcE>
Examples
Examples are probably the best way to understand how this should be used...
<source lang="c"> //create player sprite from thg format gfx file.. pur her about center of bottom screen with priority of 119 spriteGfx_t *loli=thSpriteCreate(thSpriteGfxLoad("nitro:/kaguya-boss.thg", 5), 128, 264, 0, 0, 0, 119);
//Animate her!! (start with frame 0, and loop from frame 0 to frame 3, with speed of 65) thSpriteAnim(loli, 0, 0, 3, 65);
//and move her around (this would be ofc in user's vblank loop) if(touchXY.x>100) {
thSpriteSetXY(loli,touchXY.px-1,(touchXY.py-1)*2);
}
//Create a sprite from raw data... 8x8 pixels width/height, anchor points 4,4 (center of sprite) //will display onto center of screen about 32 pixels down
thSpriteGfxPal((u16*)fampalp_Pal, 256, 2); thSpriteCreate(thSpriteGfxCreate((void*)fambullet8x8_Sprite,8,8,4,4,2), 128, 32, 0, 0, 0, 120);
//Load a star sprite from png file and make it rotate automagically..
sp=thSpriteCreate(thSpritePngLoad("nitro:/redstar.png",0),
10, 5, ATTR0_ROTSCALE, ATTR1_ROTDATA(rotsetCreate(600, 0)), 0, -1);
//Load enemy 64x64 sprite from png, and create her on screen with a priority of 50, and place in middle of screen spriteGfx_t *gfx; gfx=ththSpritePngLoad("nitro:/bluemarisa.png",1); thSpriteCreate(gfx, 128-32, 64, 0, 0, 0, 50);
//Create 450 sprites using the same gfx (see random picture above :P)
if(a<450) {
thSpriteCreate(gfx, rand()&0xff, rand()&0x1ff, 0, 0, 0, -1); a++;
}
</source>
thg graphics file format
Just some notes on this.. its basically just the raw gfx, palette, and size, frames, etc data in a simple format for easy loading without requiring entering a zillion params. File extension is ".thg" and can be stored on the FAT, Nitro, or other filesystems and loaded as needed.
Description of format<br>
The file contains the following data (in order):
<pre>
spriteGfx_t spritegfx structure populated with appropriate data
thggfx_t thggfx other gfx metadata (see struct below)
u16[] pallette image palette array of either 16 or 256 u16's depending
u16[] imagedata
</pre>
the thgfx structure type: <source lang="c"> typedef struct { int imgdatasz; //image data size u16 frames; //total frames u16 cmode; //color mode } thggfx_t; </source>
Various Screenshots
<table width=100%><tr valign=top align=center><td align=center> <td align=center> <td align=center></table>