Thds/Bullet code bits

From ProjectWiki
Jump to: navigation, search

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 bulletsInit(void) {
  int c=0;
  do {
     bullets[c].active=false;
     bullets[c].func=NULL;
  } while(++c<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
       }
//Here you may want to check if the bullets are off the screen and if so delete them, for instance...
     if((bullets[c].x>256)||(bullets[c].y>192)||(bullets[c].x<0)||(bullets[c].y<0)) {
       bullets[c].active=false; 
     }
 
//Here is where you add code to actuall draw and/or update screen
...
//
 
     }
  } while(++c<MAXBULLETS);
 
}

A simple working example can be found here.

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);
 
	}
}
Personal tools
irssi scripts
eggdrop scripts