EasyX 是针对 C++ 的图形库,可以帮助 C/C++ 初学者快速上手图形和游戏编程。
比如可以基于 EasyX 图形库很快地用几何图形画一个房子,或者一辆移动的小车,可以编写俄罗斯方块、贪吃蛇、黑白棋等小游戏,可以练习图形学的各种算法,等等。
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 位真彩色可以达到人眼分辨的极限。
表示颜色的方法:
在 EasyX 中,坐标分两种:物理坐标和逻辑坐标。
物理坐标:
物理坐标是描述设备的坐标体系。
坐标原点在设备的左上角,X 轴向右为正,Y 轴向下为正,度量单位是像素。
坐标原点、坐标轴方向、缩放比例都不能改变。
逻辑坐标:
逻辑坐标是在程序中用于绘图的坐标体系。
坐标默认的原点在窗口的左上角,X 轴向右为正,Y 轴向下为正,度量单位是点。
默认情况下,逻辑坐标与物理坐标是一一对应的,一个逻辑点等于一个物理像素。
在本手册中,凡是没有注明的坐标,均指逻辑坐标。
"设备",是指绘图表面。
在 EasyX 中,设备分为两种,一种是默认的绘图窗口,另一种是 IMAGE 对象。通过 SetWorkingImage 函数可以设置当前用于绘图的设备。
设置当前用于绘图的设备后,所有的绘图函数都会绘制在该设备上。
这个函数用于初始化绘图窗口。
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) |
返回值:
示例:
// 创建一个尺寸为 640 x 480 的绘图窗口
initgraph(640, 480);
// 创建一个尺寸为 640 x 480 的绘图窗口,同时显示控制台窗口
initgraph(640, 480, EW_SHOWCONSOLE);
// 创建一个尺寸为 640 x 480 的绘图窗口,同时显示控制台窗口,并禁用关闭按钮
initgraph(640, 480, EW_SHOWCONSOLE | EW_NOCLOSE);
这个函数用于关闭绘图窗口。
void closegraph();
这个函数使用当前背景色清空绘图设备。
void cleardevice();
RGB 宏用于将红、绿、蓝颜色分量合成颜色。
COLORREF RGB(BYTE byRed, BYTE byGreen, BYTE byBlue);
参数:
返回值:
该函数用于转换 HSL 颜色为 RGB 颜色。
COLORREF HSLtoRGB(float H, float S, float L);
参数:
色相 H 是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等。红色在 0 度,绿色在 120 度,蓝色在 240 度,以此方向过渡。
饱和度 S 是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取 0-100% 的数值。
亮度 L 等于 0 时为黑色,等于 0.5 时是色彩最鲜明的状态,等于 1 时为白色。
该函数用于转换 HSV 颜色为 RGB 颜色。
COLORREF HSVtoRGB(float H, float S, float V);
参数:
明度 V 等于 0 时为黑色,在最大明度 1 时,是色彩最鲜明的状态。
这个函数用于设置当前设备绘图背景色。
void setbkcolor(COLORREF color);
参数:
在设置背景颜色之后,并不会改变现有背景色,而只是改变背景色的值,之后再执行绘图语句,例如 outtextxy,会使用新设置的背景色值。
如果需要修改全部背景色,可以在设置背景色后再执行 cleardevice() 函数。
示例:
#include // 引入图形库头文件
#include
#define WIDTH 640
#define HEIGHT 480
int main()
{
// 初始化绘画窗口
initgraph(WIDTH, HEIGHT);
// 将背景色设置为蓝色
setbkcolor(BLUE);
// 用当前的背景色清空屏幕
cleardevice();
// 按任意键退出
_getch();
closegraph();
return 0;
}
这个函数用于设置当前设备图案填充和文字输出时的背景模式。
void setbkmode(int mode);
参数:
mode:指定图案填充和文字输出时的背景模式。可以是以下值:
值 | 描述 |
---|---|
OPAQUE | 背景用当前背景色填充**(默认)** |
TRANSPARENT | 背景是透明的 |
这个函数用于设置当前设备填充颜色。
void setfillcolor(COLORREF color);
参数:
这个函数用于设置当前设备画线颜色。
void setlinecolor(COLORREF color);
参数:
这个函数用于设置当前设备画线样式。
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:用户自定义样式数组的元素数量。
绘图函数从填充样式分类,可分为:无填充、有边框填充以及无边框填充。
绘图函数从形状来分类,常用的可分为以下八种:
该函数使用当前画线样式绘制无填充的圆。
void circle(int x, int y, int radius);
参数:
该函数使用当前线形和当前填充样式绘制有边框的填充圆。
void fillcircle(int x, int y, int radius);
参数:
该函数使用当前填充样式绘制无边框的填充圆。
void solidcircle(int x, int y, int radius);
参数:
#include // 引入图形库头文件
#include
#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;
}
这个函数用于在指定位置输出字符串。
void outtextxy(int x, int y, LPCTSTR str);
这个函数用于在指定位置输出字符。
void outtextxy(int x, int y, TCHAR c);
参数:
字符串常见的编码有两种:MBCS(Multi-Bytes Character Set,即多字节字符集)和 Unicode(统一码、万国码、单一码)。
LPCTSTR 可以同时适应两种编码。为了适应两种编码,请使用 TCHAR 字符串及相关函数。
默认情况下,输出字符串的背景会用当前背景色填充。使用函数 setbkmode 可以设置文字的背景部分保存透明或使用背景色填充。
这个函数用于设置当前文字颜色。
void settextcolor(COLORREF color);
参数:
这个函数用于设置当前字体样式。
void settextstyle(
int nHeight,
int nWidth,
LPCTSTR lpszFace
);
参数:
该程序是 HSL 色彩模型的应用范例,程序通过调节 HSL 模型的亮度绘制渐变的天空,调节色相绘制七色彩虹。
#include
#include
#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;
}
该程序示范了常见的绘图操作,包括设置字体、画线等。
#include
#include
#include
#include
#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;
}