原理
打地鼠游戏是一种经典的反应力游戏。游戏界面由多个洞口组成,地鼠会随机从不同的洞口冒出,玩家需要在限定时间内尽可能多地点击出现的地鼠来获得积分。游戏通过计时和积分系统来评估玩家的表现。
界面展示
下载地址
GitHub - mcdudu233/Whack-a-Mole: 基于easyx库的打地鼠游戏
界面
(1)游戏主界面:
显示游戏标题和三个按钮:开始游戏、设置和退出游戏。
(2)游戏设置界面:
音量调节:可以通过滑动条调节音量;
难度选择:可以选择简单、普通和困难三种难度;
分辨率选择:可以选择不同的屏幕分辨率。
还需要一个返回主界面按钮。
(3)游戏界面:
要求能显示当前关卡、剩余时间和当前得分。
地鼠随机出现,玩家需要点击地鼠得分。
提供返回按钮,点击返回主界面。
系统架构
本项目采用模块化设计,主要分为以下几个模块:
(1)主模块:程序入口,负责初始化资源、启动主界面。
(2)窗口模块:负责各个界面的绘制和用户交互处理。
(3)游戏模块:负责游戏逻辑的实现,包括地鼠生成、点击检测、得分计算等。
(4)资源模块:负责图片、音效等资源的加载和管理。
(5)音效模块:负责音效的播放和管理。
模块功能设计
主模块
主模块负责程序的初始化和启动。
- 初始化随机种子
- 加载图片和音效资源
- 初始化图形界面
- 启动主界面
窗口模块
窗口模块负责各个界面的绘制和用户交互处理。
- 主界面绘制与点击事件处理
- 设置界面绘制与点击事件处理
- 游戏界面绘制与点击事件处理
游戏模块
游戏模块负责游戏逻辑的实现。
- 地鼠洞和地鼠的生成
- 地鼠的随机出现
- 用户点击地鼠的检测
- 游戏时间和得分的更新
- 关卡的管理
资源模块
资源模块负责图片、音效等资源的加载和管理。
- 图片资源的加载和获取
- 音效资源的加载和播放控制
音效模块
音效模块负责音效的播放和管理。
- 音效的播放
- 音效的停止
- 音量的调节
关键算法分析
地鼠生成算法
// 随机生成地鼠
void game::spawnMoles() {
MOUSEMSG m;
int x, y;
while (!destroyed) {
for (auto &row: holes) {
for (auto &hole: row) {
if (rand() < (int) (getDifficultyFactor() * 100.0F)) {
debug("show mole");
hole.mole.show();
}
}
}
delay(50);
}
}
这段代码可以根据游戏的难度因子运用随机数判断该地鼠洞是否应该生成地鼠。
击打检测算法
void game::hitListener() {
MOUSEMSG m;
int x, y;
while (!destroyed) {
m = mouseMessage();
x = m.x;
y = m.y;
for (auto &row: holes) {
for (auto &hole: row) {
if (m.mkLButton && hole.mole.isHited(x, y)) {
debug("mole hited, now score:" + std::to_string(this->score));
// 每击中一个地鼠得5分
score += 5;
}
}
}
delay(10);
}
}
该段代码可以根据地鼠的实体框检测是否被击中。
锤子跟踪算法
// 监听锤子位置
void game::hammerListener() {
IMAGE *tmp;
MOUSEMSG m;
int x, y, last_x, last_y;
while (!destroyed) {
m = mouseMessage();
x = m.x - 50;
y = m.y - 50;
// 还原之前的状态
if (tmp == nullptr) {
tmp = new IMAGE;
} else {
putimage(last_x, last_y, tmp);
}
// 保存之前的状态
getimage(tmp, x, y, 100, 100);
last_x = x;
last_y = y;
// 放置锤子
if (m.mkLButton) {
debug("hammer down.");
putImage(x, y, IMG_HAMMER_DOWN);
} else {
putImage(x, y, IMG_HAMMER);
}
delay(10);
}
}
该段代码可以跟踪鼠标的位置并不断刷新出锤子,同时检测鼠标左键是否按下来设置锤子的运动状态。