第十二章 设置许多敌人的运动模式吧
前面我们已经写好了控制一个敌人移动的函数了。现在我们再多做几个看看。
我试着做了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 |
在这里,由于敌人的移动模式的信息放到了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)
运行结果