专业的编程技术博客社区

网站首页 > 博客文章 正文

C语言+EasyX库GUI编程之数字记忆游戏——音频播放和设置中心

baijin 2024-08-18 13:32:15 博客文章 6 ℃ 0 评论

上一期《C语言GUI编程之数字记忆游戏——计时器、暂停和重置游戏》为游戏添加了计时器以及暂停、重置的逻辑,这一期继续让游戏的可玩性增强——为游戏添加背景音乐和提示音,并且提供设置中心的功能以供玩家可以选择音频的开关。

C语言里的音频播放

为了控制音频播放,增加了一个media.cpp媒体模块。

引用winmm.lib库

使用windows系统再带的“winmm.lib”库进行音频的播放控制。引用winmm.lib库有两种方式,第一种直接在模块最上方声明使用:

#pragma comment(lib, "winmm.lib")

第二种,在使用Visual Studio的情况下,打开项目->属性设置->连接器->输入,找到“附加依赖”项,编辑添加“winmm.lib”即可。

播放音频

播放音频就比较简单了,先把音频文件拷贝到项目目录里,这里创建了子目录media用来存放;然后用以下函数执行播放:

mciSendString(_T("open media\\bk_music1.mp3 alias bkmusic"), NULL, 0, NULL);
mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);

这里不做过多的解释,更多的使用方式可以去网上查阅资料。

短音频二次播放

这里说一下短音频二次播放的问题。

先看使用场景:玩家点击正确的数字格子,给出“游戏正确”的提示音,这个提示音的音频时间很短,大概1秒,第一次点击正确触发提示音没有任何问题,紧接着再次触发提示音后却不能播放了。

此时的解决方法是在播放短音频之前先关闭它,然后再接上常规的播放逻辑,如:

mciSendString(_T("close incorrect"), NULL, 0, NULL);
mciSendString(_T("open media\\tips_incorrect.mp3 alias incorrect"), NULL, 0, NULL);
mciSendString(_T("play incorrect"), NULL, 0, NULL);

设置中心

UI思路

用一张图片作为设置中心的图层,然后在上面绘制设置项。

注意,以设置中心为设备进行绘制的时候,坐标原点在设置中心区域的左上角,并不是窗口的左上角。

绘制完成后再使用SetWorkingImage()函数切换到窗口绘制模式,并用putimage()函数把设置中心的图层输出在窗口上。

动画

整个设置中心作为整体从窗口底部向上移入到窗口的中心位置,关闭时从原路移除,效果如下。

这个动画原理不复杂,点击右下角设置按钮的时候,触发下面的逻辑:

  • 绘制设置中心,把文字、按钮都绘制到设置中心上去
  • 循环把设置中心在窗口上的位置(Y轴)从大到小递减,一直到窗口中间

注意:循环体中要使用cleardevice()清除上一次的设备,否则会出现重叠。但是执行cleardevice()会使窗口变成黑框(原来的画面都清除了),所以在此之前先利用getimage()函数把整个窗口的“快照图像”保存下来记为window_image,在执行cleardevice()之后使用putimage(0,0,&window_image)即可完美呈现出想要的动画效果。

关闭并移除设置中心的时候,先要获取设置中心的快照图像,然后进行清除设备、画窗口快照、画设置中心快照这三步循环。

另外,还有一个逻辑:游戏正在进行中点击设置按钮时要暂停计时。

数据管理

设置的数据保存在一个二进制文件里。程序里定义一个全局变量保存设置项里的数据,在主函数里读取文件数据并赋给这个全局变量;当在设置中心修改后改变这个全局变量里的值,并且把新数据写入到文件里。

开关按钮动画

EasyX做UI界面的话有点不太合适,这里勉强做了一个开关按钮的动画。

简单说一下思路:开关底层是一个按钮,上层一半是按钮滑块,一半是开关的提示文字“ON/OFF”;点击切换状态的时候把上面的滑块往另一侧移动,循环这个移动的过程借助BeginBatchDraw()、FlushBatchDraw()、EndBatchDraw()即可实现开关动画。

为了使得开发方便,把设置开关按钮单独封装成一个函数,并且留一个滑块偏移量的参数,这样就可以通过逐渐改变偏移量来循环绘制并达到动画的效果。

点击区域的管理

在项目里要记录比较多的点击区域:

  • 展示数字的格子
  • 右侧的暂停/重置功能按钮
  • 右下角的设置ICON
  • 设置中心的开关、关闭按钮

其中,格子的坐标特别有规律,记录判断也很方便;而剩下的就不太方便了,项目里的处理方式是整理两个类型(功能按钮、设置相关的按钮)的按钮坐标数组作为全局变量,在绘制的时候把坐标依次记录下,然后再特定逻辑下去判断点击了哪个按钮,并且相应去执行哪个函数。

感觉这种方式比较直接、简单粗暴,但是维护起来可能不太方便。后期可以专门定义一个结构体数据来存放点击区域,并加上相应的标记,这样可以使得点击事件的处理逻辑尽可能的统一,让代码的扩展性和维护性更强。

OK,这一期的内容分享就到这里了,目前游戏已经算得上“能玩”了,后面再把排行榜模块完善一下,再往后就做个项目总结、重构一下项目代码。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表