用Devc++与easyx一步一步做游戏[启动界面部分]-之按钮制作

news2024/12/24 8:08:22

前面我们介绍了如何为dev c++配置好easyx,至于用easyx能够做一些什么呢?大用处我不敢说,用来学习了解消息机制还是不错的。这我们来实现一个简单的游戏启动界面的设计,主要是按钮的设计。总体设计好的效果如下:
在这里插入图片描述
GIF截图看不到鼠标移动的效果,实际上这里是随着鼠标的移动而显示的效果,鼠标移动到对应的菜单上则下面的提示文字显示对应的内容,离开按钮则恢复显示CopyRight的信息。

一、绘制简单的按钮

1、准备easyx图形环境

easyx环境不会配置的请参考我前面的博文,这里直接从图形环境的代码开始:

#include <graphics.h>      
#include <conio.h>
#include<stdio.h>
#include<easyx.h>
#include <iostream>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv) {
	
	initgraph(640, 480);   
	setbkcolor(0x3B0000);//底色采用的深蓝色,这里用的是BGR的代码,和常规RGB的不同,要注意
	cleardevice();
	
	
	getchar();
	return 0;
}

setbkcolor(0x3B0000)底色采用的深蓝色,这里用的是BGR的代码,和常规RGB的顺序是不同的,要注意三个颜色的顺序。
有了上面的图形,我们至少可以启动一个空白的界面了,在这基础之上我们便有了展开拳脚的舞台了。
在这里插入图片描述
下面,我们准备开始按钮轮廓的绘制。

2、绘制按钮轮廓

我们来绘制按钮的轮廓,这里用到了几个基本的绘制函数,我简单的列在这里,想进一步了解的可以到easyx官网查阅。
setfillcolor:色彩填充函数
fillroundrect:绘制填充型倒角矩形函数
settextstyle:设置文本字体样式
settextcolor:设置字体颜色
outtextxy:绘制文字
textheight/textwidth:设置文字高宽。

int main(int argc, char** argv) {
	
	initgraph(640, 480);   
	setbkcolor(0x3B0000);
	cleardevice();
	//绘制按钮轮廓
	int x=240,y=50;
	int w=150,h=40;
	TCHAR text[20]="Begin";
    setbkmode(TRANSPARENT);   
    setfillcolor(GREEN);
    fillroundrect(x,y,x+w,y+h,10,10);
    TCHAR s1[] = "Arial BLACK";
    settextstyle(30,0,s1);
    settextcolor(WHITE); 
    int tx = x + (w - textwidth(text)) / 2;
    int ty = y + (h - textheight(text)) / 2;
    outtextxy(tx, ty, text);
    
	getchar();
	return 0;
}

绘制完毕,一个简单的按钮轮廓就有了,看起来像了。效果如下:
在这里插入图片描述
绘制完这个简单的按钮,那接下来就要封装按钮绘制函数了,否则后面还有很多的按钮需要绘制,重要的是还有按钮的几个状态也要绘制,总不可能每个都这么绘制。

二、封装按钮添加消息循环

1、封装按钮

void button(int x,int y,TCHAR* text)
{
	
		int w=200,h=44;
	    setbkmode(TRANSPARENT);
	    
	    setfillcolor(GREEN);
	    fillroundrect(x,y,x+w,y+h,10,10);
	    TCHAR s1[] = "Arial BLACK";
	    settextstyle(30,0,s1);
	    settextcolor(WHITE);
	    
	    int tx = x + (w - textwidth(text)) / 2;
	    int ty = y + (h - textheight(text)) / 2;
	
	    outtextxy(tx, ty, text);
}

2、利用封装的按钮绘制一组按钮

//增加一个间隔变量和起始Y坐标变量;
   int gap=40;
   int starty=50;
   int height=50;
    
   //用循环来实现
   TCHAR title[4][50] = {"Load Game","Start Game","Quit Game", "Game Help"};  
   for(int i=0;i<4;i++)
	button(220, starty+i*height+i*gap,  title[i]);

在这里插入图片描述
看起来按钮的形已经有了一个粗的框架了,可惜是不能和我们的鼠标互动,中看不中用,我们接下来就是要让他对我们的鼠标动作有反应。

3、增加消息循环

easyx中的消息循环和我们在VC或者QT中用到的消息循环没有什么差别,有基础的童鞋直接可以上手,没有基础的可能就要了解一下消息循环机制。windows的消息循环我们可以理解为是一张川流不息的物流配送网,任何需要配送的物品都要先送到物流中心然后由中心再配发给各个站点,最终由站点来实现末端配送。
windows采用了一个无限循环来不停的收发来及鼠标键盘及其他输入设备的信息(这些信息就是物流要配送的物品),谁来收这些各个站点送来的物品(各输入设备输入的消息)呢?easyx提供了几个专业的消息函数,如下:
ExMessage :消息结构体。
flushmessage:清空消息缓冲区。
getmessage:获取一个消息。如果当前消息缓冲区中没有,就一直等待。
peekmessage:获取一个消息,并立即返回。
这里我们选用peekmessage,这个函数的即使反馈能力好,不会让你等太久。我们来看这个函数的用法:
bool peekmessage(ExMessage *msg, BYTE filter = -1, bool removemsg = true);
对于新童鞋,咋一看有点复杂吧,有一个消息指针msg和一个字节和一个布尔变量,细看,其实后两个参数都是有默认值的,所以调用起来很方便,最简单的调用如下:

 ExMessage *msg; //声明一个消息指针
    while (true) {
     if (peekmessage(msg, EM_MOUSE)) {
         switch (msg->message)
         {
	         case WM_LBUTTONDOWN:break;	//鼠标按键动作都在这里处理了
	         case WM_MOUSEMOVE:break;	//鼠标移动和鼠标悬停都在这里处理了
	         default:break;
         }
     }

看这个调用框架是不是感觉是否简单,对,本来就十分简单。接下来我们就要通过鼠标移动来增加按钮信息提示效果了。思路是当鼠标进入到我们绘制按钮的区域就显示对应的按钮消息,所以关键点是必须获得鼠标的位置,这个鼠标的位置其实早就被系统打包在消息里面了,也就是说鼠标位置属于消息的一个属性。看下面代码:

	ExMessage msg; //声明一个消息指针
	    while (true) {
	     if (peekmessage(&msg, EM_MOUSE)) {
	         switch (msg.message)
	         {
		         case WM_LBUTTONDOWN:break;	
		         case WM_MOUSEMOVE:
				 if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 50 && msg.y <= 50 + 50)
	             outtextxy(220, 420, title[0]);
	             if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 140 && msg.y <= 140 + 50)
	             outtextxy(220, 420, title[1]);
	             if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 230 && msg.y <= 230 + 50)
	             outtextxy(220, 420, title[2]);
	             if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 320 && msg.y <= 320 + 50)
	            outtextxy(220, 420, title[3]);
				  break;	
		         default:break;
	         }
	     }
	    }
 

上面的消息循环已经起作用了,但有个问题,那就是上一次显示的文字和当前次显示的文字会重叠在一起,如下:
在这里插入图片描述
再来一次,就叠加在一起了。
在这里插入图片描述
所以,我们必须在每一次绘制提示文字前清除文字绘制区域,这里用到了一个函数clearrectangle,这里很清楚了,是清楚一个矩形区域,我们在绘制文字前加上它即可。
上面的代码问题还很多,或者说还很粗暴,因为都是一个个坐标直接在每个分支中重复的输入,遇到调整修改那就是一场灾难(如果分支够多的话)。所这里也需要封装。
我们将提示文字的输出封装为tipInfo,如下:

void tipInfo(RECT rc,TCHAR * titles)
{
	clearrectangle(rc.left,rc.top,rc.right,rc.bottom);
	outtextxy(rc.left, rc.top, titles[0]);
}

	ExMessage msg; //声明一个消息指针
	    while (true) {
	     if (peekmessage(&msg, EM_MOUSE)) {
	         switch (msg.message)
	         {
		         case WM_LBUTTONDOWN:break;	
		         case WM_MOUSEMOVE:
				 if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 50 && msg.y <= 50 + 50)
	             tipInfo(tipInfoRect, title[0]);
	             if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 140 && msg.y <= 140 + 50)
	             tipInfo(tipInfoRect, title[1]);
	             if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 230 && msg.y <= 230 + 50)
	             tipInfo(tipInfoRect, title[2]);
	             if (msg.x >= 220 && msg.x <= 220 + 170 && msg.y >= 320 && msg.y <= 320 + 50)
	             tipInfo(tipInfoRect, title[3]);
				  break;	
		         default:break;
	         }
	     }
	    }

这样,上面的问题一并解决了,但鼠标移动的时候,下面的提示也会随之闪烁,这可不是我们愿意看到的。
下一篇博文,我们解决hover状态时的闪烁问题。请继续关注。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183262.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(免费分享)springboot音乐网站

开发工具&#xff1a;eclipse&#xff0c;数据库mysql5.7 jdk1.8技术&#xff1a;springbootmybatis/** * * * */package com.bjpowernode.music.ss.service.impl;import javax.annotation.Resource;import com.bjpowernode.music.common.AbstractService; import com.bjpowe…

基于 ROS 机器人和 RTAB-MAP 算法实现室内三维重建

本文叙如何利用RTAB-Map算法和Turtlebot3机器人在自己构建的室内场景中建图 文章目录1、安装依赖2、创建工作空间3、安装rtabmap和rtabmap_ros4、建立gazebo场景功能包5、建立机器人功能包6、为机器人添加kinect相机参考7、编译工作空间8、建立环境地图9、建图1、安装依赖 必要…

数据结构第五周 :(进制转换问题 + 迷宫自动行走问题 + 杨辉三角形 + 队列元素逆置 + 银行排队 + 整数划分问题 + 卡特兰数)

目录进制转换问题迷宫自动行走问题杨辉三角形队列元素逆置银行排队——队列整数划分问题买票问题——卡特兰数小兔的棋盘——卡特兰数进制转换问题 【问题描述】根据课堂讲授&#xff0c;请用“顺序栈”解决进制转换问题&#xff0c;不采用顺序栈&#xff0c;不给分。 【输入形…

前端屏幕录制工具 + 录制<video>标签内容

一、录制的实现思路 1.开始录制、停止录制、下载视频 2.Blob介绍 3.概念 var mediaRecord //用于录制视频 var mediaStream //视频流 var videoBuffer [] //保存的视频数据二、屏幕录制工具 下载地址&#xff1a; https://chrome.google.com/webstore/detail/tampermonkey…

Linux- 系统随你玩之--文本处理三剑客--grep继任者awk

文章目录1、sed概述1.1、 与vim等编辑器的区别&#xff1a;1.2、sed工作原理1.3 、sed数据处理原理1.4 、正则表达式概念2、 sed语法和常用选项2.1、语法&#xff1a;2.2、sed常用内部命令2.3、参数&#xff1a;3、 sed 正则表达式&#xff08;定位&#xff09;3.1 、数字定址…

管理机密(RH294)

在ansible中有一个命令行工具ansible-vault可用于创建 编辑 加密 解密 查看文件举个栗子ansible-vaultcreate filenameNew Vault password&#xff1a; #输入密码Confirm New Vault password&#xff1a; #确认密码也可以使用别的方法 比如创建一个密码文件ansible-vaultcreate…

互联网开发必读Git工具利器-《30天精通Git版本控管》中文版免费分享

本书介绍在软体开发领域&#xff0c;对原始码进行版本控管是非常重要的一件事&#xff0c;有别于Subversion或TFS这类集中式版本控管系统&#xff0c;Git是一套分散式版本控管系统&#xff0c;并带来许多版本控管上的各种优势与解决传统集中式版本控管的缺失&#xff0c;例如支…

Spring Cloud_Hystrix断路器

目录一、概述1.分布式系统面临的问题2.是什么3.能干嘛4.官网资料5.Hystrix官宣&#xff0c;停更进维二、Hystrix重要概念1.服务降级Fallback2.服务熔断Breaker3.服务限流Flowlimit三、hystrix案例1.构建2.高并发测试3.故障现象和导致原因4.上诉结论5.如何解决&#xff1f;解决的…

面试_Selenium常见问题

1.selenium 工作原理 1.对于每一条Selenium脚本&#xff0c;一个http请求会被创建并且发送给浏览器的驱动 2.浏览器驱动中包含了一个HTTP Server&#xff0c;用来接收这些http请求 3.HTTP Server接收到请求后根据请求来具体操控对应的浏览器 4.浏览器执行具体的测试步骤 5.浏览…

Smali语法小记

Smali语法小记 介绍 在执行 Android Java 层的代码时&#xff0c;其实就是 Dalvik(ART) 虚拟机&#xff08;使用 C 或 C 代码实现&#xff09;在解析 Dalvik 字节码&#xff0c;从而模拟程序的执行过程。 自然&#xff0c;Dalvik 字节码晦涩难懂&#xff0c;研究人员们给出了…

通过 eShopOnContainers 项目学习一下微服务

这里是项目地址 https://github.com/dotnet-architecture/eShopOnContainers, 这是微软创建的一个基于 .NET 平台的微服务架构的示例应用程序&#xff0c;里面基本上市面上主流的时髦的技术都用上了。 因为涉及的内容比较多&#xff0c;所以我们只简单查看一下微服务的代码实现…

信息抽取命名实体识别和关系抽取)

信息抽取的定义为&#xff1a;从自然语言文本中抽取指定类型的实体&#xff0c;关系、事件等事实信息。并形成结构化数据输出的文本处理技术。 信息抽取是从文本数据中抽取特定信息的一种技术&#xff0c;文本数据由医学具体的单位构成&#xff0c;例如&#xff0c;句子、段落、…

JavaWeb—Vue的简单介绍

1 Vue介绍 概述 Vue是一套构建用户界面的渐进式前端框架。只关注视图层&#xff0c;并且非常容易学习&#xff0c;还可以很方便的与其它库或已有项目整合。通过尽可能简单的API来实现响应数据的绑定和组合的视图组件。 数据渲染 数据库 --JDBC–> java程序 --http协议–>…

《MySQL实战45讲》——学习笔记23 “binlogredolog 的写入机制/组提交机制“

本篇主要介绍数据的可靠性有关的知识&#xff0c;包括binlog的写入机制和redolog的写入机制&#xff0c;通过了解这些机制从而可以在MySQL的IO性能瓶颈上做些优化&#xff1b;前文介绍了MySQL在可靠性、性能相关的概念&#xff0c;包括WAL技术、redolog与binlog、2阶段提交、ch…

阿里云图标使用 (symbol 引用方式)

阿里云图标网址: https://www.iconfont.cn/ 一、登录注册 这个简单&#xff0c;就不说了 二、给当前项目找图库 2.1、添加项目 2.2、寻找图标添加入库 添加入库 2.3、打开入库 的图标添加到指定项目 添加到当前项目 1 2 三、项目使用图标 ( symbol 引用方式) 3.1、下…

《HelloGitHub》第 82 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01;简介HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。https://github.com/521xueweihan/HelloGitHub这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Pyth…

Studio One6有哪些新功能及系统配置要求介绍

Studio One6全新版本上线记录、生产、混合、掌握和执行所有操作。从工作室到舞台&#xff0c;Studio One6以易用为核心&#xff0c;是您的创意合作伙伴。当你准备好登上舞台时&#xff0c;Studio One就在那里。只有Studio One从最初的灵感到完整的制作&#xff0c;最终混音到精…

一个数码管显示0-F

数码管的一种是半导体发光器件&#xff0c;数码管可分为七段数码管和八段数码管&#xff0c;区别在于八段数码管比七段数码管多一个用于显示小数点的发光二极管单元DP&#xff08;decimal point&#xff09;&#xff0c;其基本单元是发光二极管。七段数码管是一类价格便宜使用简…

VuePress 搭建结合GitHub Pages CI

简介 VuePress 是尤雨溪&#xff08;vue.js 框架作者&#xff09;4月12日发布的一个全新的基于 vue 的静态网站生成器&#xff0c;实际上就是一个 vue 的 spa 应用&#xff0c;内置 webpack&#xff0c;可以用来写文档。详见 VuePress中文网 其实类似的建站工具有很多&#x…

Java多线程 - 创建线程池的方法 - ThreadPoolExecutor和Executors

文章目录线程池(重点)线程池介绍实现线程池的方式方式一: 实现类ThreadPoolExecutorThreadPoolExecutor构造器的参数线程池处理Runnable任务线程池处理Callable任务方式二: Executors工具类创建线程池线程池(重点) 线程池介绍 什么是线程池? 线程池就是一个可以复用线程的技…