C++使用easyX庫(kù)實(shí)現(xiàn)三星環(huán)繞效果流程詳解
1,項(xiàng)目描述
功能1:使用圖形化的方式描述地球圍繞著太陽(yáng)轉(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ì)圍繞太陽(yáng)反轉(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)原理是一致的
對(duì)于地球圍繞著太陽(yáng)進(jìn)行轉(zhuǎn)動(dòng)來說,可以將太陽(yáng)作為中心點(diǎn),地球圍繞著這個(gè)中心點(diǎn)進(jìn)行轉(zhuǎn)動(dòng),對(duì)于月球圍繞著地球進(jìn)行轉(zhuǎn)動(dòng)來說,可以將地球作為一個(gè)中心點(diǎn),月球圍繞著地球進(jìn)行轉(zhuǎn)動(dòng),這樣就實(shí)現(xiàn)了基本的地球,太陽(yáng)和月球的三星環(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庫(kù)不是C++的自帶庫(kù)需要下載和安裝,很簡(jiǎn)單
easyX庫(kù)是基于C++的,所以文件的后綴名需要改為.cpp才能正常運(yùn)行
首先為了方便程序的可維護(hù)性,所以最開始,使用了枚舉定義了地球,月球和太陽(yáng)的半徑。
typedef enum RADIES {//星球半徑
sunradies = 150,//太陽(yáng)
earthradies = 30,//地球
moonradies = 5,//月亮
}radies;然后為了能實(shí)現(xiàn)色彩的變化,也可以先定義一個(gè)顏色的枚舉,顏色是基于easyX庫(kù)中的。
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)基本的地球,太陽(yáng)和月球三星環(huán)繞關(guān)鍵代碼
可以看作是三個(gè)中心點(diǎn)之間的不斷的運(yùn)算關(guān)系,最核心的是通過不斷更新中心坐標(biāo)的位置實(shí)現(xiàn),對(duì)于太陽(yáng)來說,它的中心坐標(biāo)是位于窗口的中心,并且對(duì)于太陽(yáng)來說它是不動(dòng)的,對(duì)于地球來說,它的中心坐標(biāo)是根據(jù)以太陽(yáng)為中心基點(diǎn),圍繞著太陽(yáng)進(jìn)行轉(zhuǎn)動(dòng)的,對(duì)于月球來說,亦然,地球和月球都是行星,它們的運(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áng),因?yàn)樘?yáng)就是一個(gè)靜止的狀態(tài):
//因?yàn)樘?yáng)它是固定的就是一個(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)建太陽(yá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);//畫太陽(yáng)
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是鍵值,也就是在鍵盤中它都有對(duì)應(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,//太陽(yáng)
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);//繪制太陽(yáng)
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)建太陽(yá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);
}
/*
地球要圍繞著太陽(yáng)轉(zhuǎn)動(dòng)
月球要圍繞著地球轉(zhuǎn)動(dòng)
按下1-7的按鍵時(shí),太陽(yáng)會(huì)變色
按下8的時(shí)候太陽(yáng)會(huì)依次的變色
當(dāng)按下空格鍵的時(shí)候,太陽(yáng)會(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庫(kù)實(shí)現(xiàn)三星環(huán)繞效果流程詳解的文章就介紹到這了,更多相關(guān)C++三星環(huán)繞內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(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-03
C語(yǔ)言實(shí)現(xiàn)日期和時(shí)間處理的常用函數(shù)總結(jié)
在C語(yǔ)言中,時(shí)間和日期處理是一項(xiàng)非常基礎(chǔ)的技能,也是開發(fā)實(shí)際應(yīng)用程序時(shí)經(jīng)常會(huì)用到的功能,本文為大家總結(jié)了C語(yǔ)言中一些常用的時(shí)間庫(kù)函數(shù),希望對(duì)大家有所幫助2023-06-06
C++中的函數(shù)指針與函數(shù)對(duì)象的總結(jié)
以下是對(duì)C++中的函數(shù)指針與函數(shù)對(duì)象的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以參考下2013-07-07
C++可執(zhí)行文件絕對(duì)路徑值與VS安全檢查詳解
這篇文章主要給大家介紹了關(guān)于C++可執(zhí)行文件絕對(duì)路徑值與VS安全檢查的相關(guān)資料,文中通過圖文以及實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-01-01
C++17實(shí)現(xiàn)flyweight_factory模板類及使用示例詳解
這篇文章主要為大家介紹了C++17實(shí)現(xiàn)flyweight_factory模板類及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
undefined 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è)語(yǔ)言,定義它的文法的一種表示,并定義一個(gè)解釋器,這個(gè)解釋器使用該表示來解釋語(yǔ)言中的句子,需要的朋友可以參考下2016-03-03

