用Devc++与easyx一步一步做游戏[启动界面部分]-解决hover闪烁问题及优化
在之前的博文中《用Devc++与easyx一步一步做游戏[启动界面部分]-之按钮制作》,我们利用Devc++和easyx完成了游戏启动界面按钮的基本制作,实现了按钮的绘制以及鼠标悬停时的信息提示功能。然而,目前还存在一个问题,即鼠标移动时,提示文字会出现闪烁现象,有很多童鞋在阅读后都表示出了兴趣。这篇博文我们就来解决这个问题并对代码进行优化。
文章目录
- 一、解决闪烁问题
- 1. 问题分析
- 2. 解决方案
- 二、代码优化
- 1. 坐标和尺寸管理
- 2. 代码结构优化
一、解决闪烁问题
1. 问题分析
提示文字闪烁的原因在于,每次鼠标移动触发WM_MOUSEMOVE
消息时,都会频繁地清除矩形区域并重新绘制文字。这导致画面不断刷新,从而产生闪烁感。为了解决这个问题,我们需要减少不必要的绘制操作。
2. 解决方案
我们可以通过记录当前鼠标悬停的按钮状态来判断是否需要更新提示文字。如果鼠标仍然悬停在同一个按钮上,就不需要重复清除和绘制。只有当鼠标从一个按钮移到另一个按钮时,才进行相应的操作。
在代码中,我们定义一个全局变量currentButtonIndex
来记录当前鼠标悬停的按钮索引,初始值设为 -1,表示没有悬停在任何按钮上。
int currentButtonIndex = -1;
然后,修改消息循环中的WM_MOUSEMOVE
处理逻辑:
ExMessage msg;
while (true) {
if (peekmessage(&msg, EM_MOUSE)) {
switch (msg.message) {
case WM_LBUTTONDOWN:
break;
case WM_MOUSEMOVE:
int newButtonIndex = -1;
if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 50 && msg.y <= 50 + 50)
newButtonIndex = 0;
else if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 140 && msg.y <= 140 + 50)
newButtonIndex = 1;
else if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 230 && msg.y <= 230 + 50)
newButtonIndex = 2;
else if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 320 && msg.y <= 320 + 50)
newButtonIndex = 3;
if (newButtonIndex != currentButtonIndex) {
// 清除之前的提示文字
if (currentButtonIndex != -1) {
RECT prevRect = {220, 420, 220 + 170, 420 + 30}; // 根据文字大小调整矩形区域
clearrectangle(prevRect.left, prevRect.top, prevRect.right, prevRect.bottom);
}
currentButtonIndex = newButtonIndex;
if (currentButtonIndex != -1) {
tipInfo(tipInfoRect, title[currentButtonIndex]);
}
}
break;
default:
break;
}
}
}
通过上述代码,只有当鼠标悬停的按钮发生变化时,才会清除之前的提示文字并绘制新的提示文字,有效地解决了闪烁问题。
二、代码优化
1. 坐标和尺寸管理
之前的代码中,按钮的坐标和尺寸都是直接写在代码里,这样不利于修改和维护。我们可以将这些参数定义为常量或者结构体,方便统一管理。
// 定义按钮相关常量
const int BUTTON_WIDTH = 170;
const int BUTTON_HEIGHT = 50;
const int BUTTON_GAP = 40;
const int START_Y = 50;
const int TIP_X = 220;
const int TIP_Y = 420;
然后在绘制按钮和判断鼠标位置时使用这些常量:
// 绘制按钮
for(int i = 0; i < 4; i++) {
int x = 220;
int y = START_Y + i * (BUTTON_HEIGHT + BUTTON_GAP);
button(x, y, title[i]);
}
// 判断鼠标位置
if (msg.x >= TIP_X && msg.x <= TIP_X + BUTTON_WIDTH && msg.y >= START_Y && msg.y <= START_Y + BUTTON_HEIGHT)
newButtonIndex = 0;
// 其他按钮判断类似,修改对应y坐标即可
2. 代码结构优化
随着功能的增加,代码逐渐变得复杂,我们可以进一步优化代码结构,将不同功能的代码封装到独立的函数中。例如,将消息循环部分封装到一个函数handleMouseMessages
中:
void handleMouseMessages() {
ExMessage msg;
while (true) {
if (peekmessage(&msg, EM_MOUSE)) {
switch (msg.message) {
case WM_LBUTTONDOWN:
break;
case WM_MOUSEMOVE:
int newButtonIndex = -1;
// 判断鼠标位置逻辑不变
//...
if (newButtonIndex != currentButtonIndex) {
// 清除和绘制逻辑不变
//...
}
break;
default:
break;
}
}
}
}
在main
函数中调用这个函数:
int main(int argc, char** argv) {
initgraph(640, 480);
setbkcolor(0x3B0000);
cleardevice();
// 绘制按钮
for(int i = 0; i < 4; i++) {
int x = 220;
int y = START_Y + i * (BUTTON_HEIGHT + BUTTON_GAP);
button(x, y, title[i]);
}
handleMouseMessages();
getchar();
closegraph();
return 0;
}
通过上述优化,代码的可读性和可维护性都得到了显著提升。
到这里,游戏启动界面按钮的制作已经基本完成,解决了闪烁问题并对代码进行了优化。后续我们可以继续完善游戏启动界面的其他功能,如按钮点击事件的处理等。希望这篇博文能帮助大家更好地理解和运用Devc++与easyx进行游戏开发。