第十二章 设置许多敌人的运动模式吧

>>点此回到教程目录

前面我们已经写好了控制一个敌人移动的函数了。现在我们再多做几个看看。

我试着做了0~10共11种控制敌人的行动模式的函数。

另外,这次也做了一个叫rang的函数。这个函数的功能是传入n,然后返回一个从-n~n的double类型的随机数。

下面的代码稍微有点长,不过就是把简单的函数写到一起而已。

–enemy_act_pattern.cpp变更–

#include "../include/GV.h"

//返回-ang~ang的随机角度
double rang(double ang){
    return ( -ang + ang*2 * GetRand(10000)/10000.0 );
}

//移动模式0
//向下移动后停止然后往上移动
void enemy_pattern0(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=3;//向下移动
    if(t==40)
        enemy[i].vy=0;//停止
    if(t==40+enemy[i].wait)//在登录的时间区间内停止
        enemy[i].vy=-3;//向上移动
}

//移动模式1
//向下移动然后停止然后向左下移动
void enemy_pattern1(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=3;//向下移动
    if(t==40)
        enemy[i].vy=0;//停止
    if(t==40+enemy[i].wait){//在登录的时间区间内停止
        enemy[i].vx=-1;//向左
        enemy[i].vy=2;//向下移动
        enemy[i].muki=0;//设置方向为左
    }
}

//移动模式2
//向下移动然后停止然后向右下移动
void enemy_pattern2(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=3;//向下移动
    if(t==40)
        enemy[i].vy=0;//停止
    if(t==40+enemy[i].wait){// 在登录的时间区间内停止
        enemy[i].vx=1;//向右
        enemy[i].vy=2;//向下移动
        enemy[i].muki=2;//设置方向为右
    }
}

//移动模式3
//迅速地下降然后向左移动
void enemy_pattern3(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=5;//向下移动
    if(t==30){//途中方向向左
        enemy[i].muki=0;
    }
    if(t<100){
        enemy[i].vx-=5/100.0;//左方向加速
        enemy[i].vy-=5/100.0;//减速
    }
}

//移动模式4
//迅速地下降然后向右移动
void enemy_pattern4(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=5;//向下移动
    if(t==30){//途中方向向右
        enemy[i].muki=2;
    }
    if(t<100){
        enemy[i].vx+=5/100.0;//右方向加速
        enemy[i].vy-=5/100.0;//減速
    }
}

//移动模式5
//斜着向左下移动
void enemy_pattern5(int i){
    int t=enemy[i].cnt;
    if(t==0){
        enemy[i].vx-=1;
        enemy[i].vy=2;
        enemy[i].muki=0;
    }
}

//移动模式6
//斜着向右下移动
void enemy_pattern6(int i){
    int t=enemy[i].cnt;
    if(t==0){
        enemy[i].vx+=1;
        enemy[i].vy=2;
        enemy[i].muki=2;
    }
}

//移动模式7
//停止然后就那样向左上移动
void enemy_pattern7(int i){
    int t=enemy[i].cnt;
    if(t==enemy[i].wait){//在登录的时间区间内停止
        enemy[i].vx=-0.7;//向左
        enemy[i].vy=-0.3;//向上移动
        enemy[i].muki=0;//设置方向为左
    }
}

//移动模式8
//停止然后就那样向右上移动
void enemy_pattern8(int i){
    int t=enemy[i].cnt;
    if(t==enemy[i].wait){//在登录的时间区间内停止
        enemy[i].vx=+0.7;//向右
        enemy[i].vy=-0.3;//向上移动
        enemy[i].muki=2;//设置方向为右
    }
}

//移动模式9
//停止然后就那样向上移动
void enemy_pattern9(int i){
    int t=enemy[i].cnt;
    if(t==enemy[i].wait)//在登录的时间区间内停止
        enemy[i].vy=-1;//向上移动
}


//移动模式10
//下降然后转着圈往上移动
void enemy_pattern10(int i){
    int t=enemy[i].cnt;
    if(t==0) enemy[i].vy=4;//向下移动
    if(t==40)enemy[i].vy=0;//停止
    if(t>=40){
        if(t%60==0){
            int r=cos(enemy[i].ang)< 0 ? 0 : 1;
            enemy[i].sp=6+rang(2);
            enemy[i].ang=rang(PI/4)+PI*r;
            enemy[i].muki=2-2*r;
        }
        enemy[i].sp*=0.95;
    }
    if(t>=40+enemy[i].wait){
        enemy[i].vy-=0.05;
    }
}

总之先看看这些函数是描述了怎样的动作的吧。 把Excel文件修改成下面那样。您可以直接下载也可以自己替换。

计数器 移动模式 敌人的种类 x坐标 y坐标 速度 发射时间 弹幕种类 子弹的颜色 体力 子弹的种类 待机时间 物品1 2 3 4 5 6
cnt pattern knd x y sp bltime blknd col hp blknd2 wait item_n
100 0 0 180 -20 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
180 1 0 200 -20 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
260 2 0 180 -20 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
340 3 0 200 -20 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
420 4 0 180 -20 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
500 5 0 200 -20 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
580 6 0 180 -20 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
660 7 0 200 150 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
740 8 0 180 150 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
820 9 0 200 150 0 150 0 0 100 0 120 0 -1 -1 -1 -1 -1
900 10 0 180 -20 0 150 0 0 100 0 360 0 -1 -1 -1 -1 -1

下载Excel

在这里,由于敌人的移动模式的信息放到了enemy[i].pattern中,我们不妨考虑利用放在移动模式信息里面的0~10的值自动地调用enemy_parttern0~enemy_parttern10函数。

这样一来我们要使用函数指针这个东西了。

像(*enemy_pattern[ENEMY_PATTERN_MAX])(int) = { enemy_pattern0, enemy_pattern1, …..

这样带入的话,这个数组里面也就放入了函数的地址了。

接下来只要我们对数组下标指定前面我们放在enemy[i].pattern里面的值之后就可以传递处理过程了。

实际上使用函数指针调用函数的方法入红字所示。

–在enemy.cpp中进行以下追加–

#include "../include/GV.h"

#define ENEMY_PATTERN_MAX 11

extern void enemy_pattern0(int);extern void enemy_pattern1(int);extern void enemy_pattern2(int);
extern void enemy_pattern3(int);extern void enemy_pattern4(int);extern void enemy_pattern5(int);
extern void enemy_pattern6(int);extern void enemy_pattern7(int);extern void enemy_pattern8(int);
extern void enemy_pattern9(int);extern void enemy_pattern10(int);

void (*enemy_pattern[ENEMY_PATTERN_MAX])(int) = {
    enemy_pattern0,    enemy_pattern1,    enemy_pattern2,    enemy_pattern3,    enemy_pattern4,
    enemy_pattern5,    enemy_pattern6,    enemy_pattern7,    enemy_pattern8,    enemy_pattern9,
    enemy_pattern10,
};

//检查空的敌人编号
int enemy_num_search(){
    for(int i=0;i<ENEMY_MAX;i++){//查询flag为无效的enemy
        if(enemy[i].flag==0){
            return i;//返回使用可能的编号
        }
    }
    return -1;//如果全部被使用返回错误
}

//登录敌人情报
void enemy_enter(){//控制、登录敌人行动的函数
    int i,j,t;
    for(t=0;t<ENEMY_ORDER_MAX;t++){
   if(enemy_order[t].cnt==stage_count){//如果当前计数是是顺序的计数的瞬间
                        if((i=enemy_num_search())!=-1){
                                enemy[i].flag   =1;//flag
                                enemy[i].cnt    =0;//计数器
                                enemy[i].pattern=enemy_order[t].pattern;//移动模式
                                enemy[i].muki   =1;//方向
                                enemy[i].knd    =enemy_order[t].knd;//敌人的种类
                                enemy[i].x      =enemy_order[t].x;//坐标
                                enemy[i].y      =enemy_order[t].y;
                                enemy[i].sp     =enemy_order[t].sp;//速度
                                enemy[i].bltime =enemy_order[t].bltime;//子弹的发射时间
                                enemy[i].blknd  =enemy_order[t].blknd;//弹幕的种类
                                enemy[i].blknd2 =enemy_order[t].blknd2;//子弹的种类
                                enemy[i].col    =enemy_order[t].col;//颜色
                                enemy[i].wait   =enemy_order[t].wait;//停止时间
                                enemy[i].hp     =enemy_order[t].hp;//体力
                                enemy[i].hp_max =enemy[i].hp;//体力最大值
                                enemy[i].vx     =0;//水平分量的速度
                                enemy[i].vy     =0;//竖直分量的速度
                                enemy[i].ang    =0;//角度
                for(j=0;j<6;j++)
                    enemy[i].item_n[j]=enemy_order[t].item_n[j];//掉落的道具
            }
        }
    }
}

//控制敌人的行动
void enemy_act(){
    int i;
    for(i=0;i<ENEMY_MAX;i++){
        if(enemy[i].flag==1){//如果敌人的flag为有效
            if(0<=enemy[i].pattern && enemy[i].pattern<ENEMY_PATTERN_MAX){

                /*** 修改请注意 ***/
                enemy_pattern[enemy[i].pattern](i);
                /*** 修改请注意 ***/

                enemy[i].x+=cos(enemy[i].ang)*enemy[i].sp;
                enemy[i].y+=sin(enemy[i].ang)*enemy[i].sp;
                enemy[i].x+=enemy[i].vx;
                enemy[i].y+=enemy[i].vy;
                enemy[i].cnt++;
                enemy[i].img=enemy[i].muki*3+(enemy[i].cnt%18)/6;
                //敌人跑到画面外面的话销毁
                if(enemy[i].x<-20 || FIELD_MAX_X+20<enemy[i].x || enemy[i].y<-20 || FIELD_MAX_Y+20<enemy[i].y)
                    enemy[i].flag=0;
            }
            else
                printfDx("enemy[i].pattern的%d的值错误。",enemy[i].pattern);
        }
    }
}

//敌人处理main
void enemy_main(){
    enemy_enter();
    enemy_act();
}

接下来为了计算角度,我们设定圆周率的定义。

由于圆周率π或者2π都经常使用,乘积的值我们也事先定义。

–在define.h中进行以下追加–

//圆周率
#define PI 3.1415926535898
#define PI2 (PI*2)

运行结果


如果像运行结果那样,敌人进行各种各样的行动的话那就成功了。

>>点此回到教程目录

results matching ""

    No results matching ""