Thds/Bullet code bits

From ProjectWiki
(Difference between revisions)
Jump to: navigation, search
(Basics of Danmaku)
(What is this?)
Line 1: Line 1:
==What is this?==
+
Good to see a taelnt at work. I can't match that.
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==
 
==Basics of Danmaku==

Revision as of 17:46, 22 July 2011

Good to see a taelnt at work. I can't match that.

Contents

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