C++使用easyX庫實(shí)現(xiàn)三星環(huán)繞效果流程詳解
1,項(xiàng)目描述
功能1:使用圖形化的方式描述地球圍繞著太陽轉(zhuǎn)動(dòng),月球圍繞著地球轉(zhuǎn)動(dòng)
功能2:在轉(zhuǎn)動(dòng)的過程中當(dāng)用戶按下1,2,3,4,5,6,7時(shí)它可以變換出7種不同的顏色,當(dāng)用戶按下8時(shí)它可以變換從1-7的顏色依次變換當(dāng)用戶再次按下8鍵時(shí)停止變換顏色
功能3:當(dāng)用戶按下上鍵時(shí),地球會(huì)圍繞太陽反轉(zhuǎn),當(dāng)再次按下上鍵時(shí)地球會(huì)恢復(fù)到正轉(zhuǎn)
功能4:當(dāng)用戶按下空格鍵的時(shí)候,所有動(dòng)畫暫停,當(dāng)再次按下空格鍵的時(shí)候所有動(dòng)畫繼續(xù)進(jìn)行。
2,解決思路
其實(shí)縱觀整個(gè)項(xiàng)目需求,在不考慮真實(shí)的星體運(yùn)算下,它的實(shí)現(xiàn)原理就像是時(shí)鐘轉(zhuǎn)動(dòng)的實(shí)現(xiàn)原理是一致的
對于地球圍繞著太陽進(jìn)行轉(zhuǎn)動(dòng)來說,可以將太陽作為中心點(diǎn),地球圍繞著這個(gè)中心點(diǎn)進(jìn)行轉(zhuǎn)動(dòng),對于月球圍繞著地球進(jìn)行轉(zhuǎn)動(dòng)來說,可以將地球作為一個(gè)中心點(diǎn),月球圍繞著地球進(jìn)行轉(zhuǎn)動(dòng),這樣就實(shí)現(xiàn)了基本的地球,太陽和月球的三星環(huán)繞
需要考慮的是整個(gè)項(xiàng)目是在轉(zhuǎn)動(dòng)中獲取按鍵信息做出相應(yīng)的畫面更新,所以按鍵更新畫面應(yīng)該是放在一個(gè)非阻塞的函數(shù)下進(jìn)行,也就是使用_kbhit()來實(shí)現(xiàn),將這個(gè)條件放在運(yùn)行中的死循環(huán)之中,可以隨時(shí)通過按鍵信息更新畫面基本元素
當(dāng)考慮到8鍵,空格鍵和上鍵時(shí),它們?nèi)齻€(gè)鍵位就相當(dāng)于開關(guān),按下就開,再按就關(guān),我可以使用開關(guān)算法完成這樣的操作。
3,關(guān)鍵代碼
開發(fā)使用IDE:Visual Studio2019
注意:
easyX庫不是C++的自帶庫需要下載和安裝,很簡單
easyX庫是基于C++的,所以文件的后綴名需要改為.cpp才能正常運(yùn)行
首先為了方便程序的可維護(hù)性,所以最開始,使用了枚舉定義了地球,月球和太陽的半徑。
typedef enum RADIES {//星球半徑 sunradies = 150,//太陽 earthradies = 30,//地球 moonradies = 5,//月亮 }radies;
然后為了能實(shí)現(xiàn)色彩的變化,也可以先定義一個(gè)顏色的枚舉,顏色是基于easyX庫中的。
typedef enum COLOR {//顏色 black = 0,//黑色 blue = 0xAA0000,//藍(lán)色 green = 0x00AA00,//綠色 cyan = 0xAAAA00,//青色 red = 0x0000AA,//紅色 magenta = 0xAA00AA,//紫色 brown = 0x0055AA,//棕色 lightgray = 0xAAAAAA,//淺灰 yellow = 0x55FFFF,//黃色 }color;
- 實(shí)現(xiàn)基本的地球,太陽和月球三星環(huán)繞關(guān)鍵代碼
可以看作是三個(gè)中心點(diǎn)之間的不斷的運(yùn)算關(guān)系,最核心的是通過不斷更新中心坐標(biāo)的位置實(shí)現(xiàn),對于太陽來說,它的中心坐標(biāo)是位于窗口的中心,并且對于太陽來說它是不動(dòng)的,對于地球來說,它的中心坐標(biāo)是根據(jù)以太陽為中心基點(diǎn),圍繞著太陽進(jìn)行轉(zhuǎn)動(dòng)的,對于月球來說,亦然,地球和月球都是行星,它們的運(yùn)動(dòng)是依靠著坐標(biāo)點(diǎn)的位置變化實(shí)現(xiàn),所以可以定義一個(gè)行星結(jié)構(gòu)體,包含行星的半徑和行星中心x和y坐標(biāo)
typedef struct Plant {//行星 int radies;//行星半徑 int center_x;//行星中心X坐標(biāo) int center_y;//行星中心Y坐標(biāo) }plant;
在程序中先創(chuàng)建行星,也就是為行星賦予基本的中心點(diǎn)和半徑作初始化,然后,通過繪制行星,傳入行星實(shí)時(shí)更新的坐標(biāo)點(diǎn)在死循環(huán)中更新圖像。
//通過傳入結(jié)構(gòu)體指針首先給指針?biāo)赶虻膬?nèi)存地址中的相關(guān)屬性賦初值 void creatplant(plant* p, int x, int y, int radies) { p->center_x = x;//行星中心的初始x坐標(biāo) p->center_y = y;//行星中心的初始y坐標(biāo) p->radies = radies;//行星的半徑 }
通過傳入中心行星和環(huán)繞行星,使用指針來訪問內(nèi)存空間,通過修改內(nèi)存中的數(shù)值實(shí)現(xiàn)實(shí)時(shí)改變終點(diǎn)坐標(biāo)
void drawplant(plant* p1, plant* p2, double angle, int a, color c, radies r) { p1->center_x = p2->center_x + (WIDTH / a) * sin(angle);//以p2為中心,實(shí)時(shí)改變角度改變內(nèi)存的x值 p1->center_y = p2->center_y - (WIDTH / a) * cos(angle);//以p2為中心,實(shí)時(shí)改變角度改變內(nèi)存的y值 setfillcolor(c); solidcircle(p1->center_x, p1->center_y, p1->radies);//根據(jù)改變的值繪制圖形 }
直接繪制太陽,因?yàn)樘柧褪且粋€(gè)靜止的狀態(tài):
//因?yàn)樘査枪潭ǖ木褪且粋€(gè)靜態(tài)圖片 void drawsun(color c, int x, int y, radies r) { setfillcolor(c); solidcircle(x, y, r); }
接下來就可在主方法中進(jìn)行繪制的實(shí)驗(yàn)了
int main(){ plant s, e, m; color c1=red; creatplant(&s, WIDTH / 2, HEIGHT / 2, sunradies);//創(chuàng)建太陽屬性 creatplant(&e, WIDTH / 8, HEIGHT / 8, earthradies);//創(chuàng)建地球?qū)傩? creatplant(&m, WIDTH / 10, HEIGHT / 10, moonradies);//創(chuàng)建月球?qū)傩? while (1) { drawsun(c1, s.center_x, s.center_y, sunradies);//畫太陽 BeginBatchDraw();在內(nèi)存中繪畫,避免頻閃 drawplant(&e, &s, eangle, 3, blue, earthradies);//傳入地球,更新角度并且繪制 drawplant(&m, &e, mangle, 13, yellow, moonradies);//傳入月球,更新角度并且繪制 eangle = eangle + 2 * PI / 60;//地球的角度實(shí)時(shí)變化 mangle = mangle + 2 * PI / 30;//月球的角度實(shí)時(shí)變化,分的分?jǐn)?shù)應(yīng)該更小如果等于60一起轉(zhuǎn)動(dòng) Sleep(50); //便于看出軌跡的運(yùn)動(dòng) FlushBatchDraw();//將畫出的內(nèi)容從內(nèi)存調(diào)出 clearcircle(e.center_x, e.center_y, earthradies);//清除 clearcircle(m.center_x, m.center_y, moonradies);//清除,再畫下一次的更新 } return 0; }
實(shí)驗(yàn)截圖:
- 開關(guān)算法思想關(guān)鍵代碼
該代碼用于主方法中控制整個(gè)程序的流程,其關(guān)鍵部分如下,56,32,72是鍵值,也就是在鍵盤中它都有對應(yīng)的值
int i = 1;//作為閃爍顏色的開關(guān) int m1 = 1;//作為暫停的開關(guān) int n1 = 1;//作為逆時(shí)針轉(zhuǎn)動(dòng)的開關(guān) while (key != 27) { if (_kbhit()) {//使用的非阻塞方法,也就是它不會(huì)等待事件的發(fā)生而阻塞是一直接收事件 switch (key = _getch()) { case 56:i = i * -1; break;//當(dāng)按下8鍵時(shí),i=-1<0,進(jìn)行顏色變換,當(dāng)再按下8鍵時(shí),i>0,不變 case 32:m1 = m1 * -1; break;//按下空格時(shí)<0,再按下時(shí)>0 case 72:n1 = n1 * -1; break;//按下上時(shí)<0,再按下時(shí)>0 } } if (i < 0) {//進(jìn)行顏色的變換 color c[8] = { black,blue,red,blue,yellow,cyan,magenta,blue }; srand((unsigned)time(NULL)); int n = rand() % 8; Sleep(1); drawsun(c[n], s.center_x, s.center_y, sunradies); } if (m1 > 0) {//只有當(dāng)m1>0時(shí)才會(huì)改變角度,當(dāng)m1<0時(shí)不再改變 if (n1 > 0) {//當(dāng)n1>0時(shí)才會(huì)正轉(zhuǎn),<0時(shí)走反轉(zhuǎn) eangle = eangle + 2 * PI / 60; mangle = mangle + 2 * PI / 30; } else { eangle = eangle - 2 * PI / 60; mangle = mangle - 2 * PI / 30; } } }
4,項(xiàng)目運(yùn)行截圖
5,具體代碼實(shí)現(xiàn)
#include<graphics.h> #include<conio.h> #include<stdlib.h> #include<math.h> #include<time.h> #define WIDTH 800//窗口的寬 #define HEIGHT 800//窗口的高 #define PI 3.14159//PI typedef enum RADIES {//星球半徑 sunradies = 150,//太陽 earthradies = 30,//地球 moonradies = 5,//月亮 }radies; typedef enum COLOR {//顏色 black = 0,//黑色 blue = 0xAA0000,//藍(lán)色 green = 0x00AA00,//綠色 cyan = 0xAAAA00,//青色 red = 0x0000AA,//紅色 magenta = 0xAA00AA,//紫色 brown = 0x0055AA,//棕色 lightgray = 0xAAAAAA,//淺灰 yellow = 0x55FFFF,//黃色 }color; typedef struct Plant {//行星 int radies;//行星半徑 int center_x;//行星中心X坐標(biāo) int center_y;//行星中心Y坐標(biāo) }plant; void drawsun(color c, int x, int y, radies r);//繪制太陽 void creatplant(plant* p, int x, int y, int radies);//創(chuàng)建星球 void drawplant(plant* p1, plant* p2, double angle, int a, color c, radies r);//繪制星球 int main() { plant s, e, m; creatplant(&s, WIDTH / 2, HEIGHT / 2, sunradies);//創(chuàng)建太陽屬性 creatplant(&e, WIDTH / 8, HEIGHT / 8, earthradies);//創(chuàng)建地球?qū)傩? creatplant(&m, WIDTH / 10, HEIGHT / 10, moonradies);//創(chuàng)建月球?qū)傩? color c1 = red; initgraph(WIDTH, HEIGHT); double eangle = 0; double mangle = 0; char key = 0; int i = 1;//作為閃爍顏色的開關(guān) int m1 = 1;//作為暫停的開關(guān) int n1 = 1;//作為逆時(shí)針轉(zhuǎn)動(dòng)的開關(guān) while (key != 27) { if (_kbhit()) { switch (key = _getch()) { case 49:c1 = blue; break; case 50:c1 = yellow; break; case 52:c1 = brown; break; case 53:c1 = magenta; break; case 54:c1 = red; break; case 55:c1 = lightgray; break; case 56:i = i * -1; break; case 32:m1 = m1 * -1; break; case 27:break; case 72:n1 = n1 * -1; break; } drawsun(c1, s.center_x, s.center_y, sunradies); } drawsun(c1, s.center_x, s.center_y, sunradies); if (i < 0) { color c[8] = { black,blue,red,blue,yellow,cyan,magenta,blue }; srand((unsigned)time(NULL)); int n = rand() % 8; Sleep(1); drawsun(c[n], s.center_x, s.center_y, sunradies); } BeginBatchDraw(); drawplant(&e, &s, eangle, 3, blue, earthradies); drawplant(&m, &e, mangle, 13, yellow, moonradies); if (m1 > 0) { if (n1 > 0) { eangle = eangle + 2 * PI / 60; mangle = mangle + 2 * PI / 30; } else { eangle = eangle - 2 * PI / 60; mangle = mangle - 2 * PI / 30; } } Sleep(50); FlushBatchDraw(); clearcircle(e.center_x, e.center_y, earthradies); clearcircle(m.center_x, m.center_y, moonradies); } EndBatchDraw(); _getch(); closegraph(); return 0; } void drawsun(color c, int x, int y, radies r) { setfillcolor(c); solidcircle(x, y, r); } void creatplant(plant* p, int x, int y, int radies) { p->center_x = x; p->center_y = y; p->radies = radies; } void drawplant(plant* p1, plant* p2, double angle, int a, color c, radies r) { p1->center_x = p2->center_x + (WIDTH / a) * sin(angle); p1->center_y = p2->center_y - (WIDTH / a) * cos(angle); setfillcolor(c); solidcircle(p1->center_x, p1->center_y, p1->radies); } /* 地球要圍繞著太陽轉(zhuǎn)動(dòng) 月球要圍繞著地球轉(zhuǎn)動(dòng) 按下1-7的按鍵時(shí),太陽會(huì)變色 按下8的時(shí)候太陽會(huì)依次的變色 當(dāng)按下空格鍵的時(shí)候,太陽會(huì)停止轉(zhuǎn)動(dòng) 當(dāng)按下上鍵的時(shí)候地球和月亮?xí)嫦虻霓D(zhuǎn)動(dòng),再按下上鍵的時(shí)候,地球和月亮?xí)槙r(shí)針轉(zhuǎn)動(dòng) */
到此這篇關(guān)于C++使用easyX庫實(shí)現(xiàn)三星環(huán)繞效果流程詳解的文章就介紹到這了,更多相關(guān)C++三星環(huán)繞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)與Lua相互調(diào)用的示例詳解
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)與Lua相互調(diào)用的方法,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-03-03C語言實(shí)現(xiàn)日期和時(shí)間處理的常用函數(shù)總結(jié)
在C語言中,時(shí)間和日期處理是一項(xiàng)非?;A(chǔ)的技能,也是開發(fā)實(shí)際應(yīng)用程序時(shí)經(jīng)常會(huì)用到的功能,本文為大家總結(jié)了C語言中一些常用的時(shí)間庫函數(shù),希望對大家有所幫助2023-06-06C++中的函數(shù)指針與函數(shù)對象的總結(jié)
以下是對C++中的函數(shù)指針與函數(shù)對象的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以參考下2013-07-07C++17實(shí)現(xiàn)flyweight_factory模板類及使用示例詳解
這篇文章主要為大家介紹了C++17實(shí)現(xiàn)flyweight_factory模板類及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08undefined reference to `SetPduPowerConsumptionCnt''錯(cuò)誤的解決方法
編譯時(shí)出現(xiàn)undefined reference to `SetPduPowerConsumptionCnt'錯(cuò)誤要如何解決呢?有沒有什么好的解決方法?下面小編就為大家解答吧,如果你也遇到了這種情況,可以過來參考下2013-07-07深入解析C++設(shè)計(jì)模式編程中解釋器模式的運(yùn)用
這篇文章主要介紹了C++設(shè)計(jì)模式編程中解釋器模式的運(yùn)用,解釋器模式給定一個(gè)語言,定義它的文法的一種表示,并定義一個(gè)解釋器,這個(gè)解釋器使用該表示來解釋語言中的句子,需要的朋友可以參考下2016-03-03