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されていますが、
中身は
//関数の引数が結構な量になったので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
これ絶対プログラム遅いよなぁ…と思いきや
意外と処理落ちしません。
さすがに画面を埋め尽くすほどの数千発の弾幕が飛び交じ合えば
多少処理で遅くもなりますが、それでも
そんな馬鹿みたいな弾幕を作らない限りは普通には動きます。
あとはこれをカウントで動かしていき、
指定カウントで関数呼び出し、出現、
50個の敵の配列を使いまわしながら組み合わせていけばそれらしく
なってきました。
敵の情報はこんな感じです。
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;
合計400発撃つことが可能です。
//敵のショットの関数その一
//自機狙い
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;
}
}
}
}