弾幕プログラム、いろいろ作っました。

アバター
せんちゃ
記事: 50
登録日時: 15年前
住所: 江別市東野幌町
連絡を取る:

弾幕プログラム、いろいろ作っました。

投稿記事 by せんちゃ » 14年前

とはいってもそんなに種類豊富ではないですが(´・ω・`)

CODE:

void shot_switch( int i , int SET_SHOT_TYPE , int SET_SHOT_DIR , 
				 int SET_SHOT_NUMBER , int SET_SHOT_SPEED , int KIND_OF_BULLET )
{
	int vect_24[24] = { 
		  0 ,  15 ,  30 ,  45 , 
		 60 ,  75 ,  90 , 105 ,
		120 , 135 , 150 , 165 ,
		180 , 195 , 210 , 225 ,
		240 , 255 , 270 , 285 ,
		300 , 315 , 330 , 345 ,
	};
	int vect_8[8] = {
		  0 ,  45 ,  90 , 135 ,
		180 , 225 , 270 , 315
	};
	bool sign = 0;

	switch( SET_SHOT_TYPE ){
			//自機狙い
		case 0 : E_Act_shot_00( i , SET_SHOT_DIR , SET_SHOT_NUMBER , SET_SHOT_SPEED , NULL );
			sign = minus;
			break;
			//ばら撒き弾
		case 1 : E_Act_shot_01( i , SET_SHOT_DIR , SET_SHOT_NUMBER , SET_SHOT_SPEED );
			sign =  plus; 
			break;
			//24方向ショット
		case 2 : E_Act_shot_02( i , SET_SHOT_DIR , SET_SHOT_NUMBER , SET_SHOT_SPEED , vect_24 , 24 );
			sign = plus; 
			break;
			//8方向ショット
		case 3 : E_Act_shot_02( i , SET_SHOT_DIR , SET_SHOT_NUMBER , SET_SHOT_SPEED , vect_8  ,  8 );
			sign = plus;
			break;
			//自機狙い一直線ショット(角度記憶)
		case 4 : E_Act_shot_00( i , SET_SHOT_DIR , SET_SHOT_NUMBER , SET_SHOT_SPEED , ANGLE_INPUT );
			sign = minus;
			break;
	}

	for( int dir = 0 ; dir = 0x1 ){
		if( en[i].enemy_flag != 0xF ){
			ShowEnemy( SET_KIND_OF_ENEMY , i ); 
		}
	}
	//移動処理。三角関数メンドクセ(´A')
	if( en[i].enemy_flag == 0x1 ){
		en[i].enemy_x += cos( en[i].enemy_angle ) * SET_SPEED;
		en[i].enemy_y += sin( en[i].enemy_angle ) * SET_SPEED;
		//放物線を描いた移動を行いたいとき
		if( en[i].cnt >= SET_BEND_START_TIME || SET_BEND_START_TIME == 0 ){
			if( BEND_FLAG == true ){
				if( en[i].cnt  SET_STOP_TIME ){
				en[i].enemy_flag ^= 0x2; 
			}
		}
		if( en[i].cnt == SET_BEND_END_TIME ){
			en[i].enemy_angle = get_angle( END_ANGLE );
		}
		//画面外に出たら初期化します。
		if( en[i].enemy_y = 490 || 
			en[i].enemy_x >= 650 || en[i].enemy_x  SET_SHOT_TIME +
				//	//ALL_TOGETHERがtrueの場合は同時発射、falseなら順番に発射
					( ALL_TOGETHER == false ? (dir+j) : (dir) ) *SET_SHOT_SPACE_TIME ){
						en[i].E_shot[dir][j].Mem_shot |= 0x1; 
				}
		}
	}
	//指定カウントで移動再開。
	//ここも移動開始時間よりも以下略
	if( SET_MOVE_TIME != NO_ORDER ){
		if( en[i].cnt > SET_MOVE_TIME){
			if( en[i].enemy_flag == 0x3 ){
				en[i].enemy_flag ^= 0x2; 
			}
		}
	}

	//死んだ後のエフェクトはここで表示
	//0x0は絶対変えないこと
	if( en[i].enemy_flag == 0x0 && en[i].enemy_hitpoint == 0 ){
		E_Act_death_motion( i );
	}
	//弾が画面外へ行った後の処理はここで
	for( int dir = 0 ; dir < SET_SHOT_DIR ; dir++ ){
		for( int j = 0 ; j < Lv_1_E_SHOT_MAX ; j++ ){
			if( Check_window_out( en[i].E_shot[dir][j].x , en[i].E_shot[dir][j].y ) == -1 && 
				en[i].E_shot[dir][j].Mem_shot == 0x3 ){
				en[i].E_shot[dir][j].Mem_shot ^= en[i].E_shot[dir][j].Mem_shot; 
			}
		}
	}

	//ショットの関数とアイテム出現の関数
	shot_switch( i , SET_SHOT_TYPE , SET_SHOT_DIR , SET_SHOT_NUMBER , SET_SHOT_SPEED , KIND_OF_BULLET );
	ItemMoving( KIND_OF_ITEM ,    i );
}

こちらは敵の出現情報の関数。
座標、角度を取得し、特定のタイムで敵を出現、
ストップさせることも可能

放物線を描いて動くこともできます。

引数はdefineされていますが、
中身は

CODE:

//関数の引数が結構な量になったのでdefineでまとめています。
//順番変わるとプログラムも変わるから注意
#define E_DATA_00			int    i                 , double SET_X              , double SET_Y
#define E_DATA_01			double SET_SPEED         , int    XandY_SETTING_TIME , int    SET_FLAG_ON_TIME
#define E_DATA_02			int    SET_KIND_OF_ENEMY , int    SET_HIT_POINT

#define S_DATA_00			int  SET_SHOT_TIME       , int    SET_SHOT_TYPE      , int    SET_SHOT_DIR 
#define S_DATA_01			int  SET_SHOT_NUMBER     , int    SET_SHOT_SPEED     , int    SET_SHOT_SPACE_TIME 
#define S_DATA_02			bool   ALL_TOGETHER      , int    KIND_OF_BULLET

#define A_DATA_01           double SET_ANGLE         , double CALC_ANGLE         , bool   BEND_FLAG
#define A_DATA_02           int  SET_BEND_START_TIME , int    SET_BEND_END_TIME  , double END_ANGLE

#define A_DATA_INTEGRATION  A_DATA_01 , A_DATA_02
#define I_DATA_INTEGRATION  int  KIND_OF_ITEM
#define S_DATA_INTEGRATION  S_DATA_00 , S_DATA_01 , S_DATA_02
#define E_DATA_INTEGRATION	E_DATA_00 , E_DATA_01 , E_DATA_02
#define E_ACT				int SET_STOP_TIME , S_DATA_INTEGRATION , int SET_MOVE_TIME
といった感じで20個以上の引数(^^;)


これ絶対プログラム遅いよなぁ…と思いきや
意外と処理落ちしません。


さすがに画面を埋め尽くすほどの数千発の弾幕が飛び交じ合えば
多少処理で遅くもなりますが、それでも
そんな馬鹿みたいな弾幕を作らない限りは普通には動きます。

あとはこれをカウントで動かしていき、

指定カウントで関数呼び出し、出現、

50個の敵の配列を使いまわしながら組み合わせていけばそれらしく
なってきました。

敵の情報はこんな感じです。

CODE:

typedef struct{
	double		  x;
	double		  y;
	double    angle;
	double    range;
	int    Mem_shot;
}shot;

typedef struct{
	int			  enemy_flag;
	int					 cnt;
	int		  enemy_hitpoint;
	double  enemy_shot_range;
	double		 enemy_range;
	double			 enemy_x;
	double			 enemy_y;
	double       enemy_angle;
	int		        mot_time;
	shot E_shot[DIR_8][E_SHOT_MAX];
}enemy_t;
敵一体につき8方向50発、
合計400発撃つことが可能です。

CODE:

//敵のショットの関数その一
//自機狙い
void E_Act_shot_00( int i , int SET_SHOT_DIR , int SET_SHOT_NUMBER , int SET_SHOT_SPEED , int SET_TYPE )
{
	const double x = en[i].enemy_x;
	const double y = en[i].enemy_y;
	const double angle = atan2( y - pl.y , x - pl.x );

	for( int dir = 0 ; dir < SET_SHOT_DIR ; dir++ ){
		for( int j = 0 ; j < SET_SHOT_NUMBER ; j++ ){
			//ここで座標と弾の角度を取得
			if( en[i].E_shot[dir][j].Mem_shot == 0x1 ){
				if( SET_TYPE == ANGLE_INPUT ){
					if( j == 0 ){
						en[i].E_shot[0][0].angle = angle;
					}
				}
				en[i].E_shot[dir][j].x     = x;
				en[i].E_shot[dir][j].y     = y;
				if( SET_TYPE == ANGLE_INPUT ){
					en[i].E_shot[dir][j].angle = en[i].E_shot[0][0].angle;
				}
				else{
					en[i].E_shot[dir][j].angle = angle;
				}
				//おわったらフラグを変更
				en[i].E_shot[dir][j].Mem_shot |= 0x2;
			}
		}
	}
}

//ばら撒き弾
void E_Act_shot_01( int i , int SET_SHOT_DIR , int SET_SHOT_NUMBER , int SET_SHOT_SPEED )
{
	unsigned char vect[50];
	SRand(10);
	for( int ini = 0 ; ini < 50 ; ini++ ){
		vect[ini] = GetRand( 135 );
	}
	for( int dir = 0 ; dir < SET_SHOT_DIR ; dir++ ){
		for( int j = 0 ; j < SET_SHOT_NUMBER ; j++ ){
			//ここで座標と弾の角度を取得
			if( en[i].E_shot[dir][j].Mem_shot == 0x1 ){
				en[i].E_shot[dir][j].x     = en[i].enemy_x;
				en[i].E_shot[dir][j].y     = en[i].enemy_y;
				en[i].E_shot[dir][j].angle = get_angle( 135 + vect[j] );
				//おわったらフラグを変更
				en[i].E_shot[dir][j].Mem_shot |= 0x2;
			}
		}
	}
}

//24方向ショット
void E_Act_shot_02( int i , int SET_SHOT_DIR , int SET_SHOT_NUMBER , int SET_SHOT_SPEED , int VECT[] , int Cycle )
{

	static short vect_cnt = 0;
	for( int dir = 0 ; dir < SET_SHOT_DIR ; dir++ ){
		for( int j = 0 ; j < SET_SHOT_NUMBER ; j++ ){
			//ここで座標と弾の角度を取得
			if( en[i].E_shot[dir][j].Mem_shot == 0x1 ){
				en[i].E_shot[dir][j].x     = en[i].enemy_x;
				en[i].E_shot[dir][j].y     = en[i].enemy_y;
				en[i].E_shot[dir][j].angle = get_angle(VECT[vect_cnt%Cycle]);
				vect_cnt++;
				//おわったらフラグを変更
				en[i].E_shot[dir][j].Mem_shot |= 0x2;
			}
		}
	}
}
ボス用の弾幕データも作っていきましょい!シャキーン
最後に編集したユーザー せんちゃ on 2010年11月02日(火) 19:28 [ 編集 1 回目 ]

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 15年前

Re: 弾幕プログラム、いろいろ作っました。

投稿記事 by Dixq (管理人) » 14年前

mixiに楽しそうなスクリーンショット上がってましたね[e]146[/e]