1.基本說明
EasyX 是針對 C++ 的圖形庫,可以幫助 C/C++ 初學者快速上手圖形和游戲編程。
比如,可以基于 EasyX 圖形庫很快的用幾何圖形畫一個房子,或者一輛移動的小車,可以編寫俄羅斯方塊、貪吃蛇、黑白棋等小游戲,可以練習圖形學的各種算法,等等。
許多人學編程都是從 C 語言入門的,而現狀是:
- 有些學校以 Turbo C 為環境學習 C 語言,只是 Turbo C 實在太老了,復制粘貼都很不方便。
- 有些學校直接拿 VC 來講 C 語言,因為 VC 的編輯和調試環境都很優秀,并且 VC 有適合教學的免費版本。可惜在 VC 里面只能做一些文字性的練習題,想畫條直線或一個圓都很難,例如需要注冊窗口類、建消息循環等等,初學者會受嚴重打擊的。初學編程想要繪圖就得用 TC,很是無奈。
- 還有計算機圖形學,這門課程的重點是繪圖算法,而不是 Windows 編程。所以,許多老師不得不用 TC 教學,因為 Windows 繪圖太復雜了,會偏離教學的重點。新的圖形學的書有不少是用的 OpenGL,可是門檻依然很高。
于是就有了這個 EasyX 庫。如果您剛開始學 C 語言,或者您是一位教 C 語言的老師,再或者您在教計算機圖形學,那么這個庫一定會讓您興奮的。
2.系統支持
操作系統:Windows XP(sp3) 及以上操作系統。
編譯環境:Visual C++ 6.0,Visual Studio 2008 至 Visual Studio 2022 (x86 & x64)。
3.安裝——EasyX Graphics Library for C++
請下載最新版 EasyX 安裝程序,直接運行,并跟隨提示安裝即可。
安裝程序會自動檢測您已經安裝的 VC 版本,并根據您的選擇將對應的 .h 和 .lib 文件安裝至 VC 的 include 和 lib 文件夾內。安裝程序不會修改注冊表或者您本機的其它任何文件。
4.如何學習easyx?
其實學習easyx的最好的方法就是看它的文檔——EasyX 文檔 - 基本說明?
5.第一個程序
首先我們要知道easyx是使用C++語言的,所以我們創建的源文件應該是.cpp后綴的
同樣我們使用的不是<stdio.h>的頭文件了,我們使用的是<easyx.h>的文件,就像下面這樣子
6.easyx快速入門之路(有點漫長,請耐心走完哦)
6.1.initgraph函數
這個函數用于初始化繪圖窗口。
?
6.2.closegraph函數?
創建了窗體,我們肯定要關閉窗體
這個函數用于關閉繪圖窗口。
我們直接上例子
#include<easyx.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體closegraph();return 0;
}
運行一下,我們發現窗體一閃而過,這是因為創建繪圖窗體之后又立馬關閉了,那怎么辦呢?
我們可以使用getchar()暫時阻塞程序,等待用戶按鍵后再關閉
getchar在<stdio.h>里面
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體getchar();closegraph();return 0;
}
?
?我們可以看到一個黑色的繪圖窗體,按回車鍵就關閉了窗體
6.3circle函數
該函數使用當前畫線樣式繪制無填充的圓。
我們看個例子?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體circle(0, 0, 300);getchar();closegraph();return 0;
}
我丟,這個圓心怎么在窗體的最左上方?這是因為easyx的坐標系統的原因
6.4easyx的坐標系統
我們先看看官網怎么說
?再看看圖
?我們之前畫的圓形的圓心是(0,0),是邏輯坐標的默認值,所以圓心自然在左上方了
邏輯坐標的原點是可以移動的,我們可以修改邏輯坐標的原點移動到窗體的中間
6.5setorigin函數
我們舉個例子
學會了這個,我們再去修改那個繪制圓的函數
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點circle(0, 0, 300);getchar();closegraph();return 0;
}
?我們看到啊,終于圓心位于正中央了!!
6.7setaspectratio函數
我們雖然把邏輯坐標的圓心改到了最中間的位置,但是y軸的方向和我們熟悉的軸線完全不一樣。因此我們有必要去修改一下y軸的方向
?我們再完善一下上面那個代碼
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向circle(0, 0, 300);getchar();closegraph();return 0;
}
?6.8putpixel函數
這個函數用于畫點。
我們先了解下面這些顏色,更多的顏色表示我們不急?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向putpixel(0, 0, RED);putpixel(200, 200, YELLOW);putpixel(200, -200, CYAN);putpixel(-200, -200, GREEN);putpixel(-200, 200, WHITE);getchar();closegraph();return 0;
}
WHAT?點呢?不要慌張,因為一個點是一個像素大小,我們很難看見它們?
我們讓效果更明顯一點,我們隨機生成100個點,x,y的坐標取值范圍如下
?我們讓效果更明顯一點,我們隨機生成100個點
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向int x, y;for (int i = 0; i < 1000; ++i){x = rand() % (800 + 1) - 400;y = rand() % (600 + 1) - 300;putpixel(x, y, WHITE);}getchar();closegraph();return 0;
}
這個效果就非常明顯了哈!?
6.9line函數
這個函數用于畫直線。
舉個例子?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向line(-200, 200, 200, -200);line(-200, -200, 200, 200);getchar();closegraph();return 0;
}
?6.10畫多個圓
我們學會了用circle來畫圓形,那我們加大一點難度
代碼:?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向for (int r = 10; r <= 300; r += 10){circle(0, 0, r);}getchar();closegraph();return 0;
}
?6.11rectangle函數
這個函數用于畫無填充的矩形。
示例?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向rectangle(-200, 100, 200, -100);getchar();closegraph();return 0;
}
?看效果
?6.12ellipse函數
這個函數用于畫無填充的橢圓。
舉例:?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向ellipse(-200, 100, 200, -100);getchar();closegraph();return 0;
}
6.12roundrect函數?
這個函數用于畫無填充的圓角矩形。
圓角矩形的樣子如下?
?
我們舉例
代碼
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向roundrect(-200, 100, 200, -100,200,100);getchar();closegraph();return 0;
}
6.13pie函數
?繪制扇形
?注意是順時針旋轉單位為弧度
舉例
代碼
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向pie(-200, 100, 200, -100,0,PI/4);getchar();closegraph();return 0;
}
6.14arc函數?
繪制圓弧
舉例
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向arc(-200, 100, 200, -100,0,PI/4);getchar();closegraph();return 0;
}
?7.繪制多邊形
基本的函數我們掌握了,我們就玩點進階的吧!
7.1繪制三角形
我們舉個例子
代碼
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向line(0, 200, 200, -200);line(200, -200, -200, -200);line(-200, -200, 0, 200);getchar();closegraph();return 0;
}
7.2polygon函數?
如果我們繪制多邊形都要像上面那樣子,就會很復雜,不過好在easyx有一個函數來幫我們繪制多邊形,那就是polygon函數
我們看看這個POINT是個什么東西?
?舉例
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向// 方法 1POINT pts[] = { {50, 200}, {200, 200}, {200, 50} };polygon(pts, 3);// 方法 2int pts2[] = { 0, 0, 100, 200, 200, 50 };polygon((POINT*)pts2, 3);getchar();closegraph();return 0;
}
?
7.3繪制矩形
?我們可以使用polygon函數來繪制矩形
假如我們要繪制下面這樣一個圖像
代碼?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向// 方法 1POINT pts[] = { {-200,100}, {200, 100}, {200, -100},{-200,-100 } };polygon(pts, 4);getchar();closegraph();return 0;
}
7.4繪制梯形?
代碼:
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向// 方法 1POINT pts[] = { {-100,100}, {100, 100}, {200, -100},{-200,-100 } };polygon(pts, 4);getchar();closegraph();return 0;
}
?7.5繪制五邊形
繪制五邊形比前面繪制四邊形多了一個棘手的問題,就是我們很難確定五個點的坐標?
那我們可以使用三角函數來得到坐標
我們看看P1和P2是怎么求的
這個時候,敏銳的同學就會發現 我們可以通過一個循環來得到五個點的坐標,起始角度是90度,每次循環增加360/5=72度,就可以得到五個點的坐標
注意:sin和cos用的是弧度制,所以代碼要用弧度制來
?代碼:
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
#include<math.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向double theta = PI / 2;//起始角度double delta = 2 * PI / 5;//每次循環增加的角度int r = 200;POINT points[5];for (int i = 0; i < 5; ++i){points[i].x = cos(theta + i * delta) * r;points[i].y = sin(theta + i * delta) * r;}polygon(points, 5);getchar();closegraph();return 0;
}
7.6繪制不規則的圖形?
我們可以使用polygon函數來繪制不規則圖形
?例如我們可以繪制像下面這樣一個多邊形
代碼
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
#include<math.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向POINT points[8] = { {-400,0},{-200,200},{0,50},{200,200},{400,0},{200,150},{0,0},{-200,150} };polygon(points, 8);getchar();closegraph();return 0;
}
呢我們能不能畫一個W呢?
答案是polygon函數不能,因為polygon函數會按順序依次連接各個點最后會繪制一條P1到P5的線
7.7polyline函數
既然我們不能使用polygon來描繪出不封閉的圖形W,我們可以使用polyline函數來繪制,這個函數和polygon的唯一區別就是它不會自動連接首尾兩個點,
我們接著畫上面那個W圖形
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);//翻轉y軸的方向POINT points[5] = { {-400,200},{-200,-200},{0,100},{200,-200},{400,200} };polyline(points, 5);getchar();closegraph();return 0;
}
8.形狀的樣式?
前面我們學習了一系列圖形的函數,但是我們發現,它們都是白色的單一線條,那我們如何讓這些圖形豐富起來呢?
8.1僅描邊圖形樣式
我們先復習一下畫圓的代碼
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點circle(0, 0, 300);getchar();closegraph();return 0;
}
我們可以發現它是僅由一條白線組成,而且圓的內部沒有填充任何顏色
我們將圖形邊緣的線條稱為圖形的描邊,描邊的顏色默認為白色,包括我們之前學習的所有繪制圖形的函數,都是如此。
8.2setlinecolor函數?
我們不想讓描邊的顏色是白色,我們可以使用setlinecolor函數來設置描邊的顏色
我們來使用一下
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setlinecolor(RED);circle(0, 0, 300);getchar();closegraph();return 0;
}
?很好,描邊變紅色了。
8.3setlinestyle函數
我們覺得感覺樣式也太單調了,那我們可以使用setlinestyle函數來改變描邊的樣式
這個函數用于設置當前設備畫線樣式
我們現在先重點關注前兩個參數
先看第一個參數 ,參數 style 指定了畫線樣式,該樣式由直線樣式、端點樣式、連接樣式三類組成。可以是其中一類或多類的組合。同一類型中只能指定一個樣式。
8.3.1線形樣式
?掩碼宏表示對應樣式組所占用的所有位。例如,對于一個已經混合了多種樣式的 style 變量,如果希望僅將直線樣式修改為點劃線,可以這么做:
style = (style & ~PS_STYLE_MASK) | PS_DASHDOT;
我們舉個例子
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setlinestyle(PS_SOLID);circle(0, 0, 50);setlinestyle(PS_DASH);circle(0, 0, 100);setlinestyle(PS_DOT);circle(0, 0, 150);setlinestyle(PS_DASHDOT);circle(0, 0, 200);setlinestyle(PS_DASHDOTDOT);circle(0, 0, 250);setlinestyle(PS_NULL);circle(0, 0, 300);getchar();closegraph();return 0;
}
我丟,這誰看得清楚啊
這個時候,我們就可以使用第二個參數來設置線條的粗細
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setlinestyle(PS_SOLID,4);circle(0, 0, 50);setlinestyle(PS_DASH,4);circle(0, 0, 100);setlinestyle(PS_DOT,4);circle(0, 0, 150);setlinestyle(PS_DASHDOT,4);circle(0, 0, 200);setlinestyle(PS_DASHDOTDOT,4);circle(0, 0, 250);setlinestyle(PS_NULL,4);circle(0, 0, 300);getchar();closegraph();return 0;
}
?怎么樣?夠清晰了吧!
8.3.2端點樣式
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);setlinestyle(PS_ENDCAP_ROUND, 16);line(-300, 200, 300, 200);setlinestyle(PS_ENDCAP_SQUARE, 16);line(-300, 150, 300, 150);setlinestyle(PS_ENDCAP_SQUARE, 16);line(-300, 100, 300, 100);getchar();closegraph();return 0;
}
?8.3.3連接樣式
?代碼
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);setlinestyle(PS_JOIN_BEVEL,64);POINT point1[3] = { {-150,100},{0,200},{150,100} };polyline(point1, 3);setlinestyle(PS_JOIN_MITER,64);POINT point2[3] = { {-150,0},{0,100},{150,0} };polyline(point2, 3);setlinestyle(PS_JOIN_ROUND,64);POINT point3[3] = { {-150,-100},{0,0},{150,-100} };polyline(point3, 3);getchar();closegraph();return 0;
}
?8.4.僅填充圖形樣式
在之前學習的封閉圖形的時候,我們發現里面都是空的,那么我們可以來進行填充
這些函數和使用描邊繪制圖形函數基本一模一樣,唯一的區別就是在函數名前加solid
例如我們要繪制有填充的圖形樣式,就要使用solidcircle函數
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);solidcircle(0, 0, 100);getchar();closegraph();return 0;
}
我們發現這個默認填充顏色是白色,那我們如何修改這個填充顏色呢?
8.4.1setfillcolor函數?
這個函數是來設置填充顏色的
我們可以對上面的代碼進行改進
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);setfillcolor(YELLOW);solidcircle(0, 0, 100);getchar();closegraph();return 0;
}
8.5描邊加填充圖形樣式?
前面我們學習了僅描邊或者僅填充的樣式,那如果我既想讓它有描邊樣式,又有填充樣式,我們該怎么辦呢?
很簡單,僅在函數名前加fill
代碼?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);setlinecolor(RED);setlinestyle(PS_DASH, 12);setfillcolor(YELLOW);fillcircle(0, 0, 200);getchar();closegraph();return 0;
}
?8.6設置背景色——setbkcolor
例如,我們想把我們的背景設置為白色
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);setbkcolor(WHITE);getchar();closegraph();return 0;
}
什么,怎么還是黑色的?
我們看看文檔
我靠,原來如此
我們改進一下
8.7cleardevice函數
使用這個函數,代表之前繪制的一切東西都會被清空?
有了這個我們就能對上面的進行改進了
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);setbkcolor(WHITE);cleardevice();getchar();closegraph();return 0;
}
我靠,成功了!!?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);setbkcolor(WHITE);cleardevice();setfillcolor(BLUE);solidcircle(0, 0, 300);getchar();closegraph();return 0;
}
9.顏色模型?
在此之前,我們用的顏色都是easyx已經定義好的顏色
但是這些顏色還是具有很多局限性的,無法表示更多豐富多彩的顏色樣式
9.1RGB顏色模型
不知道大家有沒有近距離的觀察過屏幕,我們就會發現屏幕居然是由很多紅點,綠點,藍點組成的,其他顏色均是由這三種顏色混合而成的。其實啊,這個是因為顯示器使用了人眼的三原色原理
我們將每種原色從弱到強分為256等分?
這個時候我們將不同比例的原色進行混合,就可以形成各種各樣的顏色
此外,顏色值也可以使用三原色份數的十六進制數進行組合表示
?那么,我們在代碼中怎么使用RGB顏色模型呢?
在easyx中,提供了一個名為RGB的函數
有人就好奇了,這個BYTE是個啥?我們看
又有人好奇了這個COLORREF是個啥?
很好!!接下來我們就來使用這個函數
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setbkcolor(RGB(134, 172, 242));cleardevice();getchar();closegraph();return 0;
}
成功啦!!哈哈?
9.2.HSV顏色模型
我們看下面這個
我們把三原色放在圓形的三等分點處,然后按與三原色的距離來分配不同顏色的比例,就能得到像下面這樣一個色環
我們發現,每一個角度都代表一種顏色,這個就叫色相,此外,HSV顏色模型還提供了兩個參數,用于控制顏色的鮮艷程度和明暗程度,它們分別為飽和度和明度。
例如,我們選取色相為240度,就是藍色,選取不同飽和度,明度,我們得到的顏色也不同
?飽和度下降,越靠近白色,明度下降,越靠近黑色,明度有時候也叫亮度,所以HSV和HSB是一個東西
但是顯示屏是使用三原色原理制作的,HSV模型無法使用于顯示屏
但是我們可以使用HSV模式選好顏色,再將其轉換為RGB模式,就可以顯示在屏幕上
9.2.1.HSVtoRGB函數
該函數將HSV顏色轉換為RGB顏色
我們可以使用在線拾色器選取一個顏色,然后將其轉換為RGB顏色
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setbkcolor(HSVtoRGB(219,0.45,0.95));cleardevice();getchar();closegraph();return 0;
}
9.3.繪制彩虹窗體?
我們怎么做才能得到彩虹色的背景呢?
其實很簡單,我們只需要環繞色環轉一圈即可
也就是色相從0開始到360度逐漸遞增變化,明度飽和度選100%就可以了
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體float dH = 360.0 / 600.0;float h = 0;for (int y = 0; y < 600; ++y){setlinecolor(HSVtoRGB(h, 1, 1));line(0, y, 800, y);h += dH;}getchar();closegraph();return 0;
}
9.4.繪制藍天,彩虹?
我們想畫下面這樣子的圖
那我們要怎么做呢?
我們線畫漸變色的藍天吧!很簡單,把圖拆分為600條線(因為寬是600像素)
?看代碼
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體float s = 0.76;float ds = s/600;for (int y = 0; y < 600; ++y){setlinecolor(HSVtoRGB(216, s, 0.95));line(0, y, 800, y);s -= ds;}getchar();closegraph();return 0;
}
我丟,這么美?,得抓緊畫彩虹了,彩虹很簡單
我們看代碼?
#include<easyx.h>
#include<stdio.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體float s = 0.76;float ds = s/600;for (int y = 0; y < 600; ++y){setlinecolor(HSVtoRGB(216, s, 0.95));line(0, y, 800, y);s -= ds;}float h = 0;float dh = 360.0 / 100.0;for (int r = 300; r >= 200; --r){setlinecolor(HSVtoRGB(h, 1, 1));circle(400, 600, r);h += dh;}getchar();closegraph();return 0;
}
10.剪切區域?
我們希望能用圓形畫出像下面這樣一朵花
很明顯,這是許多個等半徑的圓形組成的,圓心都位于內部圓形的六等分處,我們就可以使用三角函數來得到圓心的坐標
我們直接上代碼?
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
#include<math.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);//設置邏輯坐標的原點setaspectratio(1, -1);setbkcolor(WHITE);cleardevice();setlinecolor(BLACK);setlinestyle(PS_SOLID, 10);int r = 150;circle(0, 0, r);for (int i = 0; i < 6; ++i){int x = cos(i * (2 * PI / 6)) * r;int y=sin(i * (2 * PI / 6)) * r;circle(x,y,r);}getchar();closegraph();return 0;
}
這不就是小case嗎!!!哈哈哈
現在我們有新需求,我們只要中間這個圓形,其他的不要
那我們怎么做呢?
這就需要學習新知識了——剪切區域
10.1剪切區域
我們在繪制前設置剪切區域,繪制在剪切區域的圖形將被保留,繪制在剪切區域的圖形將被拋棄
注意:必須先建立剪切區域,再調用繪圖函數
回到上面那個問題,我們可以先建立一個剪切區域
這樣子白色部分的將被保留,其他的將被刪除
10.2.創建區域
我們怎么創建剪切區域呢?
easyx并沒有直接提供創建區域的函數,因此我們需要借助Windows GDI
我們一個一個來好好看看
?
我們發現,這些函數和它們對應的圖形繪制函數的參數形式一模一樣 ,實際上,它們分別和對應的繪制函數的用法也是一模一樣的
注意:剪切區域是以物理坐標為坐標系的
由于沒有直接繪制圓形的函數,我們可以使用繪制橢圓的
10.3設置剪切區域——setcliprgn函數
小兄弟,光創建了區域還不行,我們還得把它設置成剪切區域才行!!!
而setcliprgn剛好是用來干這個活的
很好,萬事具備,只欠東風,我們開寫
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
#include<math.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);setaspectratio(1, -1);setbkcolor(WHITE);cleardevice();setlinecolor(BLACK);setlinestyle(PS_SOLID, 10);int r = 150;HRGN rgn = CreateEllipticRgn(250, 150, 550, 450);//創建區域setcliprgn(rgn);//將創建的區域設置為剪切區域circle(0, 0, r);for (int i = 0; i < 6; ++i){int x = cos(i * (2 * PI / 6)) * r;int y=sin(i * (2 * PI / 6)) * r;circle(x,y,r);}setcliprgn(NULL);//將剪切區域設為空DeleteObject(rgn);//銷毀區域getchar();closegraph();return 0;
}
注意繪圖完成后,要將剪切區域設為空,并且要刪除創建的區域
我靠,就這?太簡單了吧!!別急,更厲害的還在后面,加油吧,少年
10.4.CombineRgn函數
區域之間可以進行集合運算并組合 ,我們可以使用CombineRgn函數來組合區域,這個函數也不是easyx自帶的,所以用的也是物理坐標
這個函數是讓源區域1和源區域2按照某種組合模式(第四個參數)進行組合得到新的剪切區域
組合模式如下
第一個參數是沒有什么太大的意義的,但是它必須是一個存在的區域,它是用來承接組合后的區域的
接下來我們就舉幾個例子來看看怎么使用組合區域
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
#include<math.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);setaspectratio(1, -1);setbkcolor(WHITE);cleardevice();setlinecolor(BLACK);setlinestyle(PS_SOLID, 10);int r = 150;HRGN rgn1 = CreateEllipticRgn(250, 250, 550, 550);//創建區域HRGN rgn2 = CreateEllipticRgn(250, 100, 550, 400);//創建區域HRGN rgn = CreateEllipticRgn(0,0,0,0);//創建區域CombineRgn(rgn, rgn1, rgn2, RGN_AND);setcliprgn(rgn);circle(0, 0, r);for (int i = 0; i < 6; ++i){int x = cos(i * (2 * PI / 6)) * r;int y=sin(i * (2 * PI / 6)) * r;circle(x,y,r);}setcliprgn(NULL);//將剪切區域設為空DeleteObject(rgn);//銷毀區域DeleteObject(rgn1);//銷毀區域DeleteObject(rgn2);//銷毀區域getchar();closegraph();return 0;
}
?
我們接下來看并集的
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
#include<math.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);setaspectratio(1, -1);setbkcolor(WHITE);cleardevice();setlinecolor(BLACK);setlinestyle(PS_SOLID, 10);int r = 150;HRGN rgn1 = CreateEllipticRgn(250, 250, 550, 550);//創建區域HRGN rgn2 = CreateEllipticRgn(250, 100, 550, 400);//創建區域HRGN rgn = CreateEllipticRgn(0,0,0,0);//創建區域CombineRgn(rgn, rgn1, rgn2, RGN_OR);setcliprgn(rgn);circle(0, 0, r);for (int i = 0; i < 6; ++i){int x = cos(i * (2 * PI / 6)) * r;int y=sin(i * (2 * PI / 6)) * r;circle(x,y,r);}setcliprgn(NULL);//將剪切區域設為空DeleteObject(rgn);//銷毀區域DeleteObject(rgn1);//銷毀區域DeleteObject(rgn2);//銷毀區域getchar();closegraph();return 0;
}
?
我們看看并集排除重疊區域
#define PI 3.14
#include<easyx.h>
#include<stdio.h>
#include<math.h>
int main()
{initgraph(800, 600);//創建了800*600像素的窗體setorigin(400, 300);setaspectratio(1, -1);setbkcolor(WHITE);cleardevice();setlinecolor(BLACK);setlinestyle(PS_SOLID, 10);int r = 150;HRGN rgn1 = CreateEllipticRgn(250, 250, 550, 550);//創建區域HRGN rgn2 = CreateEllipticRgn(250, 100, 550, 400);//創建區域HRGN rgn = CreateEllipticRgn(0,0,0,0);//創建區域CombineRgn(rgn, rgn1, rgn2, RGN_XOR);setcliprgn(rgn);circle(0, 0, r);for (int i = 0; i < 6; ++i){int x = cos(i * (2 * PI / 6)) * r;int y=sin(i * (2 * PI / 6)) * r;circle(x,y,r);}setcliprgn(NULL);//將剪切區域設為空DeleteObject(rgn);//銷毀區域DeleteObject(rgn1);//銷毀區域DeleteObject(rgn2);//銷毀區域getchar();closegraph();return 0;
}