用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进行游戏开发。
相关文章:
用Devc++与easyx一步一步做游戏[启动界面部分]-解决hover闪烁问题及优化
在之前的博文中《用Devc与easyx一步一步做游戏[启动界面部分]-之按钮制作》,我们利用Devc和easyx完成了游戏启动界面按钮的基本制作,实现了按钮的绘制以及鼠标悬停时的信息提示功能。然而,目前还存在一个问题,即鼠标移动时&#x…...
mysql 学习3 SQL语句--整体概述。SQL通用语法;DDL创建数据库,查看当前数据库是那个,删除数据库,使用数据库;查看当前数据库有哪些表
SQL通用语法 SQL语句分类 DDL data definition language : 用来创建数据库,创建表,创建表中的字段,创建索引。因此成为 数据定义语言 DML data manipulation language 有了数据库和表以及字段后,那么我们就需要给这个表中 添加数…...
【数据结构】_链表经典算法OJ:分割链表(力扣—中等)
目录 1. 题目描述及链接 2. 解题思路 2.1 思路1 2.2 思路2 2.3 思路3(本题采取该解法) 3. 题解程序 1. 题目描述及链接 题目链接:面试题 02.04. 分割链表 - 力扣(LeetCode) 题目描述: 给你一个链表…...
k8s支持自定义field-selector spec.hostNetwork过滤
好久没写博客啦,年前写一个博客就算混过去啦😂 写一个小功能,对于 Pod,在没有 label 的情况下,支持 --field-selector spec.hostNetwork 查询 Pod 是否为 hostNetwork 类型,只为了熟悉 APIServer 是如何构…...
ICSE‘25 LLM Assistance for Memory Safety
不知道从什么时候开始,各大技术社区,技术群聊流行着 “用Rust重写!” ,放一张图(笑死… 这不, 随着大模型技术的流行,大家都在探索如何让大模型自动完成仓库级别(全程序)的代码重构,代码变换(Refactor&…...
《十七》浏览器基础
浏览器:是安装在电脑里面的一个软件,能够将页面内容渲染出来呈现给用户查看,并让用户与网页进行交互。 常见的主流浏览器: 常见的主流浏览器有:Chrome、Safari、Firefox、Opera、Edge 等。 输入 URL,浏览…...
TikTok 推出了一款 IDE,用于快速构建 AI 应用
字节跳动(TikTok 的母公司)刚刚推出了一款名为 Trae 的新集成开发环境(IDE)。 Trae 基于 Visual Studio Code(VS Code)构建,继承了这个熟悉的平台,并加入了 AI 工具,帮助开发者更快、更轻松地构建应用——有时甚至无需编写任何代码。 如果你之前使用过 Cursor AI,T…...
阅读springboot源码 记录
关于 :: 双冒号 用stream的map简洁提取id,类似代码1 // 代码1 List<String> Ids list.stream().map(Student::getId).collect(Collectors.toList())// 代码2 List<String> Ids list.stream().map(use->{return use.getId(); }).collect(Collector…...
Linux之内存管理前世今生(一)
一个程序(如王者荣耀)平常是存储在硬盘上的,运行时才把这个程序载入内存,CPU才能执行。 问题: 这个程序载入内存的哪个位置呢?载入内核所在的空间吗?系统直接挂了。 一、虚拟内存 1.1 内存分…...
Beautiful Soup 入门指南:从零开始掌握网页解析
Beautiful Soup 入门指南:从零开始掌握网页解析 前言 在数据驱动的时代,网页数据是非常宝贵的资源。很多时候我们需要从网页上提取数据,进行分析和处理。Beautiful Soup 是一个非常流行的 Python 库,可以帮助我们轻松地解析和提…...
网络通信---MCU移植LWIP
使用的MCU型号为STM32F429IGT6,PHY为LAN7820A 目标是通过MCU的ETH给LWIP提供输入输出从而实现基本的Ping应答 OK废话不多说我们直接开始 下载源码 LWIP包源码:lwip源码 -在这里下载 ST官方支持的ETH包:ST-ETH支持包 这里下载 创建工程 …...
Go-并行编程新手指南
Go 并行编程新手指南 在Go语言中,并行编程是充分利用多核CPU资源、提升程序性能的重要手段。它的核心概念包括goroutine和channel,这些特性使得Go在处理并发任务时表现出色。 goroutine:轻量级的并发执行单元 goroutine是Go并行编程的基础…...
基于Django的个人博客系统的设计与实现
【Django】基于Django的个人博客系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 系统采用Python作为主要开发语言,结合Django框架构建后端逻辑,并运用J…...
Python爬虫获取custom-1688自定义API操作接口
一、引言 在电子商务领域,1688作为国内领先的B2B平台,提供了丰富的API接口,允许开发者获取商品信息、店铺信息等。其中,custom接口允许开发者进行自定义操作,获取特定的数据。本文将详细介绍如何使用Python调用1688的…...
kaggle-ISIC 2024 - 使用 3D-TBP 检测皮肤癌-学习笔记
问题描述: 通过从 3D 全身照片 (TBP) 中裁剪出单个病变来识别经组织学确诊的皮肤癌病例 数据集描述: 图像临床文本信息 评价指标: pAUC,用于保证敏感性高于指定阈值下的AUC 主流方法分析(文本) 基于CatBoo…...
滤波电路汇总
0、前言 1. 引言 滤波电路是电子系统中不可或缺的组成部分,其主要功能是选择性地通过或衰减特定频率范围内的信号。在现代电子技术中,滤波电路广泛应用于信号处理、通信系统、音频设备、电源设计等多个领域。通过滤波,可以去除信号中的噪声和干扰,提高信号的质量和稳定性…...
1.Template Method 模式
模式定义 定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method 使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的某些特…...
MySQL分表自动化创建的实现方案(存储过程、事件调度器)
《MySQL 新年度自动分表创建项目方案》 一、项目目的 在数据库应用场景中,随着数据量的不断增长,单表存储数据可能会面临性能瓶颈,例如查询、插入、更新等操作的效率会逐渐降低。分表是一种有效的优化策略,它将数据分散存储在多…...
基于回归分析法的光伏发电系统最大功率计算simulink建模与仿真
目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于回归分析法的光伏发电系统最大功率计算simulink建模与仿真。选择回归法进行最大功率点的追踪,使用光强和温度作为影响因素,电压作为输出进行建模。…...
计算机毕业设计【任务书】怎么写?
1. 什么是毕业设计任务书 毕业设计任务书是学生在毕业设计初期向指导教师提交的文档,主要用于说明毕业设计的选题、研究内容、目标、方法、进度安排等。 2. 撰写任务书的步骤 2.1 确定选题 选题是撰写任务书的第一步。选题应结合自身兴趣、专业方向和实际应用需…...
如何用开源工具实现专业级图像修复与纹理合成?揭秘GIMP Resynthesizer的技术奥秘
如何用开源工具实现专业级图像修复与纹理合成?揭秘GIMP Resynthesizer的技术奥秘 【免费下载链接】resynthesizer Suite of gimp plugins for texture synthesis 项目地址: https://gitcode.com/gh_mirrors/re/resynthesizer 在数字图像处理领域,…...
为什么传统绩效考核正在被OKR取代?2026年企业目标管理的智能化选择
OKR绩效管理系统是帮助企业实施目标与关键成果法(Objectives and Key Results)的数字化工具,通过可视化目标设定、进度追踪和结果评估,让团队目标对齐更清晰、执行更高效。2026年的主流系统已集成AI能力,能自动生成目标…...
DeepAnalyze数据结构优化:提升大规模数据处理性能
DeepAnalyze数据结构优化:提升大规模数据处理性能 1. 引言 当你面对几十GB甚至TB级别的数据集时,是不是经常遇到处理速度慢、内存占用高的问题?DeepAnalyze作为一款强大的AI数据分析工具,在处理大规模数据时,数据结构…...
收藏备用|大模型应用演进3阶段(React/Multi-agent+Spring AI Alibaba实战)
本文详细拆解大模型应用的三大演进阶段,从基础组件构建、工作流编排,到自主Agent落地,重点剖析React模式与Multi-agent模式的核心逻辑及实现原理。结合Spring AI Alibaba框架,手把手演示Java如何快速实现简单Multi-agent框架&…...
关于sms,voip路由以及smpp
SMS 和 VoIP 路由是国际通讯行业核心技术,用于高效传递短信和语音通话。SMPP 协议则是 SMS 传输的关键标准,帮助运营商和企业实现全球消息互联。SMS 基础知识SMS(Short Message Service,短消息服务)是手机最常见的文本…...
如何用CodeMaker将Java/Scala开发效率提升300%?5个核心技巧带你掌握智能代码生成
如何用CodeMaker将Java/Scala开发效率提升300%?5个核心技巧带你掌握智能代码生成 【免费下载链接】CodeMaker A idea-plugin for Java/Scala, support custom code template. 项目地址: https://gitcode.com/gh_mirrors/co/CodeMaker 作为Java/Scala开发者&a…...
快马平台十分钟速成:用AI大模型构建你的第一个智能客服对话Agent原型
最近在尝试用AI大模型构建智能客服对话系统,发现InsCode(快马)平台特别适合快速验证这类原型。花十分钟就能搭建出具备基础功能的对话agent,和大家分享下具体实现思路: 界面设计 先用HTML搭建基础框架,主要包含三个部分࿱…...
利用快马平台AI能力,十分钟快速生成qoderwork官网原型
最近在尝试为AI代码生成工具qoderwork设计官网原型时,发现用传统方式从零开始写代码特别耗时。正好体验了InsCode(快马)平台的AI生成功能,十分钟就做出了可交互的响应式单页原型,分享下这个高效的工作流: 明确核心模块 官网原型需…...
炸锅!Claude Code 完整源码意外泄露,51 万行核心代码直接开源!
突发!Claude Code 意外开源 51 万行源码全网曝光 2026 年 3 月 31 日,AI 圈迎来重磅事件 ——Anthropic 旗下 Claude Code 因 npm 配置失误,通过 source map 文件意外泄露全部源码,超 1900 个文件、51.2 万行 TypeScript 代码公开…...
别再手动翻译Excel了!用Python+腾讯翻译API,5分钟搞定整张表格
别再手动翻译Excel了!用Python腾讯翻译API,5分钟搞定整张表格 当产品经理收到海外用户反馈的CSV文件时,第一反应往往是打开翻译网站逐行复制粘贴。我曾见过同事花三小时处理200条英文评论,而同样的工作用Python脚本只需喝杯咖啡的…...
