当前位置: 首页 > article >正文

用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进行游戏开发。


http://www.kler.cn/a/521030.html

相关文章:

  • Arduino大师练成手册 -- 控制 PN532 NFC 模块
  • 第 25 场 蓝桥月赛
  • 什么是AI Agent?
  • Vue.js 什么是 Vuex?
  • 基于新年视角下的城市人流数据分析
  • Baklib赋能下的内容中台智能化推荐系统解析与展望
  • Mac cursor设置jdk、Maven版本
  • Qt中QVariant的使用
  • 【橘子ES】使用docker搭建ELK环境
  • 2025美赛数学建模C题:奥运奖牌榜模型——思路+代码+模型
  • 二维数组一
  • Linux系统之ifconfig命令的基本使用
  • 2274. 不含特殊楼层的最大连续楼层数
  • 嵌入式C语言:结构体对齐
  • 前部分知识复习01
  • SpringBoot使用 easy-captcha 实现验证码登录功能
  • spring spring-boot spring-cloud发布以及适配
  • SAP MM 记录一次SAP外协采购收货提示 这种物料的特殊库存 O 0100003359 14019002不存在的问题
  • PTMD2.0-疾病相关的翻译后修饰数据库
  • 数字图像处理:实验七