樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

这篇具有很好参考价值的文章主要介绍了樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

💐专栏导读

🌸作者简介:花想云,在读本科生一枚,致力于 C/C++、Linux 学习。

🌸本文收录于 初学C语言必会的20个小游戏专栏,本专栏主要内容为利用C/C++与图形库EasyX实现各种有趣的小游戏。

🌸相关专栏推荐:C语言初阶系列C语言进阶系列数据结构与算法

💐文章导读

本文主要内容为,利用图形库与简单的C语言知识实现樱花树。文章涉及的C语言语法并不多,但要求了解简单的递归运用。每一小节都会附有完整代码与实现效果图,有需求的小伙伴也可以直接去复制使用~

特别声明——本文内容与代码全部参考书籍《C和C++趣味游戏编程》,当然我也非常推荐这本书。

樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

绘制一根线条

  1. 初始化画板窗口;
  2. 设置画板背景颜色(白色);
  3. 绘制一个线条;
  4. 设置线条颜色(黑色);

2-1

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include<math.h>

#define WIDTH 800 // 画面宽度
#define HEIGHT 600 // 画面高度

int main()
{
	initgraph(WIDTH, HEIGHT); // 初始化窗口
	setbkcolor(RGB(225, 225, 225)); //白色背景

	setlinecolor(RGB(0, 0, 0)); // 设定线条颜色为黑色
	setlinestyle(PS_SOLID, 3);  // 设定线宽

	cleardevice(); // 清屏

	BeginBatchDraw(); // 开始批量绘制

	line(WIDTH / 2, HEIGHT, WIDTH / 2,  150); //绘制线条
	
	FlushBatchDraw(); // 刷新画板
	_getch(); // 等待输入
	closegraph(); // 关闭画板
	return 0;
}

效果图
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

绘制一个简易的树干

  1. 使用函数递归来完成树干的绘制;
  2. 利用三角函数来改变每根线条的倾斜度;

2-2

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include<math.h>

#define PI 3.1415926 // 圆周率
#define WIDTH 800 // 画面宽度
#define HEIGHT 600 // 画面高度

// 绘制树干的函数
void branch(float x_start, float y_start, float angle, int generation)
{
	// 利用三角函数求出当前树枝的终点坐标
	float x_end, y_end;
	x_end = x_start + 150 * cos(angle);
	y_end = y_start + 150 * sin(angle);

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

	// 求出子枝干的代数
	int childGeneration = generation + 1;
	
	// 当子枝干的代数<=4,画出当前枝干,并递归调用产生子枝干
	if (childGeneration <= 4)
	{
		// 产生左右的子枝干
		branch(x_end, y_end,angle+PI/6,childGeneration);
		branch(x_end, y_end, angle - PI / 6, childGeneration);

	}
}

int main()
{
	initgraph(WIDTH, HEIGHT); // 初始化窗口
	setbkcolor(RGB(225, 225, 225)); // 白色背景

	setlinecolor(RGB(0, 0, 0)); // 设定线条颜色为黑色
	setlinestyle(PS_SOLID, 3);  // 设定线宽

	cleardevice(); // 清屏

	BeginBatchDraw(); // 开始批量绘制

	branch(WIDTH/2,HEIGHT,-PI/2,1); // 递归绘图

	FlushBatchDraw();
	_getch();
	closegraph();
	return 0;
}

效果图
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

优化树干,使其更加细致

  1. 使用比例来控制父枝干与子枝干的长度;
  2. 控制父枝干与子枝干的夹角变化;

2-3

#define PI 3.1415926 // 圆周率
#define WIDTH 800 // 画面宽度
#define HEIGHT 600 // 画面高度
float offsetAngle = PI / 6; // 左右枝干与父枝干偏离的角度
float shortenRate = 0.65; // 左右枝干长度与父枝干长度的比例


void branch(float x_start, float y_start, float length,float angle,float thickness, int generation)
{
	// 利用三角函数求出当前树枝的终点坐标
	float x_end, y_end;
	x_end = x_start + length * cos(angle);
	y_end = y_start + length * sin(angle);

	setlinestyle(PS_SOLID, thickness); //设置当前枝干的宽

	setlinecolor(RGB(0, 0, 0)); // 设置当前枝干的颜色

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

	// 求出子枝干的代数
	int childGeneration = generation + 1;
	
	float childLength = shortenRate * length; // 生成的枝干的长度逐渐变短


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

		if (childThickness < 2)
		{
			childThickness = 2;
		}
		// 产生左右的子枝干
		branch(x_end, y_end, childLength, angle + offsetAngle, childThickness, childGeneration);
		branch(x_end, y_end, childLength, angle - offsetAngle, childThickness, childGeneration);
	}
}

int main()
{
	initgraph(WIDTH, HEIGHT); // 初始化窗口
	setbkcolor(RGB(225, 225, 225)); //白色背景

	setlinecolor(RGB(0, 0, 0)); //设定线条颜色为黑色
	setlinestyle(PS_SOLID, 3);  //设定线宽

	cleardevice(); // 清屏

	BeginBatchDraw(); // 开始批量绘制

	branch(WIDTH/2,HEIGHT,0.45*HEIGHT*shortenRate,-PI/2, 15 * shortenRate, 1); // 递归绘图

	FlushBatchDraw();
	_getch();
	closegraph();
	return 0;
}

樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

绘制樱花树

  1. 修改树干颜色为褐色;
  2. 为末端的树干添上樱花(实际为粉色的小圆);

2-4

#define PI 3.1415926 // 圆周率
#define WIDTH 800 // 画面宽度
#define HEIGHT 600 // 画面高度
float offsetAngle = PI / 6; // 左右枝干与父枝干偏离的角度
float shortenRate = 0.65; // 左右枝干长度与父枝干长度的比例


// 枝干生成和绘制递归函数
// 输入参数:枝干起始x y坐标,枝干长度,枝干角度,枝干绘图线条宽度,第几代
void branch(float x_start, float y_start, float length, float angle, float thickness, int generation)
{
	// 利用三角函数求出当前枝干的终点x,y坐标
	float x_end, y_end;
	x_end = x_start + length * cos(angle);
	y_end = y_start + length * sin(angle);
	setlinestyle(PS_SOLID, thickness); // 设定当前枝干线宽
	setlinecolor(HSVtoRGB(15, 0.75, 0.5)); // 设定当前枝干颜色为褐色
	line(x_start, y_start, x_end, y_end); // 画出当前枝干

	// 求出子枝干的代数
	int childGeneration = generation + 1;
	// 生成子枝干的长度,逐渐变短
	float childLength = shortenRate * length;

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

		// 产生左右的子枝干
		branch(x_end, y_end, childLength, angle + offsetAngle, childThickness, childGeneration);
		branch(x_end, y_end, childLength, angle - offsetAngle, childThickness, childGeneration);
		// 产生中间的子枝干
		branch(x_end, y_end, childLength, angle, childThickness, childGeneration);
	}
	else  // 画出最末端的樱花
	{
		setlinestyle(PS_SOLID, 1); // 线宽
		setlinecolor(HSVtoRGB(325, 0.3, 1)); // 设定线条颜色 粉色
		setfillcolor(HSVtoRGB(325, 0.3, 1)); // 设定填充颜色 粉色
		if (childLength <= 4) // 如果子枝干长度小于等于4
			fillcircle(x_end, y_end, 2); // 圆的半径为2(再小就看不清了)
		else
			fillcircle(x_end, y_end, childLength / 2); // 画一个圆,半径为子枝干长度的一半
	}
}

int main()
{
	initgraph(WIDTH, HEIGHT); // 初始化窗口
	setbkcolor(RGB(225, 225, 225)); //白色背景

	setlinecolor(RGB(0, 0, 0)); // 设定线条颜色为黑色
	setlinestyle(PS_SOLID, 3);  // 设定线宽

	cleardevice(); // 清屏
	BeginBatchDraw(); // 开始批量绘制

	branch(WIDTH/2,HEIGHT,0.45*HEIGHT*shortenRate,-PI/2, 15 * shortenRate, 1); // 递归绘图

	FlushBatchDraw();
	_getch();
	closegraph();
	return 0;
}

效果图
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

增加随机树形与渐变色效果

将樱花树的各个参数修改为随机数,生成各种形态不同的樱花树;

  1. 控制树干的颜色渐变(越往上枝干越亮);
  2. 设置花瓣的随机颜色;
  3. 控制树干的长度与比例具有随机性;

如何设置随机数

  • 使用rand函数来生成随机数;
  • 定义mapvalue函数来将生成的随机数映射到某一区间;
float mapValue(float input, float inputMin, float inputMax, float outputMin, float outputMax)
{
	float output;
	if (abs((float)(input - inputMin) < 0.000001)) // 防止除以零的bug
		output = outputMin;
	else
		output = (input - inputMin) * (outputMax - outputMin) / (inputMax - inputMin) + outputMin;
	return output;
}

// 生成[min,max]之间的随机小数
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;
}

2-5

#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include<math.h>
#include <time.h>

#define  PI 3.1415926
#define  WIDTH 800   // 画面宽度
#define  HEIGHT 600  // 画面高度度

float offsetAngle = PI / 6; // 左右枝干和父枝干偏离的角度
float shortenRate = 0.65;  // 子枝干比父枝干变短的倍数

// 把[inputMin,inputMax]范围的input变量,映射为[outputMin,outputMax]范围的output变量
float mapValue(float input, float inputMin, float inputMax, float outputMin, float outputMax)
{
	float output;
	if (abs((float)(input - inputMin) < 0.000001)) // 防止除以零的bug
		output = outputMin;
	else
		output = (input - inputMin) * (outputMax - outputMin) / (inputMax - inputMin) + outputMin;
	return output;
}

// 生成[min,max]之间的随机小数
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;
}

// 枝干生成和绘制递归函数
// 输入参数:枝干起始x y坐标,枝干长度,枝干角度,枝干绘图线条宽度,第几代
void branch(float x_start, float y_start, float length, float angle, float thickness, int generation)
{
	// 利用三角函数求出当前枝干的终点x,y坐标
	float x_end, y_end;
	x_end = x_start + length * cos(angle);
	y_end = y_start + length * sin(angle);

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

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

	// 求出子枝干的代数
	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);

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

		// 一定概率产生左、右、中子枝干
		if (randBetween(0, 1) < 0.95)
			branch(x_end, y_end, leftChildLength, angle + offsetAngle * randBetween(0.5, 1), childThickness, childGeneration);
		if (randBetween(0, 1) < 0.95)
			branch(x_end, y_end, rightChildLength, angle - offsetAngle * randBetween(0.5, 1), childThickness, childGeneration);
		if (randBetween(0, 1) < 0.85)
			branch(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); // 画一个圆,半径为子枝干长度的一半
	}
}

void startup()  // 初始化
{
	srand(time(0)); // 随机初始化
	initgraph(WIDTH, HEIGHT); // 新开一个画面
	setbkcolor(RGB(255, 255, 255)); // 白色背景
	cleardevice(); // 清屏
	BeginBatchDraw(); // 开始批量绘制
	brunch(WIDTH / 2, HEIGHT, 0.45 * HEIGHT * shortenRate, -PI / 2, 15 * shortenRate, 1); // 递归函数调用
	FlushBatchDraw(); // 批量绘制
}

void update()  // 每帧更新
{
	offsetAngle = randBetween(PI/10,PI/6);
	shortenRate = randBetween(0.7, 0.3);

	cleardevice(); // 清屏
	branch(WIDTH / 2, HEIGHT, 0.45 * HEIGHT * shortenRate, -PI / 2, 15 * shortenRate, 1); // 递归调用
}

int main() // 主函数
{
	startup();  // 初始化 	
	while (1)  // 重复循环
		update();  // 每帧更新
	return 0;
}

效果图
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

进阶——通过鼠标点击来控制生成樱花树

2-5版本缺点在于每次运行程序只能生成一棵樱花树。我们还可以引进鼠标点击的功能来实现每次鼠标点击生成不同的樱花树。

  • 检测鼠标是否发生移动,从而更新递归函数的参数;

2-6

if (m.uMsg == WM_MOUSEMOVE) // 当鼠标移动时,设定递归函数的参数
		{
			// 鼠标从左到右,左右子枝干偏离父枝干的角度逐渐变大
			offsetAngle = mapValue(m.x, 0, WIDTH, PI / 10, PI / 4);
			// 鼠标从上到下,子枝干比父枝干的长度缩短的更快
			shortenRate = mapValue(m.y, 0, HEIGHT, 0.7, 0.3);
		}
  • 检测鼠标是否发生点击动作,若点击则开始绘制;
f (m.uMsg == WM_LBUTTONDOWN) // 当鼠标左键点击时,以当前参数开始绘制一棵新数
		{
			cleardevice(); // 清屏
			branch(WIDTH / 2, HEIGHT, 0.45 * HEIGHT * shortenRate, -PI / 2, 15 * shortenRate, 1); // 递归调用
			FlushBatchDraw(); // 批量绘制
		}

效果图
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

进阶——生成樱花树并展示生长过程

  • 使用sleep函数与FlushBatchDraw将每次绘制的结果间隔一秒刷新,形成樱花树生长的动画。

2-7

void branch(float x_start, float y_start, float length, float angle, float thickness, int generation)
{
	//....

	if (isShowAnimation) // 如果为1,绘制樱花树生成的过程动画
	{
		FlushBatchDraw(); // 批量绘制
		Sleep(1); // 暂停
	}
}

效果图
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』

快去向你喜欢的人展示樱花树叭~
樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』
点击下方个人名片,可添加博主的个人QQ,交流会更方便哦~
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓文章来源地址https://www.toymoban.com/news/detail-418457.html

到了这里,关于樱花树盛开的季节,我用简单的C代码绘制了一棵樱花树向她表白~『C/C++&图形库EasyX』的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一个简单的Python樱花飘落动画代码

    以下是一个简单的Python樱花飘落动画代码示例: 这个示例代码将在控制台中显示一个樱花飘落的动画效果,使用了 ANSI Escape Codes 来控制颜色。请注意,这段代码可能在某些操作系统上无法正常运行,因为不同的操作系统支持的 ANSI Escape Codes 可能不同。

    2024年02月11日
    浏览(62)
  • Python爬去樱花动漫 超简单

    没事干,就像爬爬樱花动漫 一,观察网页 樱花动漫有国漫,日漫,欧美,港台等分区,他们的网址有略微不同,类似于这样。 国漫:https://www.yhdmwz.com/gcdm.html 日漫:https://www.yhdmwz.com/rhdm.html 每个分区下面不止一页动漫,每页动漫地址也不一样,拿国漫举例,第一页: https://www

    2023年04月09日
    浏览(48)
  • pythonturtle绘图代码樱花,如何用python画一朵樱花

    大家好,给大家分享一下python画樱花树代码如何读懂,很多人还不知道这一点。下面详细解释一下。现在让我们来看看! 最近在学习Python库turtle的用法,顺便也整理了几个用turtle库画的图形,具体如下PYTHON库“IMITATION”。 1. 引用 turtle库 2. 常用的基础函数 (1)绘制状态的函

    2024年02月04日
    浏览(51)
  • html、css、javascript简单三剑客实现樱花飘落\雪花飘落特效汇总

    素材来源于网络稍作修改 侵删 如果觉得复制下面运行有问题或者嫌麻烦 可以直接下载源代码 欢迎fork、star 预览 话不多说,直接上代码 预览 预览

    2024年02月14日
    浏览(72)
  • 前端开发必备技能!用简单CSS代码绘制三角形,提升用户体验

        🎬 江城开朗的豌豆 :个人主页  🔥 个人专栏  :《 VUE 》 《 javaScript 》  📝  个人网站  :《 江城开朗的豌豆🫛 》  ⛺️ 生活的理想,就是为了理想的生活 ! 目录  ⭐  专栏简介  📘  文章引言 一、前言 二、实现过程 三、原理分析 ⭐  写在最后         欢

    2024年02月07日
    浏览(52)
  • C语言 switch语句详细讲解 简单计算器及PTA例题季节判断,今天星期几-1(switch语句实现), 数据按需处理

    (1) 当被测试的变量等于 case 中的常量时,case 后跟的语句将被执行,直到遇到  break  语句为止。 (2)不是每一个 case 都需要包含  break 。如果 case 语句不包含  break ,控制流将会  继续  后续的 case,直到遇到 break 为止。 (3) 上面所有 case 都无法判断结果时,可用 default 代替

    2024年02月05日
    浏览(66)
  • 经纬度坐标为中心点生成米距离长度半径的圆形面,含java js源码+在线绘制,代码简单零依赖

    目录 java版源码 js版源码 在线绘制预览效果 关于计算的精确度 前些时间在更新我的坐标边界查询工具的时候,需要用到经纬度坐标点的距离计算,和以坐标点为中心生成一个指定距离为半径的圆,搜了一下没有找到现成简单又合适的代码,于是把自己压箱底的代码翻出来了

    2024年02月08日
    浏览(56)
  • 我用nodejs和electron实现了一个简单的聊天软件-----chat 开源

    🔗https://www.bilibili.com/video/BV1Fg4y1u76d/ 希望观众老爷给个免费的三连支持一下新人up主 翎 是基于 electron(vue2) 和 nodejs 实现的简单聊天软件,其中用 websocket 和 http 进行通讯传递,数据库使用了 mysql 数据库,该项目功能简单,界面简洁,适合正在练习 websocket 和 vue 的小白查看代码,代码

    2024年02月12日
    浏览(76)
  • 因为懒,我用了“低代码”打下手

    一、前言 二、工具介绍 三、平台特点 四、如何使用JNPF? 五、低代码平台的选择参考 六、总结 「一个优秀的开发者,一定是会利用各种工具来提升自己的开发效率。」 前段时间,体验了很多国内前沿的低代码平台,在csdn上也看到很多优秀的低代码平台文章分享,自己尝试

    2024年02月09日
    浏览(103)
  • 七夕节,我用代码制作了表白信封

    大家好,我是小周,明天就是七夕了,这么浪漫的节日,自然少不了我这个浪漫博主,本次为大家贡献表白信封的制作,其他的就看缘分啦,哈哈,最后会放上资源包,需要的小伙伴自取就可以了,999 https://excalidraw.com/ 使用上面的画图工具,手绘信封,可自己发挥,工具上手

    2024年02月21日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包