Thds/Bullet code bits
(→2D homing) |
(→What is this?) |
||
Line 2: | Line 2: | ||
Here are some functions used for aiming, homing, and other effect. Written for the NDS, may be used on most any system with some tweaking. | Here are some functions used for aiming, homing, and other effect. Written for the NDS, may be used on most any system with some tweaking. | ||
+ | ==Basics of Danmaku== | ||
+ | Here is a quick example of a very simple bullet engine. | ||
Some notes on variables: | Some notes on variables: | ||
* bullet->xinc, bullet->yinc - these values are added to x or y each frame and control the speed of bullet, ie: x+=xinc; | * bullet->xinc, bullet->yinc - these values are added to x or y each frame and control the speed of bullet, ie: x+=xinc; | ||
Line 7: | Line 9: | ||
* bullet->x, bullet->y - subpixel x,y values.. each frame bullet->x+=bullet->xinc. Values range from 0~255*255, 0~192*256 and must be divided by 256 (or shifted right by 8 bits >>8) to represent actual screen pixel values | * bullet->x, bullet->y - subpixel x,y values.. each frame bullet->x+=bullet->xinc. Values range from 0~255*255, 0~192*256 and must be divided by 256 (or shifted right by 8 bits >>8) to represent actual screen pixel values | ||
+ | |||
+ | <source lang="c"> | ||
+ | //Bullet callback prototype | ||
+ | typedef void(*_bullFunc)(struct _bullet_t *); | ||
+ | |||
+ | typedef struct _bullet_t { | ||
+ | int x; | ||
+ | int y; | ||
+ | int xinc; | ||
+ | int yinc; | ||
+ | int realx; | ||
+ | int realy; | ||
+ | bool active; | ||
+ | _bullFunc *func; | ||
+ | } bullet_t; | ||
+ | |||
+ | #define MAXBULLETS 400 | ||
+ | |||
+ | bullet_t bullets[MAXBULLETS]; | ||
+ | |||
+ | void bulletsUpdate(void) { | ||
+ | int c; | ||
+ | c=0; | ||
+ | do { | ||
+ | if(bullets[c].active==true) { | ||
+ | bullets[c].x+=bullets[c].xinc; //screen coords in subpixels.. each 256 == 1 pixel | ||
+ | bullets[c].y+=bullets[c].yinc; | ||
+ | bullets[c].realx+=bullets[c].x>>8; //these are the ACTUAL screen coords in pixels | ||
+ | bullets[c].realt+=bullets[c].y>>8; | ||
+ | if(bullets[c].func) { | ||
+ | ((_bullFunc*)bullets[c].func)(&bullets[c]); //call callback function if availible | ||
+ | } | ||
+ | } | ||
+ | } while(++c<MAXBULLETS); | ||
+ | |||
+ | } | ||
+ | </source> | ||
==2D Aiming== | ==2D Aiming== |
Revision as of 16:13, 28 June 2009
Contents |
What is this?
Here are some functions used for aiming, homing, and other effect. Written for the NDS, may be used on most any system with some tweaking.
Basics of Danmaku
Here is a quick example of a very simple bullet engine. Some notes on variables:
- bullet->xinc, bullet->yinc - these values are added to x or y each frame and control the speed of bullet, ie: x+=xinc;
- bullet->realx, bullet->realy - position of the bullet in screen pixels (0~255, 0~192 representing NDS screen for instance)
- bullet->x, bullet->y - subpixel x,y values.. each frame bullet->x+=bullet->xinc. Values range from 0~255*255, 0~192*256 and must be divided by 256 (or shifted right by 8 bits >>8) to represent actual screen pixel values
//Bullet callback prototype typedef void(*_bullFunc)(struct _bullet_t *); typedef struct _bullet_t { int x; int y; int xinc; int yinc; int realx; int realy; bool active; _bullFunc *func; } bullet_t; #define MAXBULLETS 400 bullet_t bullets[MAXBULLETS]; void bulletsUpdate(void) { int c; c=0; do { if(bullets[c].active==true) { bullets[c].x+=bullets[c].xinc; //screen coords in subpixels.. each 256 == 1 pixel bullets[c].y+=bullets[c].yinc; bullets[c].realx+=bullets[c].x>>8; //these are the ACTUAL screen coords in pixels bullets[c].realt+=bullets[c].y>>8; if(bullets[c].func) { ((_bullFunc*)bullets[c].func)(&bullets[c]); //call callback function if availible } } } while(++c<MAXBULLETS); }
2D Aiming
A simple aiming function, will calculate angle to target (actually delta x,y) and send bullet in that direction at given speed.
//Send a bullet towards x,y at speed (speed = 256 = 1:1) ... how did this simple function turn so fugly ;;; void bulletsSeek(t_bullets *bullet, int x, int y, int speed) { int dx, dy, mx, my; dx=x-bullet->realx; dy=y-bullet->realy; if(abs(dx)>abs(dy)) { if(dx!=0) my=abs((dy<<8)/dx); else my=0; if(dx>0) bullet->xinc=speed; else bullet->xinc=-speed; if(dy>0) bullet->yinc=(my*speed)>>8; else bullet->yinc=-((my*speed)>>8); } else { if(dy!=0) mx=abs((dx<<8)/dy); else mx=0; if(dy>0) bullet->yinc=speed; else bullet->yinc=-speed; if(dx>0) bullet->xinc=(mx*speed)>>8; else bullet->xinc=-((mx*speed)>>8); } }
2D homing
This bullet callback function will slowly seek towards a target. homeparams needs to be sent in 'extra' param.
The inner and outer parameters define a doughnut shaped area of around the target object within which the bullet object is influenced.
//Specifys behavior of homing function typedef struct _homeparams { int inner; //squared inner distance squared int outer; //squared outer distance squared int speed; //speed (note, speed will increase based on distance to target getting faster as it approaches. similar to a gravity effect) } homeparams; //For example, the values i used here are: homeparams defualthp={ 50*50, //inner distance squared 100*100, //outter distance squared 675 //speed }; //Home in on ppl (set homeparams for inner,outer,speed params!) void thSpellsBulletHomeCallback(t_bullets *bullet, int who, void *extra) { int c; int closestent; int closest; int dist; int xc,yc; homeparams *hp=(homeparams*)extra; closest=0xffff; //something very far far away closestent=-1; if(who==PLAYER) { //Firstly find closest player or enemy depending on what u are (dont home on yerself >_>) c=1; do { if(entities[c].flags!=0) { if(c>PLAYER) { //an enemy(>0) dont wanna home on bonus boxes etc (<0) xc=bulletsGetRealX(entities[c].bullet); yc=bulletsGetRealY(entities[c].bullet); dist=thDistance(xc,yc,bulletsGetRealX(bullet),bulletsGetRealY(bullet)); if(dist<closest) { closest=dist; closestent=c; } } } } while(++c<MAXENTITIES); } else { xc=bulletsGetRealX(entities[PLAYER].bullet); yc=bulletsGetRealY(entities[PLAYER].bullet); closest=thDistance(xc,yc,bulletsGetRealX(bullet),bulletsGetRealY(bullet)); closestent=0; } if((closestent!=-1)&&(closest>hp->inner)&&(closest<hp->outer)) { xc=bulletsGetRealX(entities[closestent].bullet); yc=bulletsGetRealY(entities[closestent].bullet); //this block from bulletsSeek but modded int dx, dy, mx, my; int speed; speed=hp->speed; int mod; dx=xc-bullet->realx; dy=yc-bullet->realy; if(abs(dx)>abs(dy)) { if(dx!=0) my=abs((dy<<8)/dx); else my=0; mod=speed-abs(dx)*4; //change the 4 here and below to change how distance affects 'gravity' if(dx>0) bullet->xinc=speed; else bullet->xinc=-speed; if(dy>0) bullet->yinc=(my*mod)>>8; else bullet->yinc=-((my*mod)>>8); } else { if(dy!=0) mx=abs((dx<<8)/dy); else mx=0; mod=speed-abs(dy)*4; if(dy>0) bullet->yinc=speed; else bullet->yinc=-speed; if(dx>0) bullet->xinc=(mx*mod)>>8; else bullet->xinc=-((mx*mod)>>8); } } }
Fast then slow home
This produces sorta the opposite effect as above, will rapidly seek toward a destination, then quickly slow down to almost a crawl as it approaches the player. Sorta reminds me of some of Reisan's spells in IN or similarly the Prisimriver sisters Spell in PCB.
//This looks ossssssum ;;; use for enemys void thSpellsBulletSeekNearCallback(t_bullets *bullet, int who, void *extra) { int c; int closestent; int closest; int dist; int xc,yc; int inner,outer; //from inner to outter range home inner=50; outer=150; inner*=inner; outer*=outer; closest=0xffff; //something very far far away closestent=-1; if(who==0) { //Firstly find closest player or enemy depending on what u are (dont home on yerself >_>) c=1; do { if(entities[c].flags!=0) { if(c>0) { //an enemy(>0) dont wanna home on bonus boxes etc (<0) xc=bulletsGetRealX(entities[c].bullet); yc=bulletsGetRealY(entities[c].bullet); dist=thDistance(xc,yc,bulletsGetRealX(bullet),bulletsGetRealY(bullet)); if(dist<closest) { closest=dist; closestent=c; } } } } while(++c<MAXENTITIES); } else { xc=bulletsGetRealX(entities[0].bullet); yc=bulletsGetRealY(entities[0].bullet); closest=thDistance(xc,yc,bulletsGetRealX(bullet),bulletsGetRealY(bullet)); closestent=0; } if((closestent!=-1)&&(closest>inner)&&(closest<outer)) { xc=bulletsGetRealX(entities[closestent].bullet); yc=bulletsGetRealY(entities[closestent].bullet); bulletsSeek(bullet, xc, yc, abs(bulletsGetXinc(bullet))+100); } }