如何实现两部分绘制循环同时进行,互不影响

0

现在的代码只能在樱花树绘制完之后进行流星的移动,有没有办法可以让流星自由移动的同时绘制樱花树

#include <easyx.h>
#include<stdio.h>
#include <graphics.h>
#include<conio.h>
#include<stdlib.h>
#include <time.h>
#include <algorithm>

IMAGE meteor1, meteor2;
float offsetAngle = PI / 4; // 左右枝干和父枝干偏离的角度
float shortenRate = 0.7;  // 子枝干比父枝干变短的倍数

/*星星结构体*/
struct Star
{
	int x, y;//坐标
	int step;//速度
	int color;//颜色

}star[1000];

/*流星结构体*/
struct Metor
{
	int x, y;//坐标
	int step;//速度
	int style;//图片

}meteor[520];

int main()
{
	srand(time(0)); // 随机初始化

	initgraph(WIDTH, HEIGHT); // 新开一个画面

	loadimage(&meteor1, _T("C:\\Users\\suenos\\Desktop\\use\\meteor1.jpg"));
	loadimage(&meteor2, _T("C:\\Users\\suenos\\Desktop\\use\\meteor2.jpg"));

	int i = 0;

	//初始化所有行星
	for (i = 0; i < 1000; i++)
		initStar(i);
	//初始化所有流星
	for (i = 0; i < 520; i++)
		initMeteor(i);

	while (1)
	{
		BeginBatchDraw();//防止闪屏,和EndBatchDraw()搭配使用
		cleardevice();//刷新

		for (i = 0; i < 1000; i++)//画1000个星星
			drawStar(i);

		drawMeteor(i);
		
		Sleep(50);

		brunch(WIDTH / 3, HEIGHT, 0.4 * HEIGHT * shortenRate, -PI / 2, 15 * shortenRate, 1); // 递归函数调用
		
		EndBatchDraw();
	}
}


float mapValue(float input, float inputMin, float inputMax, float outputMin, float outputMax)
{
	float output;
	if (abs(input - inputMin) < 0.000001) // 防止除以零的bug
		output = outputMin;
	else
		output = (input - inputMin) * (outputMax - outputMin) / (inputMax - inputMin) + outputMin;
	return output;
}

float randBetween(float min, float max)
{
	float t = rand() / double(RAND_MAX); // 生成[0,1]的随机小数
	// 调用mapValue函数,把值范围从[0,1]映射到[min,max]
	float r = mapValue(t, 0, 1, min, max);
	return r;
}

void brunch(float x_start, float y_start, float length, float angle, float thickness, int generation) //参数:枝干起始x y坐标,枝干长度,枝干角度,枝干绘图线条宽度,第几代
{
	int i = 520;

	// 利用三角函数求出当前枝干的终点x,y坐标
	float x_end, y_end;
	x_end = x_start + length * cos(angle);
	y_end = y_start + length * sin(angle);

	moveMeteor(i);

	// 画线条枝干
	setlinestyle(PS_SOLID, thickness); // 设定当前枝干线宽

	moveMeteor(i);

	// 设置枝干为灰褐色,主树干最黑,子枝干逐渐变亮
	COLORREF  color = HSVtoRGB(15, 0.75, 0.4 + generation * 0.05);
	setlinecolor(color); // 设定当前枝干颜色

	line(x_start, y_start, x_end, y_end); // 画出当前枝干(画线)

	moveMeteor(i);

	// 求出子枝干的代数
	int childGeneration = generation + 1;

	// 生成左、右、中间三个子枝干的长度,逐渐变短,并有一定随机性
	float childLength = shortenRate * length;
	float leftChildLength = childLength * randBetween(0.9, 1.1);
	float rightChildLength = childLength * randBetween(0.9, 1.1);
	float centerChildLength = childLength * randBetween(0.8, 1.1);

	moveMeteor(i);

	// 当子枝干长度大于2,并且代数小于等于10,递归调用产生子枝干
	if (childLength >= 2 && childGeneration <= 9)
	{
		// 生成子枝干的粗细,逐渐变细
		float childThickness = thickness * 0.8;

		if (childThickness < 2) // 枝干绘图最细的线宽为2
			childThickness = 2;

		moveMeteor(i);

		// 一定概率产生左、右、中子枝干
		if (randBetween(0, 1) < 0.95)
			brunch(x_end, y_end, leftChildLength, angle + offsetAngle * randBetween(0.5, 1), childThickness, childGeneration);
		if (randBetween(0, 1) < 0.95)
			brunch(x_end, y_end, rightChildLength, angle - offsetAngle * randBetween(0.5, 1), childThickness, childGeneration);
		if (randBetween(0, 1) < 0.85)
			brunch(x_end, y_end, centerChildLength, angle + offsetAngle / 5 * randBetween(-1, 1), childThickness, childGeneration);
	}
	else // 最末端绘制樱花,画一个粉色填充圆
	{
		setlinestyle(PS_SOLID, 1); // 线宽
		// 樱花粉色HSVtoRGB(325,0.3,1),有一定随机性
		COLORREF  color = HSVtoRGB(randBetween(300, 350), randBetween(0.2, 0.3), 1);
		setlinecolor(color); // 设定线条颜色
		setfillcolor(color); // 设定填充颜色

		if (childLength <= 4) // 如果子枝干长度小于等于4
			fillcircle(x_end, y_end, 2); // 圆的半径为2(再小就看不清了)
		else
			fillcircle(x_end, y_end, childLength / 2); // 画一个圆,半径为子枝干长度的一半
	}

	moveMeteor(i);

	FlushBatchDraw(); // 批量绘制
	Sleep(1); // 暂停
}

void initStar(int i)
{
	star[i].x = rand() % 1000;
	star[i].y = rand() % 600;
	star[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);//星星的颜色采用五颜六色
	star[i].step = rand() % 5 + 2;
}

void initMeteor(int i)
{
	meteor[i].x = rand() % 2000 - 1000;//这样的话,取的值就是在[0,1999]之间
	meteor[i].y = rand() % 200;//[0,199]-400;
	meteor[i].step = rand() % 20 + 5;//[0,40]+5
	meteor[i].style = rand() % 2;//流星有两种风格随便取
}

void drawMeteor(int i)
{
	for (i = 0; i < 520; i++)
	{
		if (meteor[i].style == 0)
			putimage(meteor[i].x, meteor[i].y, &meteor1, SRCPAINT);//为了防止这流星图片重叠,而加的SRCPAINT

		if (meteor[i].style == 1)
			putimage(meteor[i].x, meteor[i].y, &meteor2, SRCPAINT);
	}
}

void drawStar(int i)
{
	putpixel(star[i].x, star[i].y, star[i].color);
	star[i].x += star[i].step;

	if (star[i].x > 945)
	{
		putpixel(star[i].x, star[i].y, star[i].color);
		initStar(i);
	}
}

void moveMeteor(int i)
{
	for (i = 0; i < 520; i++)
	{
		meteor[i].x += meteor[i].step;
		meteor[i].y += meteor[i].step;

		if (meteor[i].x > 1000 || meteor[i].y > 600)
			initMeteor(i);
	}
}
ava
希冉

2021-4-25

0

将两个绘图分成一个个的独立步骤,然后:

while(true)
{
	流星计算();
	樱花计算();

	绘制流星();
	绘制樱花();

	Sleep(20);
}
ava
慢羊羊

2021-4-25

技术讨论社区