文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C++使用easyX库实现三星环绕效果流程详解

2022-11-13 19:02

关注

1,项目描述

功能1:使用图形化的方式描述地球围绕着太阳转动,月球围绕着地球转动

功能2:在转动的过程中当用户按下1,2,3,4,5,6,7时它可以变换出7种不同的颜色,当用户按下8时它可以变换从1-7的颜色依次变换当用户再次按下8键时停止变换颜色

功能3:当用户按下上键时,地球会围绕太阳反转,当再次按下上键时地球会恢复到正转

功能4:当用户按下空格键的时候,所有动画暂停,当再次按下空格键的时候所有动画继续进行。

2,解决思路

其实纵观整个项目需求,在不考虑真实的星体运算下,它的实现原理就像是时钟转动的实现原理是一致的

对于地球围绕着太阳进行转动来说,可以将太阳作为中心点,地球围绕着这个中心点进行转动,对于月球围绕着地球进行转动来说,可以将地球作为一个中心点,月球围绕着地球进行转动,这样就实现了基本的地球,太阳和月球的三星环绕

需要考虑的是整个项目是在转动中获取按键信息做出相应的画面更新,所以按键更新画面应该是放在一个非阻塞的函数下进行,也就是使用_kbhit()来实现,将这个条件放在运行中的死循环之中,可以随时通过按键信息更新画面基本元素

当考虑到8键,空格键和上键时,它们三个键位就相当于开关,按下就开,再按就关,我可以使用开关算法完成这样的操作。

3,关键代码

开发使用IDE:Visual Studio2019

注意:

easyX库不是C++的自带库需要下载和安装,很简单

easyX库是基于C++的,所以文件的后缀名需要改为.cpp才能正常运行

首先为了方便程序的可维护性,所以最开始,使用了枚举定义了地球,月球和太阳的半径。

typedef enum RADIES {//星球半径
    sunradies = 150,//太阳
    earthradies = 30,//地球
    moonradies = 5,//月亮
}radies;

然后为了能实现色彩的变化,也可以先定义一个颜色的枚举,颜色是基于easyX库中的。

typedef enum COLOR {//颜色
    black = 0,//黑色
    blue = 0xAA0000,//蓝色
    green = 0x00AA00,//绿色
    cyan = 0xAAAA00,//青色
    red = 0x0000AA,//红色
    magenta = 0xAA00AA,//紫色
    brown = 0x0055AA,//棕色
    lightgray = 0xAAAAAA,//浅灰
    yellow = 0x55FFFF,//黄色
}color;

可以看作是三个中心点之间的不断的运算关系,最核心的是通过不断更新中心坐标的位置实现,对于太阳来说,它的中心坐标是位于窗口的中心,并且对于太阳来说它是不动的,对于地球来说,它的中心坐标是根据以太阳为中心基点,围绕着太阳进行转动的,对于月球来说,亦然,地球和月球都是行星,它们的运动是依靠着坐标点的位置变化实现,所以可以定义一个行星结构体,包含行星的半径和行星中心x和y坐标

typedef struct Plant {//行星
    int radies;//行星半径
    int center_x;//行星中心X坐标
    int center_y;//行星中心Y坐标
}plant;

在程序中先创建行星,也就是为行星赋予基本的中心点和半径作初始化,然后,通过绘制行星,传入行星实时更新的坐标点在死循环中更新图像。

//通过传入结构体指针首先给指针所指向的内存地址中的相关属性赋初值
void creatplant(plant* p, int x, int y, int radies) {
p->center_x = x;//行星中心的初始x坐标
p->center_y = 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);//以p2为中心,实时改变角度改变内存的x值
p1->center_y = p2->center_y - (WIDTH / a) * cos(angle);//以p2为中心,实时改变角度改变内存的y值
setfillcolor(c);
solidcircle(p1->center_x, p1->center_y, p1->radies);//根据改变的值绘制图形
}

直接绘制太阳,因为太阳就是一个静止的状态:

//因为太阳它是固定的就是一个静态图片
void drawsun(color c, int x, int y, radies r) {
setfillcolor(c);
solidcircle(x, y, r);
}

接下来就可在主方法中进行绘制的实验了

int main(){
    plant s, e, m;
    color c1=red;
    creatplant(&s, WIDTH / 2, HEIGHT / 2, sunradies);//创建太阳属性
    creatplant(&e, WIDTH / 8, HEIGHT / 8, earthradies);//创建地球属性
    creatplant(&m, WIDTH / 10, HEIGHT / 10, moonradies);//创建月球属性
    while (1) {
        drawsun(c1, s.center_x, s.center_y, sunradies);//画太阳
        BeginBatchDraw();在内存中绘画,避免频闪
        drawplant(&e, &s, eangle, 3, blue, earthradies);//传入地球,更新角度并且绘制
        drawplant(&m, &e, mangle, 13, yellow, moonradies);//传入月球,更新角度并且绘制
        eangle = eangle + 2 * PI / 60;//地球的角度实时变化
        mangle = mangle + 2 * PI / 30;//月球的角度实时变化,分的分数应该更小如果等于60一起转动
        Sleep(50); //便于看出轨迹的运动
        FlushBatchDraw();//将画出的内容从内存调出
        clearcircle(e.center_x, e.center_y, earthradies);//清除
        clearcircle(m.center_x, m.center_y, moonradies);//清除,再画下一次的更新
    }
    return 0;
}

实验截图:

该代码用于主方法中控制整个程序的流程,其关键部分如下,56,32,72是键值,也就是在键盘中它都有对应的值

int i = 1;//作为闪烁颜色的开关
int m1 = 1;//作为暂停的开关
int n1 = 1;//作为逆时针转动的开关
while (key != 27) {
    if (_kbhit()) {//使用的非阻塞方法,也就是它不会等待事件的发生而阻塞是一直接收事件
    switch (key = _getch()) {
        case 56:i = i * -1; break;//当按下8键时,i=-1<0,进行颜色变换,当再按下8键时,i>0,不变
        case 32:m1 = m1 * -1; break;//按下空格时<0,再按下时>0
        case 72:n1 = n1 * -1; break;//按下上时<0,再按下时>0
    }
}
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);
}
if (m1 > 0) {//只有当m1>0时才会改变角度,当m1<0时不再改变
    if (n1 > 0) {//当n1>0时才会正转,<0时走反转
        eangle = eangle + 2 * PI / 60;
        mangle = mangle + 2 * PI / 30;
    }
    else {
        eangle = eangle - 2 * PI / 60;
        mangle = mangle - 2 * PI / 30;
    }
    }
}

4,项目运行截图

5,具体代码实现

#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,//蓝色
	green = 0x00AA00,//绿色
	cyan = 0xAAAA00,//青色
	red = 0x0000AA,//红色
	magenta = 0xAA00AA,//紫色
	brown = 0x0055AA,//棕色
	lightgray = 0xAAAAAA,//浅灰
	yellow = 0x55FFFF,//黄色
}color;
typedef struct Plant {//行星
	int radies;//行星半径
	int center_x;//行星中心X坐标
	int center_y;//行星中心Y坐标
}plant;
void drawsun(color c, int x, int y, radies r);//绘制太阳
void creatplant(plant* p, int x, int y, int radies);//创建星球
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);//创建太阳属性
	creatplant(&e, WIDTH / 8, HEIGHT / 8, earthradies);//创建地球属性
	creatplant(&m, WIDTH / 10, HEIGHT / 10, moonradies);//创建月球属性
	color c1 = red;
	initgraph(WIDTH, HEIGHT);
	double eangle = 0;
	double mangle = 0;
	char key = 0;
	int i = 1;//作为闪烁颜色的开关
	int m1 = 1;//作为暂停的开关
	int n1 = 1;//作为逆时针转动的开关
	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);
}

到此这篇关于C++使用easyX库实现三星环绕效果流程详解的文章就介绍到这了,更多相关C++三星环绕内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯