一、基本说明
EasyX 是针对 C++ 的图形库,可以帮助 C/C++ 初学者快速上手图形和游戏编程。
比如可以基于 EasyX 图形库很快地用几何图形画一个房子,或者一辆移动的小车,可以编写俄罗斯方块、贪吃蛇、黑白棋等小游戏,可以练习图形学的各种算法,等等。
二、基本概念
2.1 - 颜色
EasyX 使用 24 bit 真彩色,不支持调色板模式。
像素是计算机屏幕上所能显示的最小单位,用来表示图像的单位。
分辨率指屏幕上像素的数目,为了控制像素的亮度和彩色深度,每个像素需要很多个二进制位来表示,如果要显示 256 种颜色,则每个像素至少需要 8 位(一个字节)来表示,即 2 ^ 8 = 256;如果要显示 24 位真彩色,则每个像素要用 3 个字节存储。
真彩色是指图像中的每个像素值都分成 R、G、B 三个基色分量,每个基色分量直接决定其基色的强度,这样产生的色彩称为真彩色。
例如图像深度为 24,用 R: G: B = 8: 8: 8 来表示色彩,即 R、G、B 都用 8 位来表示,每个基色分量占一个字节,共 3 个字节,每个像素的颜色就是由这 3 个字节中的数值直接决定,可生成的颜色数就是 2 ^ 24 = 16 777 216 种。24 位真彩色可以达到人眼分辨的极限。
表示颜色的方法:
- 用预定义常量表示颜色,例如 BLACK、WHITE、BLUE 等。
- 用 16 进制数字表示颜色,16 进制的颜色表示规则为:0xbbggrr(bb = 蓝,gg = 绿,rr = 红)
- 用 RGB 宏合成颜色(详见 RGB)。
- 用 HSLtoRGB、HSVtoRGB 转换其他色彩模型到 RGB 颜色(详见 HSLtoRGB、HSVtoRGB )。
2.2 - 坐标
在 EasyX 中,坐标分两种:物理坐标和逻辑坐标。
-
物理坐标:
物理坐标是描述设备的坐标体系。
坐标原点在设备的左上角,X 轴向右为正,Y 轴向下为正,度量单位是像素。
坐标原点、坐标轴方向、缩放比例都不能改变。
-
逻辑坐标:
逻辑坐标是在程序中用于绘图的坐标体系。
坐标默认的原点在窗口的左上角,X 轴向右为正,Y 轴向下为正,度量单位是点。
默认情况下,逻辑坐标与物理坐标是一一对应的,一个逻辑点等于一个物理像素。
在本手册中,凡是没有注明的坐标,均指逻辑坐标。
2.3 - 设备
"设备",是指绘图表面。
在 EasyX 中,设备分为两种,一种是默认的绘图窗口,另一种是 IMAGE 对象。通过 SetWorkingImage 函数可以设置当前用于绘图的设备。
设置当前用于绘图的设备后,所有的绘图函数都会绘制在该设备上。
三、绘图设备相关函数
3.1 - initgraph
这个函数用于初始化绘图窗口。
HWND initgraph(int width, int height, int flag = NULL);
参数:
-
width:绘图窗口的宽度。
-
height:绘图窗口的高度。
-
flag:绘图窗口的样式,默认为 NULL。可以为以下值:
值 含义 EW_DBLCLKS 在绘图窗口中支持鼠标双击(double clicks)事件 EW_NOCLOSE 禁用绘图窗口的关闭按钮(no close) EW_NOMINIMIZE 禁用绘图窗口的最小化按钮(no minimize) EW_SHOWCONSOLE 显示控制台窗口(show console)
返回值:
- 返回新建绘图窗口的句柄(HWND)。
示例:
// 创建一个尺寸为 640 x 480 的绘图窗口
initgraph(640, 480);
// 创建一个尺寸为 640 x 480 的绘图窗口,同时显示控制台窗口
initgraph(640, 480, EW_SHOWCONSOLE);
// 创建一个尺寸为 640 x 480 的绘图窗口,同时显示控制台窗口,并禁用关闭按钮
initgraph(640, 480, EW_SHOWCONSOLE | EW_NOCLOSE);
3.2 - closegraph
这个函数用于关闭绘图窗口。
void closegraph();
3.3 - cleardevice
这个函数使用当前背景色清空绘图设备。
void cleardevice();
四、颜色模型
3.1 - RGB
RGB 宏用于将红、绿、蓝颜色分量合成颜色。
COLORREF RGB(BYTE byRed, BYTE byGreen, BYTE byBlue);
参数:
- byRed:颜色的红色部分,取值范围:0 ~ 255。
- byGreen:颜色的绿色部分,取值范围:0 ~ 255。
- byBlue:颜色的蓝色部分,取值范围:0 ~ 255。
返回值:
- 返回合成的颜色。
3.2 - HSLtoRGB
该函数用于转换 HSL 颜色为 RGB 颜色。
COLORREF HSLtoRGB(float H, float S, float L);
参数:
- H:原 HSL 颜色模型的 Hue(色相)分量,0 <= H < 360。
- S:原 HSL 颜色模型的 Saturation(饱和度)分量,0 <= S <= 1。
- L:原 HSL 颜色模型的 Lightness(亮度)分量,0 <= L <= 1。
HSL 的颜色模型如图所示:
色相 H 是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等。红色在 0 度,绿色在 120 度,蓝色在 240 度,以此方向过渡。
饱和度 S 是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取 0-100% 的数值。
亮度 L 等于 0 时为黑色,等于 0.5 时是色彩最鲜明的状态,等于 1 时为白色。
3.3 - HSVtoRGB
该函数用于转换 HSV 颜色为 RGB 颜色。
COLORREF HSVtoRGB(float H, float S, float V);
参数:
- H:原 HSV 颜色模型的 Hue(色相)分量,0 <= H < 360。
- S:原 HSV 颜色模型的 Saturation(饱和度)分量,0 <= S <= 1。
- V:原 HSV 颜色模型的 Value(明度)分量,0 <= V <= 1。
HSV 颜色模型如图所示:
明度 V 等于 0 时为黑色,在最大明度 1 时,是色彩最鲜明的状态。
五、图形颜色及样式设置相关函数
5.1 - setbkcolor
这个函数用于设置当前设备绘图背景色。
void setbkcolor(COLORREF color);
参数:
- color:指定要设置的背景颜色。
在设置背景颜色之后,并不会改变现有背景色,而只是改变背景色的值,之后再执行绘图语句,例如 outtextxy,会使用新设置的背景色值。
如果需要修改全部背景色,可以在设置背景色后再执行 cleardevice() 函数。
示例:
#include <graphics.h> // 引入图形库头文件
#include <conio.h>
#define WIDTH 640
#define HEIGHT 480
int main()
{
// 初始化绘画窗口
initgraph(WIDTH, HEIGHT);
// 将背景色设置为蓝色
setbkcolor(BLUE);
// 用当前的背景色清空屏幕
cleardevice();
// 按任意键退出
_getch();
closegraph();
return 0;
}
5.2 - setbkmode
这个函数用于设置当前设备图案填充和文字输出时的背景模式。
void setbkmode(int mode);
参数:
-
mode:指定图案填充和文字输出时的背景模式。可以是以下值:
值 描述 OPAQUE 背景用当前背景色填充**(默认)** TRANSPARENT 背景是透明的
5.3 - setfillcolor
这个函数用于设置当前设备填充颜色。
void setfillcolor(COLORREF color);
参数:
- color:填充颜色。
5.4 - setlinecolor
这个函数用于设置当前设备画线颜色。
void setlinecolor(COLORREF color);
参数:
- color:将要设置的画线颜色。
5.5 - setlinestyle
这个函数用于设置当前设备画线样式。
void setlinestyle(
int style,
int thickness = 1,
const DWORD *puserstyle = NULL,
DWORD userstylecount = 0
);
参数:
-
style:指定画线样式,该样式由直线样式、端点样式、连接样式三类组成。可以是其中一类或多类的组合。同一类型中只能指定一个样式。
直线样式可以是以下值:
值 含义 PS_SOLID 线形为实线 PS_DASH 线形为:------------ PS_DOT 线形为:············ PS_DASHDOT 线形为:-·-·-·-·-·-· PS_DASHDOTDOT 线形为:-··-··-··-·· PS_NULL 线形不可见 PS_USERSTYLE 线形样式为用户自定义,由参数 puserstyle 和 userstylecount 指定 宏 PS_STYLE_MASK 是直线样式的掩码,可以通过该宏从画线样式中分离出直线样式。
端点样式可以是以下值:
值 含义 PS_ENDCAP_ROUND 端点为圆形 PS_ENDCAP_SQUARE 端点为方形 PS_ENDCAP_FLAT 端点为平坦 宏 PS_ENDCAP_MASK 是端点样式的掩码,可以通过该宏从画线样式中分离出端点样式。
连接样式可以是以下值:
值 含义 PS_JOIN_BEVEL 连接处为斜面 PS_JOIN_MITER 连接处为斜接 PS_JOIN_ROUND 连接处为圆弧 宏 PS_JOIN_MASK 是连接样式的掩码,可以通过该宏从画线样式中分离处连接样式。
-
thickness:线的宽度,以像素为单位。
-
puserstyle:用户自定义样式数组,仅当线型为 PS_USERSTYLE 时该参数有效。数组第一个元素指定画线长度,第二元素指定空白的长度,第三个元素指定画线的长度,第四个元素指定空白的长度,以此类推。
-
userstylecount:用户自定义样式数组的元素数量。
六、图形绘制相关函数
6.1 - 绘图函数的分类
绘图函数从填充样式分类,可分为:无填充、有边框填充以及无边框填充。
绘图函数从形状来分类,常用的可分为以下八种:
- circle - 画圆
- ellipse - 画椭圆
- pie - 画扇形
- polygon - 画多边形
- rectangle - 画矩形
- roundrect - 画圆角矩形
- line - 画线
- putpixel - 画点
6.2 - 圆
-
该函数使用当前画线样式绘制无填充的圆。
void circle(int x, int y, int radius);
参数:
- x:圆心 x 坐标。
- y:圆心 y 坐标。
- radius:圆的半径。
-
该函数使用当前线形和当前填充样式绘制有边框的填充圆。
void fillcircle(int x, int y, int radius);
参数:
- x:圆心 x 坐标。
- y:圆心 y 坐标。
- radius:圆的半径。
-
该函数使用当前填充样式绘制无边框的填充圆。
void solidcircle(int x, int y, int radius);
参数:
- x:圆心 x 坐标。
- y:圆心 y 坐标。
- radius:圆的半径。
6.3 - 示例
#include <graphics.h> // 引入图形库头文件
#include <conio.h>
#define WIDTH 640
#define HEIGHT 480
int main()
{
// 初始化绘画窗口
initgraph(WIDTH, HEIGHT);
// 将背景色设置为黄色
setbkcolor(HSLtoRGB(60, 1, 0.5));
// 用当前的背景色清空屏幕
cleardevice();
// 将画线颜色设置为红色
setlinecolor(RGB(255, 0, 0));
// 将画线样式设置为实线,线的宽度为 3 像素
setlinestyle(PS_SOLID, 3);
// 将填充颜色设置为绿色
setfillcolor(0x00ff00);
// 使用当前画线样式绘制无填充圆
circle(50, 50, 50);
// 使用当前线形和当前填充样式绘制有边框的填充圆
fillcircle(50, 150, 50);
// 使用当前填充样式绘制无边框的填充圆
solidcircle(50, 250, 50);
// 按任意键退出
_getch();
closegraph();
return 0;
}
七、文字输出相关函数
7.1 - outtextxy
这个函数用于在指定位置输出字符串。
void outtextxy(int x, int y, LPCTSTR str);
这个函数用于在指定位置输出字符。
void outtextxy(int x, int y, TCHAR c);
参数:
- x:字符串输出时头字母的 x 轴的坐标值。
- y:字符串输出时头字母的 y 轴的坐标值。
- str:待输出的字符串的指针。
- c:待输出的字符。
字符串常见的编码有两种:MBCS(Multi-Bytes Character Set,即多字节字符集)和 Unicode(统一码、万国码、单一码)。
LPCTSTR 可以同时适应两种编码。为了适应两种编码,请使用 TCHAR 字符串及相关函数。
默认情况下,输出字符串的背景会用当前背景色填充。使用函数 setbkmode 可以设置文字的背景部分保存透明或使用背景色填充。
7.2 - settextcolor
这个函数用于设置当前文字颜色。
void settextcolor(COLORREF color);
参数:
- color:要设置的文字颜色。
7.3 - settextstyle
这个函数用于设置当前字体样式。
void settextstyle(
int nHeight,
int nWidth,
LPCTSTR lpszFace
);
参数:
- nHeight:指定高度(逻辑单位)。
- nWidth:字符的平均宽度(逻辑单位)。如果为 0,则比例自适应。
- lpszFace:字体名称。
八、示例程序
8.1 - 彩虹
该程序是 HSL 色彩模型的应用范例,程序通过调节 HSL 模型的亮度绘制渐变的天空,调节色相绘制七色彩虹。
#include <graphics.h>
#include <conio.h>
#define WIDTH 640
#define HEIGHT 480
int main()
{
initgraph(WIDTH, HEIGHT);
// 通过调节 HSL 模型的亮度(Lightness)绘制渐变的天空
float H = 190;
float S = 1;
float L = 0.7f;
float increase = (1.0 - L) / HEIGHT;
for (int y = 0; y < HEIGHT; y++) // 注意:x 坐标和 y 坐标从 0 开始
{
L += increase;
setlinecolor(HSLtoRGB(H, S, L));
line(0, y, WIDTH - 1, y);
}
// 调节色相(Hue)绘制七色彩虹
H = 0;
S = 1;
L = 0.5f;
setlinestyle(PS_SOLID, 2); // 将线宽设置为 2
for (int r = 400; r > 344; r--)
{
H += 6;
setlinecolor(HSLtoRGB(H, S, L));
circle(500, 480, r);
}
_getch();
closegraph();
return 0;
}
8.2 - 字符阵
该程序示范了常见的绘图操作,包括设置字体、画线等。
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#define WIDTH 640
#define HEIGHT 480
int main()
{
srand((unsigned int)time(NULL));
initgraph(WIDTH, HEIGHT);
settextstyle(16, 8, _T("Courier")); // 将文字的高度和宽度分别设置为 16 和 8,字体为 Courier
settextcolor(GREEN); // 将文字颜色设置为绿色
setbkmode(TRANSPARENT); // 文字输出时的背景模式为 TRANSPARENT
setlinecolor(BLACK); // 将画线颜色设置为黑色
int x, y;
char c;
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < 3; j++) // 在随机位置显示三个随机字母
{
x = rand() % (WIDTH - 7); // x:0 ~ WIDTH - 8
y = rand() % (HEIGHT - 15); // y:0 ~ HEIGHT - 16
c = rand() % 26 + 65; // c:65 ~ 90,即 'A' ~ 'Z'
outtextxy(x, y, c);
}
line(0, i, WIDTH - 1, i); // 画线擦掉一个像素行
Sleep(10); // 延时 0.01 秒
if (i >= HEIGHT - 1) // 当到最后一行时,置 i 为 -1
i = -1;
if (_kbhit()) // 按任意键退出
break;
}
closegraph();
return 0;
}