第三十八章 来绘制Stage Title吧
敌人的基本行动、Boss、弹幕我们都做好了,看起来我们现在很想完成的就是一个完整的Stage了呢。
从现在开始,要完成一个Stage,我想我们需要做许多细微的工作了。
无论是龙神录还是东方,Stage开始后稍微过了一会儿敌人便会出现,同时Title也显示出来了,而Stage这个时候才算真正开始了呢。现在我们试着展示一下这个Stage Ttile。
与前面所作的工作相同,我们需要编写这样子的程序:定义Stage Title用到的结构体,当到了应该显示Title的时候我们将flag设置为有效,之后自动地进行计算。
登录/计算/绘制,一般而言这三个过程是最基本的格式。
那么,这次因为要增加计算部分,所以请在calc.cpp文件中进行追加。
在calc.cpp中我们将要写入本次以及以后的制作中所需要的各种各样细小的计算处理。
在主循环中只需要调用将在后面实现的cacl_main函数,而在calc_main函数中我们决定哪个函数被调用。
因此,首先我们来进行结构体的定义以及变量的声明吧。
然后,为了设定本次的Stage,我们定义这样一些东西:用于标识当前为哪个stage的stage变量以及一共有多少个stage的宏STAGE_NUM。
—-在 define.h 中进行以下追加 —-
//stage数
#define STAGE_NUM 5
—-在 GV.h 中追加以下红字部分—-
//flag/状态变量
GLOBAL int func_state,stage_count,count,stage; //用于控制函数的变量
GLOBAL int se_flag[SE_MAX]; // SE标志
//设定用变量
GLOBAL int stage_title_count[STAGE_NUM];
~略~
GLOBAL stage_title_t stage_title;// Stage Title
—-在 function.h 中进行以下追加 —-
//calc.cpp
GLOBAL void calc_main();
—-在 struct.h 中进行以下追加 —-
//游戏Stage Title
typedef struct{
//flag、图像句柄、计数器、亮度、出现计数
int flag,img,cnt,brt,appear_cnt;
}stage_title_t;
接下来,首先我们进行初始化吧。
本次我们定义了“stage_title_count”这个变量了呢。
我们往这个变量里面放入用于确定到多少计数的时候才开始显示Title的计数值。
如果我们想在Stage 1中600次计数后开始显示Title,那么那么我们就往state_title_count[0]中代入600就行了。
当游戏的计数器值到达这个计数的时候就会进行自动登录。
我们在stage_title.appear_cnt中设置在Stage中开始显示Title的计数值。
那么我们就这么干吧。
—-在 first_ini.cpp 中进行以下追加 —-
stage=0;
stage_title_count[0]=200;
—-在 ini.cpp 中进行以下红字部分追加 —-
//游戏初始化
void ini(){
stage_count=1;
memset(&ch,0,sizeof(ch_t));
memset(enemy,0,sizeof(enemy_t)*ENEMY_MAX);
memset(lazer,0,sizeof(lazer_t)*LAZER_MAX);
memset(enemy_order,0,sizeof(enemy_order_t)*ENEMY_ORDER_MAX);
memset(shot,0,sizeof(shot_t)*SHOT_MAX);
memset(cshot,0,sizeof(cshot_t)*CSHOT_MAX);
memset(effect,0,sizeof(effect_t)*EFFECT_MAX);
memset(del_effect,0,sizeof(del_effect_t)*DEL_EFFECT_MAX);
memset(&bom,0,sizeof(bom_t));
memset(&bright_set,0,sizeof(bright_set_t));
memset(&dn,0,sizeof(dn_t));
memset(&boss,0,sizeof(boss_t));
memset(child,0,sizeof(child_t)*CHILD_MAX);
memset(&stage_title,0,sizeof(stage_title_t));
ch.x=FMX/2;
ch.y=FMY*3/4;
ch.power=500;
stage_title.appear_cnt=stage_title_count[stage];
/*弹幕的各种设定。在后面的章节中我们再来好好设定吧。*/
boss.appear_count[0]=2000;//中路Boss出现的时刻
for(int i=0;i<DANMAKU_MAX;i++){//弹幕的各种HP
boss.set_hp[i]=10000;
boss.hp_max=10000;
}
for(int i=0;i<DANMAKU_MAX;i++)//弹幕的各种背景种类
boss.back_knd[i]=1;
/*到此为止*/
bright_set.brt=255;//最开始亮度为最大
}
我们把这些处理试着写在calc.cpp中吧。
如果和出现计数值一致了的话,就登录。
那之后我们渐渐地进行变亮的处理,稍微保持一会儿又进行变暗的处理,如果到了时间点的话就结束显示。
这次,由于我们对这个图像的使用仅仅是瞬间,因此没有必要作为让图像数据在内存上一直保存到游戏结束。
因此,我们只需要在登录的时候读入,在不需要它的时候释放它。
—-在 calc.cpp 中进行以下追加 —-
#include "../include/GV.h"
//Title处理
void calc_stage_title(){
if(stage_title.appear_cnt==stage_count){//如果现在是开始显示的时刻的话
stage_title.flag=1;
stage_title.img = LoadGraph("../dat/img/board/subject0.png");
}
if(stage_title.flag==0)return;
if(stage_title.cnt<128)//在最初的128次计数中逐渐变量
stage_title.brt+=2;
if(stage_title.cnt>128+128)//逐渐变暗
stage_title.brt-=2;
if(stage_title.cnt>128+128+128){//结束
stage_title.cnt=0;
stage_title.brt=0;
stage_title.flag=0;
DeleteGraph(stage_title.img);//释放图像
return ;
}
stage_title.cnt++;
//强制结束的时候需要释放图像
}
void calc_main(){
calc_stage_title();//Title处理
}
—-在 graph.cpp 中追加以下红字部分 —-
//Title的显示
void graph_stage_title(){
if(stage_title.flag>0){
SetDrawBlendMode( DX_BLENDMODE_ALPHA, stage_title.brt );
DrawGraph(120+FX+dn.x,10+FY+dn.y,stage_title.img,TRUE);
SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 );
}
}
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_boss();
graph_enemy();//敌人的绘制
graph_cshot();//自机射击的绘制
if(bright_set.brt!=255)SetDrawBright(255,255,255);
graph_ch();//自机的绘制
if(bright_set.brt!=255)SetDrawBright(bright_set.brt,bright_set.brt,bright_set.brt);
graph_lazer();//激光的绘制
graph_bullet();//子弹的绘制
if(bright_set.brt!=255)SetDrawBright(255,255,255);
graph_effect(1);//Boom的特效
graph_effect(2);//Boom线的特效
graph_effect(3);// Boom角色的特效
graph_stage_title();//Title的显示
graph_board();//面板的绘制
graph_develop();
}
—-在 main.cpp的main函数中进行以下红字部分变更 —-
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){
ChangeWindowMode(TRUE);//窗口模式
if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初始化与里表面化
while(ProcessLoop()==0){//主循环
music_ini();
switch(func_state){
case 0://只在游戏开始时进行的处理
load(); //读入数据
first_ini();//最开始的初始化
func_state=99;
break;
case 99://STG开始前进行的初始化
ini();
load_story();
func_state=100;
break;
case 100://一般处理
calc_ch(); //角色计算
ch_move(); //控制角色的移动
cshot_main();//自机射击main
enemy_main();//敌人处理main
boss_shot_main();
shot_main(); //射击main
out_main(); //碰撞计算
effect_main();//特效main
calc_main();//游戏Title显示计算
graph_main();//绘制main
if(boss.flag==0)
stage_count++;
break;
default:
printfDx("错误的func_state\n");
break;
}
music_play();
if(CheckStateKey(KEY_INPUT_ESCAPE)==1)break;//按下ESC键则跳出徐U你还
ScreenFlip();//里外画面翻转
count++;
}
DxLib_End();//DX Library终止处理
return 0;
}
—-在 load.cp中进行以下红字变更 —-
void load_story(){
int n,num,i,fp;
char fname[32]={"../dat/csv/38章/storyH0.csv"};
int input[64];
char inputc[64];
运行结果