第十九章 给敌人加上消灭特效吧
如果敌人突然就消失了,看起来实在是很寂寞,现在我们试着做出消灭特效吧。
那么,我先追加一个效果用的文件。
在解决方案管理器里面,右键project项目追加一个新的项目,现在我们往mydat文件夹里面的source里面追加“effect.cpp”。
然后像下面那样复制过去。
—- effect.cpp —-
#include "../include/GV.h"
//检查登录为空的效果编号
int search_effect(){
for(int i=0;i<EFFECT_MAX;i++){
if(effect[i].flag==0)
return i;
}
return -1;
}
//计算效果
void calc_effect(){
for(int i=0;i<EFFECT_MAX;i++){
if(effect[i].flag>0){ //如果效果已经登录了
switch(effect[i].knd){//根据效果的种类进行分歧
case 0://0号的处理
effect[i].cnt++;
effect[i].r+=0.08;//逐渐把效果的大小变大
if(effect[i].cnt>10)//如果计数为10以上
effect[i].brt-=25;//将亮度降低
if(effect[i].cnt>20)//效果为20以上
effect[i].flag=0;//销毁之
break;
default:
printfDx("effect设定错误\n");
break;
}
}
}
}
//检查登录为空的死亡效果编号
int search_del_effect(){
for(int i=0;i<DEL_EFFECT_MAX;i++){
if(del_effect[i].flag==0)
return i;
}
return -1;
}
//登录消灭特效
void enter_del_effect(int s){
int k=search_del_effect();
if(k!=-1){
del_effect[k].flag=1;//设置flag为有效
del_effect[k].cnt=0;
del_effect[k].col=enemy[s].back_col;//设定敌人的背景色为消灭色
del_effect[k].x=enemy[s].x;//将敌人的坐标设置为死亡位置
del_effect[k].y=enemy[s].y;
}
}
//进行消灭特效的计算和特效的登录
void calc_del_effect(){
int k;
for(int i=0;i<DEL_EFFECT_MAX;i++){
if(del_effect[i].flag>0){
if(del_effect[i].cnt%2==0){//每1/30秒登录一次
if((k=search_effect())!=-1){//搜索空着的编号
memset(&effect[k],0,sizeof(effect_t));//初始化
effect[k].flag=1;//设置flag为有效
effect[k].brt=255;//将亮度变为最大值
effect[k].ang=rang(PI);//随机角度
effect[k].col=del_effect[i].col;//设置颜色
effect[k].eff=1;// 1是发光效果。这里设置为光效果。
effect[k].img=img_del_effect[effect[k].col];//设置消灭的图像
effect[k].knd=0;//效果的种类是0号(消灭特效的knd一定是0)
effect[k].x=del_effect[i].x;//设置坐标
effect[k].y=del_effect[i].y;
}
}
if(del_effect[i].cnt>8){//如果计数器大于8的话结束
del_effect[i].flag=0;
}
del_effect[i].cnt++;
}
}
}
void effect_main(){
calc_del_effect();//消灭特效计算
calc_effect();//特效计算
}
在enter_del_effect中登录消灭特效的话,后面就可以对特效进行全自动地计算,这会非常方便。
这个函数通过参数s传入敌人的识别编号。这样一来,就可以登录s号的敌人的消灭特效了。
现在我们也新定义好了信息数据库。
为了登录消灭特效而定义del_effect 为了登录特效而定义effect
对于消灭特效和特效两种不同的数据库,可能会有人产生疑问。
消灭特效事实上并不是进行特效,而是负责管理在什么时间点上登录效果、将什么特效往哪里登录之类的事情。
也即是说,实际的效果还是在effect中计算和绘制。
由于这个effect变量是泛用的,因此除了消灭特效以外,还能够登录别的特效。
我们后面将会在特效里面登录许许多多东西,大部分都是在这里处理的。
一旦我们需要许多特效,由于需要使用许多不同的变量,处理起来将会很麻烦么,因此这样做效率比较高。
因此,现在您需要记住“在消灭特效变量之上,还有特效变量。如果仅仅只有消灭特效变量的话并不能形成特效,消灭特效变量的工作只是管理特效”这一点。
在enter_del_effect函数中登录的信息将在calc_del_effect()函数中计算。
如果您看了注释的话应该就会明白了,一系列的工作是:搜索登录了的消灭特效,如果有的话每1/30秒登录1次特效。然后,搜索效果的登录编号,最后设置信息。
和之前所说的一样,由于效果变量可以使用任何值,因此我们往knd传入0——它用于标识这是哪个种类的特效。而今后我们就把消灭特效设置为0号的特效。
在out_main中进行自机总射击的子弹与所有敌人的总碰撞判定。
那么与此同时,进行下面那样的修改。
—-在 out.cpp 中进行以下部分的变更 —-
/***修改请注意***/
extern void enter_del_effect(int);
/***修改请注意***/
void enemy_death_judge(int s){
int i;
se_flag[8]=1;//击中敌人的声音
if(enemy[s].hp<0){//如果敌人的HP小于0
enemy[s].flag=0;//消灭敌人
se_flag[1]=1;//敌人的击毁声
/***修改请注意***/
enter_del_effect(s);
/***修改请注意***/
—-在 define.h 中进行以下追加 —-
//特效登录最大数
#define EFFECT_MAX 100
//消灭特效登录最大数
#define DEL_EFFECT_MAX 30
—-在 struct.h 中进行以下变更 —-
//和敌人相关的结构体
typedef struct{
int flag,cnt,pattern,muki,knd,hp,hp_max,item_n[6],
/***修改请注意***/
img,back_col;
/***修改请注意***/
//flag、计数器、移动模式、方向、敌人的种类、HP最大值、掉落道具、背景色
double x,y,vx,vy,sp,ang;
//坐标、速度x分量、速度y分量、速度、角度
int bltime,blknd,blknd2,col,state,wtime,wait;
//弹幕开始时间、弹幕种类、子弹的种类、颜色、状态、待机时间、停止时间
}enemy_t;
—-在 enemy.cpp的enemy_enter函数的登录部分进行以下追加—-
enemy[i].back_col=GetRand(4);
—-在 function.h 中进行以下追加 —-
//effect.cpp
GLOBAL void effect_main();
—-在 GV.h 中进行以下追加 —-
GLOBAL int img_del_effect[5];
GLOBAL del_effect_t del_effect[DEL_EFFECT_MAX];//消灭特效
GLOBAL effect_t effect[EFFECT_MAX];//特效
—-在 ini.cpp 的 ini函数中进行以下追加 —-
memset(effect,0,sizeof(effect_t)*EFFECT_MAX);
memset(del_effect,0,sizeof(del_effect_t)*DEL_EFFECT_MAX);
—-在 load.cpp 的 load函数中进行以下追加 —-
LoadDivGraph( "../dat/img/enemy/hit_effect.png" , 5 , 5 , 1 , 140 , 140 , img_del_effect ) ;
—-在 main.cpp 的main函数中进行以下变更 —-
case 100://通常处理
calc_ch(); //角色计算
ch_move(); //控制角色移动
cshot_main();//自机射击main
enemy_main();//敌人处理main
shot_main(); //射击main
out_main(); //碰撞判定
/***修改请注意***/
effect_main();//特效main
/***修改请注意***/
graph_main();//绘制main
stage_count++;
break;
—-在 struct.h 中进行以下追加 —-
//特效
typedef struct{
int flag,cnt,col,knd,img,eff,brt;
double x,y,r,ang;
}effect_t;
//消灭特效
typedef struct{
int flag,cnt,col;
double x,y;
}del_effect_t;
—-在 graph.cpp 中进行以下追加 —-
/***修改请注意***/
void graph_effect(){
for(int i=0;i<EFFECT_MAX;i++){
if(effect[i].flag>0){
if(effect[i].eff==1)//如果特效是光特效
SetDrawBlendMode( DX_BLENDMODE_ADD, effect[i].brt) ;
DrawRotaGraphF(effect[i].x+FIELD_X,effect[i].y+FIELD_Y,effect[i].r,effect[i].ang,effect[i].img,TRUE);
if(effect[i].eff==1)
SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0) ;
}
}
}
/***修改请注意***/
void graph_main(){
/***修改请注意***/
graph_effect();
/***修改请注意***/
graph_enemy();
graph_cshot();
graph_ch();
graph_bullet();
graph_board();
}
运行结果