0x00 前言
请希望速成者和大佬们关掉此文章,对于您们来说,这篇文章会耽误您们的时间,谢谢!
欢迎阅读 <OI志> code 星之旅,本篇讲述了:
- EGE图形库的配置
- 基本的绘图
- 绘制不同形式,不同颜色,不同字体的文字
- 导入图片
0x10 EGE图形库
0x11 引入
传说有个星球叫做 code 星球,上面的生物叫做 OIer,因为常年沉溺于 C++ 的小黑框之中,使他们失去了颜色感受能力。为此,代码研究院(Code Research Instiyute)的新晋院士 预测者(ycz),来到 code 星,使用神奇的工具(EGE)让 OIers 恢复颜色感受能力。
让我们看看 预测者 的 code 星之旅吧。
预测者小贴士:为了我们能少跑点路,我们接下来所有的操作都是通过代码实现的。
0x12 召唤神奇工具(配置图形库)
降落到 code 星球上,预测者受到了当地居民的热烈欢迎!预测者说明来意后,向飞船
RedPanda IDE
发出了请求,名为graphics.h
的运输船降落了下来。
预测者说,召唤神奇工具有四步:
-
向 RedPanda IDE 发出请求(打开 小熊猫DEV c++)。
-
按下
Ctrl
+n
,新建一个源代码。 -
按照常规格式添加头文件与主函数,链接到 code 星的总控系统上。
-
在头文件里添加
#include <graphics.h>
,召唤神奇工具的运输船。
最后添加上的代码就是:
#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;
int main() {
return 0;
}
现在,graphics.h
运输船上的工具你就可以任意使用了。
🏆 达成进度 神奇的召唤
0x13 打开一个图窗
运输船上的工具很神奇,可以通过代码的形式让他们自己运作,但是,我们必须得为工具的运作提供一个平台。——预测者
graphics.h
上的工具函数并不能直接在 code 星的总控系统驱动下工作,因此,我们就得为它申请一个可以运作的驱动空间。
预测者强调道:没错,再申请一个小空间!
你可能会说:这怎么可能,就算可以,也肯定很难吧。
但实际上,申请一个驱动空间很简单,我们只需要在 code 星的总控系统里添加一句代码:initgraph()
,就会发现终端显示编译错误!
那其实是因为我们并没有向总控系统说明我们需要多大的驱动空间,我们继续将initgraph()
代码的参数填充完。Ta实际上应该长这个样子:
initgraph(窗口宽度, 窗口高度);
所以我们它改成initgraph(480, 480);
,向 code 星总控系统申请一个 480×480 的空间,就可以啦!
你又一次按下了编译键,控制台显示编译成功!但你看到一个驱动空间 闪烁 了一下,然后总控系统返回0
。
你暴怒道:什预测者,骗我!
预测者说:诶,我知道你很急,但你先别急!
让我们分析一下为什么有个窗口闪烁了一下:
-
当总控系统检测到
initgraph()
生成了一个工具函数驱动。 -
继续检测,检测到
return 0
,外部代码停止,工具函数驱动被清除。
所以,如果想要 看到 驱动空间,我们就需要一个能够是 程序停住 的代码。作为 code 星常驻居民,这自然难不倒你,你很快列举了出来:
//普通的输入需要输入值并按下回车,不是很方便
int n;
cin >> n;
scanf("%d", &n);
//字符读取只需要随意按下一个键就可以继续了,很方便
getch();
getchar();
让我们加上代码,再让总控系统检测一次……这一次,我们可以看到,驱动空间很顺利的显示了出来。
预测者小贴士:这里的 return 并没有清除生成的驱动空间,只是将它隐藏了,如果不关掉终端或使用接下来讲的这个函数的话,就会占满总控系统内存。
看完了小贴士,我们就直接看向这个函数——closegraph()
,这一次,括号里面不需要任何参数,它的作用就是关掉所有打开的绘图框。我们将它添加到终端代码里,就可以在按下 任意键 后关闭驱动空间.
效果代码
#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;
int main() {
initgraph(480, 480);
getch();
closegraph();
return 0;
}
🏆 达成进度 初识图形库
0x14 学习一下绘图吧
现在万事齐备,只差教学 code 星的 OIers 使用工具,使自己恢复颜色感应能力了。——预测者
读完上面这一节,我们学会了为工具函数 申请驱动空间,以及 释放驱动空间。
预测者说:接下来,我们一起学习使用第一个工具——方框绘制。
绘制方框的工具函数很简单,工具原型是void EGEAPI bar(int left, int top, int right, int bottom, PIMAGE pimg = NULL);
。当然,预测者也知道你看不懂,用不来,所以配上了 中文:
bar(左上角x, 左上角y, 右下角x, 右下角y);
这一次,相信聪明的 code 星 OIers 应该看懂了。让我们把它输入终端里看看效果:
效果代码
#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;
int main() {
initgraph(480, 480);
bar(100, 100, 200, 200)
getch();
closegraph();
return 0;
}
全场所有 OIers 都惊呆了,他们并没有看到预测者所说的方框,难道他们真的一点颜色感应能力都没有了吗?
预测者说:别急,这个时候你还没有给方框设置颜色,驱动空间不知道你要什么色的方框,所以罢工了。
所以,废话不多说,预测者直接在终端里添加了这一行代码:
setfillcolor(RED);
效果代码
#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;
int main() {
initgraph(480, 480);
setfillcolor(RED);
bar(100, 100, 200, 200)
getch();
closegraph();
return 0;
}
“出现了,红色的方框!” 全场的 OIers 叫道。他们还能看到一点颜色!
好的,现在我们来讲讲这个函数:
-
首先,从字面意义上理解,
set
设置,fill
填充,color
颜色,连起来就是 “设置填充颜色”。 -
括号中的
RED
是可以替换的,可以替换成下面这些宏,下面这些就是 OIers 还能够直接看到的颜色:
颜色 | 宏 |
---|---|
红色 | RED |
橘色 | ORANGE |
黄色 | YELLOW |
绿色 | GREEN |
蓝色 | BLUE |
紫色 | PURPLE |
黑色 | BLACK |
白色 | WHITE |
棕色 | BROWN |
灰色 | GREY |
当然,对于只能看到区区10种颜色,OIers 自然是非常不满。于是预测者掏出了另一样工具——EGERGB()
,它可以帮助 OIers 们看到更多的颜色。当然,还是要配上简单的说明,让所有 OIers 都会使用它:
EGERGB(红色, 绿色, 蓝色) //三个数值的范围均为[0, 255]
方框画出来了,这不得让 OIers 都实践一下,但……只画一个框是不是并不能对 OIers 的视觉起到强有力的锻炼。于是,我们可以让这个方框动起来,这样效果绝对翻番。让方框动起来之前,先给大家讲一讲基本的让工具函数停止的工具,那就是bar()
!
全场 OIers 震怒道:你刚才还说这是绘制方框的函数,现在又能清屏了,你是不是耍我们!
预测者说:你看,如果我给整个驱动空间再绘制一层黑色,是不是就充当清屏了呢。
理论存在,实践开始!
#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;
int main() {
initgraph(480,480);
while (true) {
for (int i = 1; i <= 20; i++) {
setfillcolor(RED);
bar(10 * i, 10 * i, 10 * i + 10, 10 * i + 10);
Sleep(100);
setfillcolor(BLACK);
bar(0, 0, 480, 480);
Sleep(100);
}
}
getch();
closegraph();
return 0;
}
预测者小贴士:EGE图形库自带
windows.h
头文件。
如大家所愿的,红色小方框沿着对角线动了起来,全场 OIers 的视线都随着小方框移动着。
最后预测者掏出了5个工具函数,给 OIers 讲到:同理的,还有许多与bar()
相同的工具函数,就比如我手上这些。我给大家配好了中文说明,希望大家使用这些工具函数,早日恢复颜色感应能力!
circle(x坐标, y坐标, 半径); //空心圆
fillcircle(x坐标, y坐标, 半径); //实心圆
line(起始x, 起始y, 终止x, 终止y); //画线
ellipse(x坐标, y坐标, 横轴半径, 竖轴半径); //空心椭圆
fillellipse(x坐标, y坐标, 横轴半径, 竖轴半径); //实心椭圆
🏆 达成进度 工具获得者
0x15 背景也能变!
OIers 都学会了使用工具函数,但对于常年看到小黑框的他们,他们自然不愿意再看到驱动空间的背景也是黑色的。于是,他们要求预测者将驱动空间的背景改成 蓝色。
预测者说:背景颜色函数很简单,就是下面这个。
setbkcolor(颜色);
你惊奇的发现,这玩意与 言归正传,现在 OIers 可以任意改变驱动空间的颜色了。setfillcolor()
除了名字不一样其他啥都一样。
OIers 们向原先的代码里添加了setbkcolor(BLUE)
和setbkcolor(GREEN)
使驱动空间的颜色在 蓝色 和 绿色 中 来回切换。
效果代码
#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;
int main() {
initgraph(480,480);
for (int j = 1; true; j++) {
for (int i = 1; i <= 20; i++) {
setfillcolor(RED);
bar(10 * i, 10 * i, 10 * i + 10, 10 * i + 10);
Sleep(100);
if (i % 2 == 1) setfillcolor(BLUE);
else setfillcolor(GREEN);
bar(0, 0, 480, 480);
Sleep(100);
}
}
getch();
closegraph();
return 0;
}
🏆 达成进度 驱动空间变变变
0x16 来点文字吧
预测者:众所周知,在小黑框里输出文字需要用到printf()
,所以, 在绘图框里也要用 printf 输出。 在绘图框里绘制文字,就需要使用xyprintf()
:
xyprintf(x坐标, y坐标, "文字内容");
作为 OIers 举一反三应该还是会的,他们很快发现,xyprintf()
也可以像printf()
一样输出变量的值。
int sum = 100;
xyprintf(100, 100, "%d", sum);
这时,有些不满足于Consolas
字体的 OIers 发言了:预测者,你讲的这个工具函数能不能更改字体大小和颜色啊!
预测者回答道:别急,设置颜色和大小的工具函数正在我手上呢! 快看看中文说明 ,学习使用吧。
setcolor(颜色); //设置字体颜色
setfont(高度, 宽度, "字体"); //设置字体样式
预测者小贴士:这里的宽度可以为0,0表示根据高度自适应宽度,当然,高度不能为0。引号中的字体必须是这台电脑拥有的字体,常用的有:“黑体”, “宋体”, “仿宋”, "Consolas"等
乐于实践的 OIers 们马上做出了 进度条 的代码。
效果代码
#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;
const int SX = 20, SY = 200;
int main() {
initgraph(480, 480);
int x = SX;
setfillcolor(WHITE);
bar(SX, SY, 220, 240);
setfillcolor(BLACK);
bar(SX + 2, SY + 2, 218, 238);
for (int i = 1; i <= 100; i++) {
setfillcolor(WHITE);
bar(SX + 2, SY + 2, x, 238);
setfont(20, 0, "黑体");
xyprintf(100, 210, "%d%%", i);
Sleep(100);
x += 2;
}
getch();
closegraph();
return 0;
}
🏆 达成进度 文字才是基础
0x17 背景有点单一,挂一张图片!
经过前面的学习, OIers 已经掌握了恢复颜色感应能力的 基本办法 ,但实验数据表明,这样需要 足足 100 个 code 星日 才能恢复,这实在是太慢了,所以,预测者决定交给 OIers 最 迅速 恢复颜色感应能力的办法。
终于,我们讲到了整个神奇工具最核心的部分——图片的放置。
看到这里,OIers 想:就用基本工具函数恢复视力不就可以了吗?为什么要学习放图片工具法?
预测者说:这其实是因为下面两点
- 基本工具函数实际上是由点到线再道到面的使用过程,这个过程比较慢。
- 总控系统驱动图片工具基本是瞬间。
当然,也要注意,总控系统只是驱动图片工具是一瞬间,但链接图片工具依旧需要 1~3 ms 。所以,我们就需要一个数据结构,能够把读取到的图片存储下来。幸运的是,图形库工具为我们提供了这种数据结构——PIMAGE
。
它可以像常用的数据结构一样声明变量,比如说:
PIMAGE image, images[114514];
当然这仅仅只是声明,与int
不一样的地方在于,它的空间需要我们手动申请,比如说:
image = newimage();
接下来我们就可以读取图片了。
getimage(变量名, 路径);
预测者小贴士:这里的路径建议使用相对路径(也就是与程序处于同文件夹或下级文件夹的文件),这样程序文件夹的位置与程序无关紧要。
预测者说:比如说我要导入这样一张图片。
预测者输入了代码,编译成功:
效果代码
#include <bits/stdc++.h>
#include <graphics.h>
using namespace std;
PIMAGE image;
int main() {
initgraph(480, 480);
setbkcolor(WHITE);
image = newimage();
getimage(image, "png\\Tis.png"); //请根据自己的实际情况设置路径,注意使用2个"\"
putimage_withalpha(NULL, image, 200, 200);
getch();
closegraph();
return 0;
}
在上面的代码中,OIers 发现了预测者从未讲过的函数——putimage_withalpha()
。
聪明的 OIers 马上想到了:读取完了图片,总得放上驱动空间,让我们能看到吧。
他们马上总结出了putimage_withalpha()
的用法。
putimage_withalpha(NULL, 存储图片的变量名, 左上角x坐标, 左上角y坐标, 0, 0, 0, 0, 高度, 宽度);
🏆 达成进度 工具核心
持续更新
有问题请评论区告诉我!