第三十九章 让敌人掉落道具吧
这次我们来让敌人掉落道具吧。
在实现和道具相关的内容的时候,我们也和平常一样,先定义结构体、声明变量,然后进行“登录/计算/绘制”这三个标准步骤。☆1
不过和道具相关的实现中增加了这些内容之后,就有必要进行和自机的碰撞判定计算以及和道具接触时的状态变化的处理了。
因此,我们试着在这一章节中先来制作“☆1”的部分。
那么我们来定义结构体。
另外如果我们在往收物线(Borderline)上方移动的话,就可以自动地收分了。
这意味着道具的状态会改变。
因此,现在我们试着在一般的结构体的之外再追加“state”变量吧。
初始化和图像的加载也先写出来。
—-在 define.h 中进行以下追加 —-
//道具显示的最大数量
#define ITEM_MAX 100
//获得道具的收物线
#define ITEM_GET_BORDER_LINE 100
//道具的收取范围
#define ITEM_INDRAW_RANGE 70
—-在 struct.h 中进行以下追加 —-
//道具的结构体
typedef struct{
//flag、计数器、种类、状态
int flag,cnt,knd,state;
//速度、坐标、大小
double v,x,y,r;
}item_t;
—-在 GV.h 中进行以下追加—-
GLOBAL int img_item[6][2];//道具的图像
GLOBAL item_t item[ITEM_MAX];//道具
—-在 ini.cpp 的 ini() 中进行以下追加 —-
memset(item,0,sizeof(item_t)*ITEM_MAX);
—-在 load.cpp 的 load() 中进行以下追加 —-
LoadDivGraph( "../dat/img/item/p0.png" , 2 , 2 , 1 , 35 , 35 , img_item[0] ) ;
LoadDivGraph( "../dat/img/item/p1.png" , 2 , 2 , 1 , 35 , 35 , img_item[1] ) ;
LoadDivGraph( "../dat/img/item/p2.png" , 2 , 2 , 1 , 15 , 15 , img_item[2] ) ;
LoadDivGraph( "../dat/img/item/p3.png" , 2 , 2 , 1 , 35 , 35 , img_item[3] ) ;
LoadDivGraph( "../dat/img/item/p4.png" , 2 , 2 , 1 , 35 , 35 , img_item[4] ) ;
LoadDivGraph( "../dat/img/item/p5.png" , 2 , 2 , 1 , 35 , 35 , img_item[5] ) ;
—-在 load.cpp 中变更以下红字部分 —-
void load_story(){
int n,num,i,fp;
/***修改请注意***/
char fname[32]={"../dat/csv/39章/storyH0.csv"};
/***修改请注意***/
int input[64];
char inputc[64];
好的,预先准备已经做好了。
那么首先我们来登录吧。
道具出现的时刻为消灭敌人或者自机被击毁的时候。
那么在敌人被击毁的时候我们调用enter_item函数使得道具出现。
至于会出现什么道具,这个信息已经先保存在敌人的item_n中了。
由于我们实在Excel数据中决定道具的掉落的,因此去确认Excel文件。
当第1个道具在敌人的位置一次出现并且有多个将要出现的时候,那么从第2个道具开始就在适当地在离开一段距离的地方出现。
—-在 out.cpp 中进行红字部分变更 —-
/***修改请注意***/
int serch_item(){
for(int i=0;i<ITEM_MAX;i++)
if(item[i].flag==0)
return i;
return -1;
}
//道具登录
//道具 0:小power 1:小点 2:弹点 3:小金 4:大power 5:大金
void enter_item(double x, double y, int item_n[], int num){//x,y,道具的种类,数量
int k;
double r[6]={0.6,0.6,1.0,0.6,1.0,1.0};//dat/img/item的图像放大率
for(int i=0;i<num;i++){//1个敌人掉落的道具最大数为6个
if(item_n[i]!=-1){//如果在Excel中指定的道具是-1(空)的话就终止
if((k=serch_item())!=-1){//查询可以登录的编号
item[k].flag=1;
item[k].v =-3.5; //速度
item[k].cnt =0;
item[k].state=0;
item[k].x =x;
item[k].y =y;
if(i>0){//如果不止一个的话就适当地分散一下
item[k].x+=rang(40);
item[k].y+=rang(40);
}
item[k].knd =item_n[i];//指定了的道具掉落
item[k].r =r[item[k].knd];
}
}
}
}
//敌人掉落的道具
void enter_enemy_item(int s){
enter_item(enemy[s].x,enemy[s].y,enemy[s].item_n, sizeof(enemy[s].item_n)/sizeof(int));
}
/***修改请注意***/
//角色掉落的道具
void enter_char_item(){
int item_n[4]={4,4,4,4};
enter_item(ch.x, ch.y, item_n, 4);
}
//决定敌人是否被击毁
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);
/***修改请注意***/
enter_enemy_item(s);//s号敌人掉落道具(39章)
/***修改请注意***/
for(i=0;i<SHOT_MAX;i++){//敌人总数次
—-在 char.cpp 中进行以下变更 —-
/***修改请注意***/
extern void enter_char_item();//(39章)
/***修改请注意***/
void calc_ch(){
if(ch.flag==1){//正在处理决死
bright_set.brt=80;//变暗
if(ch.cnt>20){//0.33秒处理决死
ch.flag =2; //1:正在处理决死 2:自机被击毁正在上浮
ch.cnt =0;
bright_set.brt=255;
}
}
if(ch.cnt==0 && ch.flag==2){//当前瞬间被击毁的话
/***修改请注意***/
enter_char_item();//登录自机的道具(39章)
/***修改请注意***/
ch.x=FMX/2;//设置坐标
ch.y=FMY+30;
ch.mutekicnt++;//进入无敌状态
}
接下来是计算和绘制。
道具的状态如果是0的话那么就是普通地降落。 如果是1的话就是被收取。 如果自机在ITEM_GET_BORDER_LINE以上的话那么item的状态就变成1以被收取。
低速移动中如果道具在自机的半径ITEM_INDRAW_RANGE以内的话状态即便为0也会收取一部分。
普通下落的时候我们只要在y方向将坐标加上速度分量就行了。
吸收的时候,自机与道具的角度使用atan2来求得,然后像平常那样用sin、cos来计算就行了。
绘制的时候我们按照“基础1,基础2,文字”的顺序绘制3次。
基础1是等倍率旋转绘制,而基础2是0.8返回旋绘制。
—-在 calc.cpp 中进行以下红字部分追加/变更 —-
/***修改请注意***/
//道具的收取处理
void calc_item_indraw(int i){
double v = item[i].state ? 8 : 3;//state如果是1的话速度为8否则为3
double angle=atan2(ch.y-item[i].y,ch.x-item[i].x);//计算与自机的角度
item[i].x += cos(angle)*v;
item[i].y += sin(angle)*v;
}
//计算道具的移动等
void calc_item(){
for(int i=0;i<ITEM_MAX;i++){
if(item[i].flag>0){
if(item[i].state==0)
if(ch.y<ITEM_GET_BORDER_LINE)//如果是收取状态的话
item[i].state=1;
if(item[i].state==0){//如果是普通状态的话
double x=ch.x-item[i].x,y=ch.y-item[i].y;
//如果在低速状态中的自机附近的话
if(CheckStatePad(configpad.slow)>0 &&
x*x+y*y<ITEM_INDRAW_RANGE*ITEM_INDRAW_RANGE){
calc_item_indraw(i);//收取一部分
}
else{
if(item[i].v<2.5)//增加速度
item[i].v+=0.06;
item[i].y+=item[i].v;//移动
}
}
else{//如果是收取状态的话
calc_item_indraw(i);
}
item[i].cnt++;
if(item[i].y>FMY+50)
item[i].flag=0;
}
}
}
/***修改请注意***/
void calc_main(){
calc_stage_title();
/***修改请注意***/
calc_item();
/***修改请注意***/
}
—-在 graph.cpp 中进行以下红字部分的变更/追加 —-
/***修改请注意***/
void graph_item(){
int i;
for(i=0;i<ITEM_MAX;i++){
if(item[i].flag==1){
DrawRotaGraphF(item[i].x+FX+dn.x,item[i].y+FY+dn.y,
item[i].r,PI2*(count%120)/120,img_item[item[i].knd][1],TRUE);
DrawRotaGraphF(item[i].x+FX+dn.x,item[i].y+FY+dn.y,
item[i].r*0.8,-PI2*(count%120)/120,img_item[item[i].knd][1],TRUE);
DrawRotaGraphF(item[i].x+FX+dn.x,item[i].y+FY+dn.y,
item[i].r,0,img_item[item[i].knd][0],TRUE);
}
}
}
/***修改请注意***/
void graph_main(){
if(bright_set.brt!=255)SetDrawBright(bright_set.brt,bright_set.brt,bright_set.brt);
graph_back_main();//背景绘制main
graph_effect(0);//敌人消灭特效
if(bright_set.brt!=255)SetDrawBright(255,255,255);
graph_effect(4);//决死的特效
if(bright_set.brt!=255)SetDrawBright(bright_set.brt,bright_set.brt,bright_set.brt);
graph_child();
/***修改请注意***/
graph_item();//道具的绘制
/***修改请注意***/
graph_boss();
graph_enemy();//敌人的绘制
graph_cshot();//自机射击的绘制
运行结果