原文地址:
上一篇里,一个敌人的移动操作的函数已经做好了。现在我们来做更多的敌人移动吧。
我们来做一个有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_pattern0 ~ 函数 enemy_pattern10 ,这要怎么做呢?
这里就要使用叫做函数指针的东西了。
(*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;//标志
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){//这个敌机的标志设置为开启的话
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();
}
——————————————————————————————————————————————————————————————————
为了后面的角度计算方便,这里先把圆周率给定义一下。
圆周率的 pi 和 2*pi 都会用到,这里预先把乘好的值也定义下来。
——————————————————————————————————————————————————————————————————
--define.h里添加如下代码--
//圆周率
#define PI 3.1415926535898
#define PI2 (PI*2)
——————————————————————————————————————————————————————————————————
运行结果
像运行结果里,有各种各样行动方式的敌人出现的话,就成功了。
(PS:最近玩剑灵,所以好久没更新了。唉,进了这DT的游戏公司,回去都12点了,再玩会剑灵,没别的时间了)
(2014-2-18 笔记,这篇结合上一篇的笔记,就很好懂了。这篇只是新增了几个敌机的移动模式而已。然后用指针数组,根据i 找到对应的模式函数。然后具体分析里面的模式,其实都比较好懂,在某个时间点改变x y 方向的速度什么的。然后就是最后一种模式,可以仔细看看。这里用的是角度和速度,来控制移动的。而enemy_act 函数里面,先是根据角度移动,然后是根据x y 速度分量移动。 所以两种移动方式都会有效的,会叠加起来。估计这里这样设计的好处,就是某些地方,适合极坐标的时候,就只用角度来进行移动,方便弹幕的绘制)
本人CSDN博客目录: