爱就要大胆说出来❤️💕💕💕😍

129 阅读5分钟

今天咱们来写一个会动且柔和又浪漫的一个爱心代码,学会了发给喜欢的女生看吧💕💕💕💕💕💕💕💕❤️❤️❤️❤️ image.png

需要源代码的可以关注主播后台私信噢!!!!!!!!👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈👈

#include<graphics.h>

#include <conio.h>

#include<time.h>

#include<math.h>

#include<stdlib.h>



struct Point {

	double x, y;

	COLORREF color;

};



COLORREF colors[256] = { RGB(255,32,83),RGB(252,222,250) ,RGB(255,0,0) ,RGB(255,0,0) ,RGB(255,2,2) ,RGB(255,0,8) ,RGB(255,5,5) };

const int xScreen = 1200;

const int yScreen = 800;

const double PI = 3.1426535159;

const double e = 2.71828;

const double averag_distance = 0.162;

const int quantity = 506;

const int circles = 210;

const int frames = 20;

Point origin_points[quantity];

Point points[circles * quantity];

IMAGE images[frames];



int creat_random(int x1, int x2)

{

	if (x2 > x1)

		return rand() % (x2 - x1 + 1) + x1;

}



void creat_data()

{

	int index = 0;

	double x1 = 0, y1 = 0, x2 = 0, y2 = 0;

	for (double radian = 0.1; radian <= 2 * PI; radian += 0.005)

	{

		x2 = 16 * pow(sin(radian), 3);

		y2 = 13 * cos(radian) - 5 * cos(2 * radian) - 2 * cos(3 * radian) - cos(4 * radian);



		double distance = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));

		if (distance > averag_distance)

		{

			x1 = x2, y1 = y2;

			origin_points[index].x = x2;

			origin_points[index++].y = y2;

		}

	}



	index = 0;

	for (double size = 0.1, lightness = 1.5; size <= 20; size += 0.1)

	{

		double success_p = 1 / (1 + pow(e, 8 - size / 2));

		if (lightness > 1) lightness -= 0.0025;



		for (int i = 0; i < quantity; ++i)

		{

			if (success_p > creat_random(0, 100) / 100.0)

			{

				COLORREF color = colors[creat_random(0, 6)];

				points[index].color = RGB(GetRValue(color) / lightness, GetGValue(color) / lightness, GetBValue(color) / lightness);

				points[index].x = size * origin_points[i].x + creat_random(-4, 4);

				points[index++].y = size * origin_points[i].y + creat_random(-4, 4);

			}

		}

	}



	int points_size = index;



	for (int frame = 0; frame < frames; ++frame)

	{

		images[frame] = IMAGE(xScreen, yScreen);

		SetWorkingImage(&images[frame]);

		setorigin(xScreen / 2, yScreen / 2);

		setaspectratio(1, -1);



		for (index = 0; index < points_size; ++index)

		{

			double x = points[index].x, y = points[index].y;

			double distance = sqrt(pow(x, 2) + pow(y, 2));

			double diatance_increase = -0.0009 * distance * distance + 0.35714 * distance + 5;

			double x_increase = diatance_increase * x / distance / frames;

			double y_increase = diatance_increase * y / distance / frames;



			points[index].x += x_increase;

			points[index].y += y_increase;



			setfillcolor(points[index].color);

			solidcircle(points[index].x, points[index].y, 1);

		}



		for (double size = 17; size < 23; size += 0.3)

		{

			for (index = 0; index < quantity; ++index)

			{

				if ((creat_random(0, 100) / 100.0 > 0.6 && size >= 20) || (size < 20 && creat_random(0, 100) / 100.0 > 0.95))

				{

					double x, y;

					if (size >= 20)

					{

						x = origin_points[index].x * size + creat_random(-frame * frame / 5 - 15, frame * frame / 5 + 15);

						y = origin_points[index].y * size + creat_random(-frame * frame / 5 - 15, frame * frame / 5 + 15);

					}

					else

					{

						x = origin_points[index].x * size + creat_random(-5, 5);

						y = origin_points[index].y * size + creat_random(-5, 5);

					}



					setfillcolor(colors[creat_random(0, 6)]);

					solidcircle(x, y, 1);

				}

			}

		}



		saveimage(_T("缓存.png"), &images[frame]);

		setorigin(0, 0);

		setaspectratio(1, 1);

		loadimage(&images[frame], _T("缓存.png"));

	}

	SetWorkingImage();

}



void init()

{

	HWND hwnd = initgraph(xScreen, yScreen);

	SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & (!WS_CAPTION));

	SetWindowPos(hwnd, HWND_TOP, 0, 0, xScreen, yScreen, SWP_SHOWWINDOW);

	BeginBatchDraw();

	setorigin(xScreen / 2, yScreen / 2);

	setaspectratio(1, -1);

	srand(time(0));

}



int main()

{

	init();

	creat_data();

	graphdefaults();



	bool extend = true, shrink = false;

	for (int frame = 0; !_kbhit();)

	{

		putimage(0, 0, &images[frame]);

		FlushBatchDraw();

		Sleep(20);

		cleardevice();



		if (extend)

			frame == 19 ? (shrink = true, extend = false) : ++frame;

		else

			frame == 0 ? (shrink = false, extend = true) : --frame;

	}

	EndBatchDraw();

	closegraph();

	return 0;

}


这段代码是一个基于 EasyX 图形库的 动态爱心粒子动画程序,运行后会呈现以下核心效果:

一、整体视觉效果

屏幕中央会出现一个由大量彩色粒子组成的 动态爱心图案,核心效果是:

  1. 爱心从微小状态 逐渐扩大(扩散) ,粒子随之向外发散;
  2. 扩大到最大后 反向缩小(收缩) ,粒子向内汇聚;
  3. 扩散 - 收缩过程循环往复,直到按下任意键盘键退出;
  4. 粒子带有随机色彩(粉色、红色系为主),部分粒子有轻微随机偏移,呈现出 “粒子流” 的灵动质感。

二、关键细节拆解

1. 爱心形状的生成

  • 代码通过 笛卡尔心形方程 生成基础爱心轮廓:

    c

    运行

    x = 16*sin³θ, y = 13cosθ - 5cos2θ - 2cos3θ - cos4θ
    
  • 对生成的轮廓点进行筛选(保证点间距均匀),得到 origin_points 数组,作为爱心的 “骨架点”。

2. 粒子的生成与变化

  • 基于爱心骨架点,生成大量粒子(points 数组):

    • 粒子大小从 0.1 逐步放大到 20,亮度随大小降低(lightness 递减),呈现 “外暗内亮” 的层次感;
    • 粒子颜色随机从粉色、红色系中选取(colors 数组定义);
    • 粒子位置带有轻微随机偏移(±4 像素),避免过于规整。

3. 动画帧的构建

  • 生成 20 帧动画(images 数组),每帧对应爱心的一个缩放状态:

    • 粒子随帧号逐渐向外扩散(距离越远的粒子扩散速度越快,通过二次函数 diatance_increase 控制);
    • 后期(大小 17~23)会额外生成随机粒子,增加 “炸开” 的视觉效果(偏移量随帧号增大,模拟扩散混乱度);
    • 每帧图像保存为缓存后重新加载,确保坐标体系正确。

4. 交互与循环

  • 程序运行后自动循环播放 20 帧动画:从第 0 帧(最小)到第 19 帧(最大)是 “扩散”,再从 19 帧退回 0 帧是 “收缩”;
  • 按下任意键盘键,动画停止并退出程序;
  • 窗口无标题栏(WS_CAPTION 屏蔽),全屏居中显示(1200×800 分辨率)。

三、运行注意事项

  1. 必须安装 EasyX 图形库(支持 graphics.hIMAGEsolidcircle 等接口),否则无法编译;
  2. 运行时会生成临时文件 缓存.png,结束后可手动删除;
  3. 动画帧率约 50 FPS(Sleep(20)),流畅度依赖设备性能;
  4. 粒子数量较多(最多 circles*quantity=210×506≈10.6 万),低配置设备可能卡顿。

四、最终呈现总结

一个 色彩柔和、动态流畅的爱心粒子动画:爱心从中心 “生长” 扩散,到最大时轻微 “炸开”,再反向收缩回中心,循环往复,适合作为浪漫主题的可视化效果(如情人节、表白相关场景)。