第四十八章 试着加上音乐吧
本章中我们试着加上音乐吧。
音乐的话这里我使用了炼狱庭园的曲子。
不妨请听听dat文件夹的music文件夹中中放入的曲子。
如果您打不开ogg文件的话,请安装 GOM Player之类的软件然后来听。
虽然这音乐听起来不像是1面的曲子,您也可以变成您喜欢的曲子。
这一章我们使用
SetLoopPosSoundMem这个函数。
虽然用PlaySoundMem函数也能够播放曲子,但是有个问题,那就是只要是曲子,大多数都是有前奏的。
因此,想要在游戏内循环重播、且曲子到达某个部分之后要回到最初的时候,那么会直接回到整个曲子的开头这很不方便了。
为了解决这个问题,我们使用这个函数来让循环播放时跳回去的地方定位到指定的毫秒位置。
我们在 Audacity之类的软件里面确认曲子的应该是循环位置的部分吧。
比如试着将最终Boss的曲子0_1.ogg中像是循环位置的部分放大来看之后,
就会发现如果把26.672秒也即26672毫秒设置为循环位置的话就行了。
这一次,我们定义了area_t类型的结构体,对于每一个区域(译者注:这里包括下文中的区域指的是每一面)中需要保存的信息都要用到一个这个结构体来保存。
在其中我们定义了bgm_t型结构体,它是与BGM相关的变量的集合。
—-在 struct.h 中进行以下追加 —-
//BGM信息(在area_t中使用(48)
typedef struct{
//BGM的播放flag、播放句柄、播放时机的种类编号、循环位置
int flag,handle,knd[2],loop_pos[2];
}bgm_t;
//区域所持有的信息
typedef struct{
bgm_t bgm;
}area_t;
—-在 GV.h 中进行以下追加 —-
GLOBAL area_t area;//区域所持有的数据 (48)
—-在 function.h 中进行以下追加 —-
GLOBAL void delete_bgm();
GLOBAL void bgm_main();
—-在 load.cpp 变更以下部分 —-
适当地调整了ChangeVolumeSoundMem函数内的音量。详情省略。
在bgm_t中定义了
flag, handle, knd[2], loop_pos[2];
这些变量。音乐的播放状态按照下面那样0~4的状态依次变化。
0:还没有播放
1:通常BGM播放中
2:通常BMG播放停止中
3:终路Boss的BGM播放中
4:终路Boss的BGM播放停止中状态0是当前区域的游戏刚开始的状态。这个时候读入数据。
在状态1下何时开始播放由knd来设定。在样例中种类0的重播方式是开始之后60次计数时开始。
由于我们希望对于每一个设定了的种类都要变更重播的时机,因此今后我们在music.cpp中增加重播的方式吧。
状态2是终路Boss临近的状态。此时停止通常BMG,删除数据,读入终路Boss的音乐数据并待机。
状态3则是开始播放。
状态4的时候虽然是停止,但是停止的处理还没有在示例中完成。
loop_pos是前面说过的循环位置。在ini函数中设置。
[0]是一般BGM的设定,[1]是终路Boss的BGM的设定。
另外,在load_bgm函数中也写好路径了。 如果我们将
0_0作为1面的通常BGM
0_1作为1面的终路Boss的BGM
1_0作为2面的通常BGM
1_1作为2面的终路Boss的BGM
的话,那么我们就可以利用这个函数沿袭着继续扩展下去了。
—-在 ini.cpp 中进行以下追加 —-
memset(&area,0,sizeof(area_t));//(48)
area.bgm.knd[0]=0;//通常BGM在什么时刻播放取决于music.cpp(48)
area.bgm.knd[1]=0;// 终路Boss的BGM在什么时刻播放取决于music.cpp(48
area.bgm.loop_pos[0]=26672;//通常BGM的循环位置 (48)
area.bgm.loop_pos[1]=27010;//Boss的BGM的循环位置(48)
—-在 GV.h 中进行以下追加 —-
GLOBAL area_t area;//当前区域所持有的数据 (48)
—-在 function.h 中进行以下追加 —-
GLOBAL void delete_bgm();
GLOBAL void bgm_main();
—-在 load.cpp 中进行以下部分变更 —-
在ChangeVolumeSoundMem函数中适当地调整了音量。详情省略。
—-在 music.cpp 中进行以下追加 —-
void load_bgm(int flag){
char str[64];
sprintf(str,"../dat/music/%d_%d.ogg",stage,flag);
area.bgm.handle=LoadSoundMem(str);
}
void delete_bgm(){
DeleteSoundMem(area.bgm.handle);
}
void bgm_main(){
if(area.bgm.flag==0){//最开始读入
load_bgm(0);
SetLoopPosSoundMem( area.bgm.loop_pos[0], area.bgm.handle );//设置循环位置
area.bgm.flag=1;
}
if(area.bgm.flag==1){//按照种类开始播放
switch(area.bgm.knd[0]){
case 0://如果是播放种类0的话
if(stage_count==60){//开始60次计数后开始播放
PlaySoundMem(area.bgm.handle,DX_PLAYTYPE_LOOP);
area.bgm.flag=2;
}
break;
default:
break;
}
}
if(area.bgm.flag==2){//在Boss出现时读入
if(stage_count==boss.appear_count[1]){//终路Boss出现的话读入
StopSoundMem(area.bgm.handle);
delete_bgm();
load_bgm(1);
SetLoopPosSoundMem( area.bgm.loop_pos[1], area.bgm.handle );//设置循环位置
area.bgm.flag=3;
}
}
if(area.bgm.flag==3){
switch(area.bgm.knd[0]){
case 0://如果是播放种类0的话
if(stage_count==boss.appear_count[1]){//终路Boss出现后再播放
PlaySoundMem(area.bgm.handle,DX_PLAYTYPE_LOOP);
area.bgm.flag=4;
}
break;
default:
break;
}
}
}
—-在 main.cpp 中追加以下红字部分 —-
case 100://通常处理
enter_func_tm("最初");
calc_ch(); enter_func_tm("角色计算");
ch_move(); enter_func_tm("角色移动");
cshot_main(); enter_func_tm("自机射击main");
enemy_main(); enter_func_tm("敌人处理main");
boss_shot_main();enter_func_tm("Boss射击main");
shot_main(); enter_func_tm("射击main");
out_main(); enter_func_tm("碰撞判定");
effect_main(); enter_func_tm("特效main");
calc_main(); enter_func_tm("计算main");
graph_main(); enter_func_tm("绘制main");
/***修改请注意***/
bgm_main(); enter_func_tm("BGMmain");
/***修改请注意***/
if(boss.flag==0)
stage_count++;
break;
default:
printfDx("错误的func_state\n");
break;
运行结果
也就是有没有音乐的区别,因此看起来没有区别。
※试着练习吧※
不妨运行这个工程,在Boss战中故意优哉一下听听BGM。这样应该就能够明白是在哪里进行循环的了。
这首曲子是炼狱庭园的曲子“裏桜華-CODE:桜樺-”。
http://www.rengoku-teien.com/mp3_wahuu.html
您可以下载曲子,然后自己对曲子进行编辑,如果能够编辑、设定到无缝循环的程度的话就非常不错了。
※管理员的话※
在龙神录中考虑到容量的问题,出于无奈只好把这首“裏桜華-CODE:桜樺-”进行剪短再循环了。
然而这首曲子有4分多钟的长度,前半部分和后半部分都非常好听。
如果您已经多次玩过龙神录了,然后听了全曲的话可能会有“诶?原来这首曲子还有这样一些部分啊”这样子的想法。
这首曲子真的很不错,可以的话请务必从头至尾地听一遍。