EasyX图形库基础使用教程(快速上手)

2 篇文章 0 订阅

EasyX图形库基础使用教程(快速上手)

前言:本文简单详细的介绍了EasyX图形库的常用函数和操作,帮助EasyX的快速上手

1、绘制简单的图形窗口

1.1头文件

graphics.h :包含已经被淘汰的函数

easyx.h: 只包含最新的函数

1.2创建图形化窗口

initgraphy函数

initgraph函数

HWND initgraph(
	int width,		//绘图窗口的宽度
	int height,		//绘图窗口的高度
    int flag=NULL	//绘图窗口的样式,默认为NULL,
);

flag的值还可以为:

含义
EX_DBLCLKS在绘图窗口中支持鼠标双击事件。
EX_NOCLOSE禁用绘图窗口的关闭按钮。
EX_NOMINIMIZE禁用绘图窗口的最小化按钮。
EX_SHOWCONSOLE显示控制台窗口。

简单句两个例子,其他同理:

创建一个尺寸为 640x480 的绘图窗口:

initgraph(640, 480);

创建一个禁用绘图窗口的关闭按钮并且尺寸为 640x480 的绘图窗口:

initgraph(640, 480,EX_NOCLOSE);

closegraph函数

closegraph函数

用于关闭绘图窗口void closegraph();

1.3窗口坐标

坐标轴及原点可按如图理解:

2、设置图形窗口属性

2.1颜色设置

setbkcolo

setbkcolor函数

void setbkcolo(COLORREF color);

注:在设置背景颜色后并不会改变现有的背景色,只是改变了背景色的值,之后再执行绘图语句,例如outtextxy,才会使用新设置的背景色值。

函数()中的值就是各种颜色对应的英文,在VS中可以右键—跳转到定义查看,以setbkcolo(RED)为例,右键RED跳转,可以看到各种颜色的值。

RGB

RGB函数

COLORREF RGB(
	BYTE byRed,		// 颜色的红色部分
	BYTE byGreen,	// 颜色的绿色部分
	BYTE byBlue		// 颜色的蓝色部分
);

使用三原色进行调光,原理同画图中的调色板,可以找到喜欢的颜色把三原色的数字输入,注意使用RGB时也要在外面加setbkcolor(),例:

setbkcolor(RGB(200,100,100));
cleardevice 刷新

cleardevice函数

void cleardevice();

使用当前别景色清空绘图设备,刷新颜色。

3、使用EasyX实现基本绘图功能

3.1 line 画线

line函数

void line(
	int x1,	 int y1,  int x2,  int y2,
);

在(x1,y1)和(x2,y2)两点间画一条线段。

3.1 circle 画圆

circle函数

void circle(
	int x,	int y,	int radius
);

以坐标(x,y)为圆心,画一个半径为radius的圆

3.2 rectangle 画矩形

rectangle函数

void rectangle(
	int left,	int top,	int right,	int bottom
);

确定举行的左上角和右下角坐标,画一个矩形

3.3 setfillcolor 填充颜色

setfillcolor函数

void setfillcolor(COLORREF color);

填充圆

  • 带线: fillcircle(int x, int y, int r);
  • 不带线: solidcircle(int x, int y, int r);

填充矩形

  • 带线: fillrectangle(int x1, int y1, int x2, int y2);

  • 不带线: solidrectangle(int x1, int y1, int x2, int y2);

代码举例:

int main()
{
	initgraph(700, 550);		//初始化图形界面尺寸
	setfillcolor(LIGHTBLUE);	//设置填充颜色
	fillcircle(150, 150, 50);	//画一个带线的圆
	solidcircle(300, 150, 50);	//画一个不带线的圆

	fillrectangle(150, 300, 280, 450);	//画一个带线的矩形
	solidrectangle(150, 300, 280, 450);	//画一个不带线的矩形

	while (1);		//防止图形化窗口一闪而过
	closegraph();	//关闭窗口
	return 0;
}

效果如图:

4、使用EasyX实现贴图功能

4.1 原样贴图

putimage 绘制图像

putimage函数

void putimage(
	int dstX,				// 绘制位置的 x 坐标
	int dstY,				// 绘制位置的 y 坐标
	IMAGE *pSrcImg,			// 要绘制的 IMAGE 对象指针
	DWORD dwRop = SRCCOPY	// 三元光栅操作码
);
void putimage(
	int dstX,				// 绘制位置的 x 坐标
	int dstY,				// 绘制位置的 y 坐标
	int dstWidth,			// 绘制的宽度
	int dstHeight,			// 绘制的高度
	IMAGE *pSrcImg,			// 要绘制的 IMAGE 对象指针
	int srcX,				// 绘制内容在 IMAGE 对象中的左上角 x 坐标
	int srcY,				// 绘制内容在 IMAGE 对象中的左上角 y 坐标
	DWORD dwRop = SRCCOPY	// 三元光栅操作码
);

如果要实现简单的贴图只需要写putimage(0,0,&img);即在坐标(0,0)的位置绘制img图像,结合下文更清晰。

loadimage 加载图像

loadimage函数

loadimage(IMAGE* img,URL);//IMAGE是一种图像对象

其中,IMAGE是一种图像对象,可以参考IMAGE,URL是想要贴上的图片的相对位置,注意将图片放到源文件的路径下,如下代码中,"./Source/1.jpg"就是源文件同路径下的Source文件夹下的文件名叫做1.jpg的图片。

代码实例:

int main()
{
	initgraph(700, 600);
	int a = 1;
	IMAGE img;
	loadimage(&img, "./Source/1.jpg");
	putimage(0, 0, &img);
	while (1);
	closegraph();
	return 0;
}

效果如下:

但是使用上述方法贴图效果无法做到合适窗口的尺寸,因此有下面的方法来进行缩放

loadimage(IMAGE* img,URL,int width,int height);

代码实例(将上面的代码中的loading函数增加两个参数即可,其余不变)

int main()
{
	initgraph(700, 600);
	int a = 1;
	IMAGE img;
	loadimage(&img, "./Source/1.jpg"700600);
	putimage(0, 0, &img);
	while (1);
	closegraph();
	return 0;
}

效果如下:

4.2 透明贴图

  • 通过图像的二进制运算达到去背景的效果

  • 认识素材

    • 掩码图
    • 背景图
  • 三元光栅操作码(仅介绍用得上的其中两个,其余可以参考putimageTernary raster operations

    • SRCAND 目标图像 = 目标图像 AND 源图像 贴掩码图
    • SRCPAINT 目标图像 = 目标图像 OR 源图像 贴背景图
  • 实例:

    int main()
    {
    	initgraph(800, 600);
    	int a = 1;
    	IMAGE img;
    	loadimage(&img, "./Source/1.jpg",1000,600);
    	putimage(0, 0, &img);
    
    	IMAGE pic[2];//创建一个IMAGE类型的数组
    	loadimage(&pic[0], "./Source/掩码图.png",400,400);
    	loadimage(&pic[1], "./Source/背景图.png", 400, 400);
    	putimage(150, 50, &pic[0],SRCAND);    //先贴掩码图
    	putimage(150, 50, &pic[1],SRCPAINT);  //再贴背景图
    
    	while (1);
    	closegraph();
    	return 0;
    }
    

4.3双缓冲贴图

BeginBatchDraw 开始双缓冲

BeginBatchDraw函数

void BeginBatchDraw();

在一个图形化的物体移动过程中,如果直接打印,会出现明显的闪烁,如以下代码(可以实现一个圆从左到右的移动):

#include <graphics.h>

int main()
{
	initgraph(640,480);
	setlinecolor(WHITE);
	setfillcolor(RED);

	for(int i=50; i<600; i++)
	{
		cleardevice();
		circle(i, 100, 40);
		floodfill(i, 100, WHITE);
		Sleep(10);
	}
	closegraph();
}

要解决这个问题就可以使用双缓冲贴图,简单来说,开始双缓冲后,绘画操作会暂时不输出到绘画窗口上,知道执行FlusBatchDraw函数或EndBatchDraw函数才将之前的绘图输出,这两个函数见下文。

EndBatchDraw 结束双缓冲

EndBatchDraw函数

void EndBatchDraw();

当需要结束双缓存贴图并执行指定区域内未完成的绘制任务时,可参照以下:

void EndBatchDraw(
	int left,	//指定区域左边的x坐标
	int top,	//指定区域上边的y左边
	int right,	//指定区域右边的x坐标
	int bottom	//指定区域下边的y坐标
);
FlushBatchDraw 显示一帧

FlushBatchDraw函数

void FlushBatchDraw();

当需要执行指定区域内未完成的绘制任务时,可参考以下:

void FlushBatchDraw(
	int left,	//指定区域左边的x坐标
	int top,	//指定区域上边的y左边
	int right,	//指定区域右边的x坐标
	int bottom	//指定区域下边的y坐标
);

使用以上的三个函数再将上面的圆的移动的代码进行优化,如下:

#include <graphics.h>

int main()
{
	initgraph(640,480);
	BeginBatchDraw();				//开始双缓冲贴图

	setlinecolor(WHITE);
	setfillcolor(RED);

	for(int i=50; i<600; i++)
	{
		cleardevice();
		circle(i, 100, 40);
		floodfill(i, 100, WHITE);
		FlushBatchDraw();			//绘画出当前帧的图案
		Sleep(10);
	}

	EndBatchDraw();					//双缓冲贴图结束
	closegraph();
}

5、实现EasyX按键件交互功能

阻塞按键交互

简单理解就是在程序运行过程中有输入等交互环节的,会在中途暂停程序直到输入完成互动再继续

比如在一个小程序中有一个可以通过上下左右控制运动的小球,按下→键,小球向右动了一下停下,等待下面的指令,直到再按下一个按键才继续,这就是一个阻塞。

非阻塞按键交互

简单理解是在一个程序中按键输入等交互动作不中断程序的运行

我们可以使用conic.h头文件下的getch()函数来读取键盘的内容,getch()函数(详情可见getch() 函数的简单使用

通过使用getch()和EasyX再加上打印图形的配合使用,可以达到一个通过键盘输入值控制窗口物体移动的效果。除了使用getch()函数,还可以使用Win 32 API下的GetAsyncKeyState函数来获取键盘键值达到键盘控制的效果,详情可以参考贪吃蛇小游戏中二、10下的内容。

6、在EasyX中进行鼠标操作

ExMessage 保存鼠标信息

ExMessage结构体

ExMessage是一个结构体,用来保存鼠标信息,定义如下:

struct ExMessage
{
	USHORT message;					// 消息标识
	union
	{
		// 鼠标消息的数据
		struct
		{
			bool ctrl		:1;		// Ctrl 键是否按下
			bool shift		:1;		// Shift 键是否按下
			bool lbutton	:1;		// 鼠标左键是否按下
			bool mbutton	:1;		// 鼠标中键是否按下
			bool rbutton	:1;		// 鼠标右键
			short x;				// 鼠标的 x 坐标
			short y;				// 鼠标的 y 坐标
			short wheel;			// 鼠标滚轮滚动值,为 120 的倍数
		};

		// 按键消息的数据
		struct
		{
			BYTE vkcode;			// 按键的虚拟键码
			BYTE scancode;			// 按键的扫描码(依赖于 OEM)
			bool extended	:1;		// 按键是否是扩展键
			bool prevdown	:1;		// 按键的前一个状态是否按下
		};

		// 字符消息的数据
		TCHAR ch;

		// 窗口消息的数据
		struct
		{
			WPARAM wParam;
			LPARAM lParam;
		};
	};
};

PeekMessage 获取鼠标信息

peekmessage函数

bool peekmessage(ExMessage *msg, BYTE filter = -1, bool removemsg = true);
  • msg是指向ExMessage的指针,用来保存获取到的信息

  • filter指定获取的信息范围,默认-1获取所有类别的消息,还可以用以下值:

    标志描述
    EX_MOUSE鼠标消息。
    EX_KEY按键消息。
    EX_CHAR字符消息。
    EX_WINDOW窗口消息。
  • removemsg:在peekmessage处理完消息后,是否将其从消息队列中移除

如果获取到了消息,则返回true,否则返回false

案例:

#include <graphics.h>
int main()
{
	initgraph(800, 800);
	ExMessage msg;
	while (1) {
		while (peekmessage(&msg)) {
			switch (msg.message) {
			case WM_LBUTTONDOWN: {
				circle(msg.x, msg.y, 10);
				break;
			}
				//按下左键,在鼠标按下的位置画圆
			case WM_RBUTTONDOWN: {
				rectangle(msg.x - 5, msg.y - 5, msg.x + 5, msg.y + 5);
				break;
				//按下右键,在鼠标按下的位置画方
			}
			}
		}
	}
	return 0;
}

OW | 窗口消息。 |

  • removemsg:在peekmessage处理完消息后,是否将其从消息队列中移除

如果获取到了消息,则返回true,否则返回false

案例:

#include <graphics.h>
int main()
{
	initgraph(800, 800);
	ExMessage msg;
	while (1) {
		while (peekmessage(&msg)) {
			switch (msg.message) {
			case WM_LBUTTONDOWN: {
				circle(msg.x, msg.y, 10);
				break;
			}
				//按下左键,在鼠标按下的位置画圆
			case WM_RBUTTONDOWN: {
				rectangle(msg.x - 5, msg.y - 5, msg.x + 5, msg.y + 5);
				break;
				//按下右键,在鼠标按下的位置画方
			}
			}
		}
	}
	return 0;
}
  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值