張煜昕
摘要:EasyX 是C++語(yǔ)言進(jìn)行圖形化編程和游戲編程的一種圖形庫(kù),可以用幾何圖形構(gòu)造各種造型及動(dòng)畫(huà),也可以加載圖像文件增強(qiáng)其質(zhì)感。多線程是并發(fā)執(zhí)行的技術(shù),在同一時(shí)間完成多項(xiàng)任務(wù),實(shí)現(xiàn)能夠在同一時(shí)間并行執(zhí)行多個(gè)方法,進(jìn)而提升整體處理性能。通過(guò)繪制鐘表指針動(dòng)畫(huà)、背景音樂(lè)、圖形顏色變換以及文字閃爍等需求,采用EasyX圖形庫(kù)和多線程技術(shù)來(lái)完成,其運(yùn)行穩(wěn)定,效果良好。
關(guān)鍵詞:EasyX多線程繪圖
中圖分類號(hào):TP311 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):1009-3044(2018)30-0226-03
1 模擬鐘表整體設(shè)計(jì)
鐘表整體設(shè)計(jì)包括界面設(shè)計(jì)和程序設(shè)計(jì)兩部分。界面設(shè)計(jì)中體現(xiàn)背景圖案(應(yīng)用putimage方法)、背景音樂(lè)(應(yīng)用mciSendString方法)、指針的形狀與顏色(應(yīng)用setlinestyle,setlinecolor方法)、動(dòng)畫(huà)的圖形及文字(應(yīng)用setwritemode方法)。程序設(shè)計(jì)主要考慮應(yīng)用多線程技術(shù)來(lái)完成各種效果的并行調(diào)用,使得整體效果達(dá)到最佳,程序流程圖如圖1所示。
2 EasyX圖形庫(kù)配置
根據(jù)開(kāi)發(fā)環(huán)境選擇相應(yīng)的安裝包,下載鏈接:http://www.easyx.cn/downloads/,選擇Setup.hta文件進(jìn)行安裝,系統(tǒng)會(huì)自動(dòng)檢查你所安裝的開(kāi)發(fā)環(huán)境,你單擊安裝就可以了。若自動(dòng)安裝失敗,則需要手動(dòng)配置,將easyx\include文件夾中的兩個(gè)文件easyx.h和graphics.h拷貝到Visual Studio所在的安裝目錄VC\include文件夾中,再將easyx\lib\amd64文件夾中的easyx.lib和easyxw.lib拷貝到Visual Studio所在的安裝目錄VC\lib\amd64文件夾中,最后將easyx\lib文件夾中的四個(gè)文件(easyx.lib,easyx6.lib,easyxw.lib,easyxw6.lib)拷貝到Visual Studio所在的安裝目錄VC\lib文件夾中,EasyX手動(dòng)配置已完成,就可以使用圖形庫(kù)了。
3 鐘表靜態(tài)界面設(shè)計(jì)
程序需添加包含文件“graphics.h”“conio.h”“math.h”“windows.h”和“Mmsystem.h”。鐘表界面設(shè)計(jì)包括背景加載(圖片和音樂(lè)),表盤繪制。程序應(yīng)用“WINMM.LIB”庫(kù)文件,調(diào)用mciSendString()函數(shù)打開(kāi)、播放mp3格式文件,函數(shù)參數(shù)寫(xiě)法參考自定義函數(shù)Voice()。表盤界面大小應(yīng)用initgraph()設(shè)置,背景加載應(yīng)用loadimage()和putimage()完成,繪制文字及圖形采用EasyX圖形庫(kù)中的函數(shù)完成,代碼如下所示。
#include
#include
#include
#include
#include
#pragma comment(lib, "WINMM.LIB")
#define PI 3.14159265359
voidDial_plate()
{
initgraph(640, 480);
SetConsoleTitle(L"erwerwe");
// 初始化640 x 480 的繪圖窗口
IMAGE img;
loadimage(&img;, _T("123.jpg"));
putimage(0, 0, &img;);//插入背景圖
// 繪制一個(gè)簡(jiǎn)單的表盤
circle(320, 240, 2);
setcolor(YELLOW);
setfillcolor(LIGHTBLUE);
fillcircle(320, 240, 160);
setcolor(GREEN);
setfillcolor(WHITE);//設(shè)置顏色
fillcircle(320, 240, 60);
outtextxy(260, 310, _T("學(xué)習(xí)使我超快樂(lè)"));
//繪制刻度
outtextxy(320, 85, _T("12"));
outtextxy(320 + 150 * sin(PI / 6), 240 - 150 * cos(PI / 6), _T("1"));
outtextxy(320 + 150 * sin(PI / 3), 240 - 150 * cos(PI / 3), _T("2"));
outtextxy(320 + 145 * sin(2 * PI / 3), 240 - 145 * cos(2 * PI / 3), _T("4"));
outtextxy(320 + 140 * sin(5 * PI / 6), 240 - 140 * cos(5 * PI / 6), _T("5"));
outtextxy(320, 380, _T("6"));
outtextxy(320 + 145 * sin(7 * PI / 6), 240 - 145 * cos(7 * PI / 6), _T("7"));
outtextxy(320 + 150 * sin(8 * PI / 6), 240 - 150 * cos(8 * PI / 6), _T("8"));
outtextxy(165, 240, _T("9"));
outtextxy(320 + 150 * sin(10 * PI / 6), 240 - 150 * cos(10 * PI / 6), _T("10"));
outtextxy(320 + 150 * sin(11 * PI / 6), 240 - 150 * cos(11 * PI / 6), _T("11"));
outtextxy(470, 240, _T("3"));
}
void Voice()
{
mciSendString(_T("open Kalimba.mp3 alias bkmusic"), NULL, 0, NULL);
mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);
}
4 多線程繪圖技術(shù)應(yīng)用
根據(jù)表盤特效要求創(chuàng)建線程函數(shù)ThreadProc_A()和ThreadProc_B()。創(chuàng)建線程函數(shù)必須按相應(yīng)格式定義,返回值類型為DWORD _ stdcall,形參類型為L(zhǎng)PVOID。ThreadProc_A()函數(shù)實(shí)施2秒變化文字顏色,ThreadProc_B()函數(shù)實(shí)施中心圓填充顏色的變化,Draw(int hour, int minute, int second)函數(shù)動(dòng)態(tài)繪制時(shí)針、分針及秒針的位置,時(shí)間通過(guò)系統(tǒng)函數(shù)GetLocalTime()獲取,程序運(yùn)行界面如圖2所示,兩個(gè)線程函數(shù)及指針繪制函數(shù)代碼如下。
DWORD _stdcallThreadProc_A(LPVOID lpParameter)
{ while (true)
{
if (flag)
{ settextcolor(BLUE);
flag = false;
}
else
{
settextcolor(YELLOW);
flag = true;
}
outtextxy(260, 330, _T("西安思源學(xué)院"));
Sleep(2000);
}
}
DWORD _stdcallThreadProc_B(LPVOID lpParameter)
{ boolean flag1=true;
while(true)
{ if (flag)
{ setfillcolor(RED);
fillcircle(320, 240, 60);
flag = false;
}
else
{ setfillcolor(WHITE);
fillcircle(320, 240, 60);
flag = true;
}
Sleep(500);
}
}
void Draw(int hour, int minute, int second)
{
double a_hour, a_min, a_sec; // 時(shí)、分、秒針的弧度值
intx_hour, y_hour, x_min, y_min, x_sec, y_sec; // 時(shí)、分、秒針的末端位置
intxh, yh, xm, ym, xs, ys;// 時(shí)、分、秒針長(zhǎng)出來(lái)的部分
// 計(jì)算時(shí)、分、秒針的弧度值
a_sec = second * 2 * PI / 60;
a_min = minute * 2 * PI / 60 + a_sec / 60;
a_hour = hour * 2 * PI / 12 + a_min / 12;
// 計(jì)算時(shí)、分、秒針的末端位置
x_sec = 320 + (int)(120 * sin(a_sec));
y_sec = 240 - (int)(120 * cos(a_sec));
x_min = 320 + (int)(100 * sin(a_min));
y_min = 240 - (int)(100 * cos(a_min));
x_hour = 320 + (int)(70 * sin(a_hour));
y_hour = 240 - (int)(70 * cos(a_hour));
xh = 320 - (int)(25 * sin(a_hour));//計(jì)算長(zhǎng)出部分的端點(diǎn)坐標(biāo)
yh = 240 + (int)(25 * cos(a_hour));
xm = 320 - (int)(20 * sin(a_min));
ym = 240 + (int)(20 * cos(a_min));
xs = 320 - (int)(15 * sin(a_sec));
ys = 240 + (int)(15 * cos(a_sec));
// 畫(huà)時(shí)針
setlinestyle(PS_SOLID, 10, NULL);
setlinecolor(WHITE);
line(320, 240, x_hour, y_hour);
line(320, 240, xh, yh);
// 畫(huà)分針
setlinestyle(PS_SOLID, 6, NULL);
setlinecolor(LIGHTGRAY);
line(320, 240, x_min, y_min);
line(320, 240, xm, ym);
// 畫(huà)秒針
setlinestyle(PS_SOLID, 2, NULL);
setlinecolor(RED);
line(320, 240, x_sec, y_sec);
line(320, 240, xs, ys);
}
void main()
{
Dial_plate();
Voice();
CreateThread(NULL,0,ThreadProc_A,NULL,0,NULL);
CreateThread(NULL,0,ThreadProc_B,NULL,0,NULL);
// 設(shè)置XOR 繪圖模式
setwritemode(R2_XORPEN); // 設(shè)置XOR 繪圖模式
// 繪制表針
SYSTEMTIME ti; // 定義變量保存當(dāng)前時(shí)間
while (!_kbhit()) // 按任意鍵退出鐘表程序
{
GetLocalTime(&ti;); // 獲取當(dāng)前時(shí)間
Draw(ti.wHour, ti.wMinute, ti.wSecond); // 畫(huà)表針
Sleep(1000); // 延時(shí)1
Draw(ti.wHour, ti.wMinute, ti.wSecond); // 擦表針
}
closegraph(); // 關(guān)閉繪圖窗口
}
主函數(shù)順序調(diào)用Dial_plate()、Voice()完成靜態(tài)界面展示,緊接著啟動(dòng)兩個(gè)線程,分別啟動(dòng)線程函數(shù)ThreadProc_A()和ThreadProc_B(),實(shí)現(xiàn)背景顏色的變化。應(yīng)用_kbhit()函數(shù)判斷是否有按鍵事件發(fā)生,若沒(méi)有,獲取系統(tǒng)時(shí)間,間隔一秒繪制時(shí)針、分針和秒針,若有單擊事件,程序退出。
5 結(jié)束語(yǔ)
EasyX圖形庫(kù)是實(shí)現(xiàn)復(fù)雜圖形展示、模擬動(dòng)畫(huà)的利器,它縮短程序開(kāi)發(fā)的周期,增強(qiáng)程序的渲染程度,減少程序員的編碼量,圖形庫(kù)配置簡(jiǎn)單,是VS集成開(kāi)發(fā)環(huán)境很好的圖形庫(kù),EasyX圖形庫(kù)有很豐富的參考資料,值得我們掌握。要實(shí)現(xiàn)多個(gè)獨(dú)立的動(dòng)畫(huà)效果,采用多線程技術(shù),創(chuàng)建多線程來(lái)實(shí)現(xiàn)也是不錯(cuò)的選擇。
參考文獻(xiàn):
[1] 宋雅娟,邊晶.基于easyX動(dòng)畫(huà)案例開(kāi)發(fā)導(dǎo)向的C語(yǔ)言程序設(shè)計(jì)課程教學(xué)方法研究[J].長(zhǎng)春大學(xué)學(xué)報(bào),2018,28(06):111-115+119.
[2] 趙敏,龐蕊.基于EasyX圖形庫(kù)的C語(yǔ)言課程改革研究與實(shí)踐[J].電腦知識(shí)與技術(shù),2015(32).
[3] 孫經(jīng)緯,孫廣中,詹石巖,等.SA*:一種多線程路徑規(guī)劃算法[J].地球信息科學(xué)學(xué)報(bào),2018,20(06):753-761.
[4] 李琳.探討C++編程中避免代碼冗余的技巧[J].電腦知識(shí)與技術(shù),2017,13(32):101-102.
【通聯(lián)編輯:朱寶貴】