文章目录
系列文章
序号 | 直达链接 |
1 | C/C++爱心代码 |
2 | C/C++跳动的爱心 |
3 | C/C++李峋同款跳动的爱心代码 |
4 | C/C++满屏飘字表白代码 |
5 | C/C++大雪纷飞代码 |
6 | C/C++烟花代码 |
7 | C/C++黑客帝国同款字母雨 |
8 | C/C++樱花树代码 |
9 | C/C++奥特曼代码 |
10 | C/C++精美圣诞树 |
11 | C/C++俄罗斯方块 |
12 | C/C++贪吃蛇 |
13 | C/C++孤单又灿烂的神-鬼怪 |
14 | C/C++闪烁的爱心 |
15 | C/C++哆啦A梦 |
16 | C/C++简单圣诞树 |
17 | C/C++小宇宙 |
18 | C/C++冰墩墩 |
19 | C/C++七彩花朵 |
20 | C/C++玫瑰花 |
21 | C/C++小猪佩奇 |
22 | C/C++简易爱心 |
写在前面
C/C++语言实现李峋同款跳动的爱心完整代码。
首先,我们需要知道C++作为一种高级编程语言,拥有强大的功能和灵活的语法,非常适合用来制作各种有趣的动画效果。而跳动的爱心,正是一种既简单又富有创意的动画效果,非常适合用来作为编程初学者的练习项目。要实现这个效果,我们需要用到C++的图形库和定时器功能。图形库可以帮助我们在控制台或窗口中绘制出爱心的形状,而定时器则可以让爱心以一定的频率跳动起来。
技术需求
图形库(Graphics Library):利用
graphics.h
提供的图形功能绘制点、圆形、文字等元素。通过setfillcolor
、solidcircle
和outtextxy
等函数精确控制图形的颜色、形状和位置。数学运算与公式:代码采用数学公式生成心形曲线的点坐标,特别是结合
sin
和cos
函数及参数方程绘制心形曲线。同时使用sqrt(pow(x, 2) + pow(y, 2))
计算点间距离,有效处理点的关系。随机数生成:使用
rand()
函数生成随机数,随机化图形的颜色、大小和位置,增强动画效果的动感和变化性。随机数还用于决定每个点是否生成,增加视觉趣味性。动画生成:通过逐帧生成图像并利用
saveimage
和loadimage
函数保存加载每一帧,实现流畅的动画效果。每帧点的位置随时间变化,形成动态视觉效果。图像处理:通过
setorigin
和setaspectratio
调整图形坐标系,确保图形适应不同屏幕分辨率和显示效果,提升视觉体验。文本绘制:使用
outtextxy
将文本如“我爱你”绘制到图形上,增强表现力和情感表达。内存与性能管理:通过
images[frame]
数组存储每一帧图像数据,确保独立处理和保存每一帧,优化内存使用和性能表现。
环境搭建
环境:C/C++
软件:Visual Studio 2022
- EasyX简介
EasyX 是专为 C++ 初学者和爱好者设计的图形库,以简洁易用、功能实用为目标,封装了 Windows GDI 接口,显著降低了 C++ 图形界面设计的复杂度,便于快速实现各类图形图像处理任务。
EasyX 提供丰富的 API,涵盖基本图形绘制(线段、圆形、矩形等)、填充、文本显示、图片加载保存、颜色设置及鼠标键盘事件处理。简单函数调用即可高效进行 2D 图形绘制和交互式程序设计。
总之,EasyX 以其友好的学习曲线和高效的图形处理能力,激发 C++ 初学者对计算机图形学的兴趣,广泛应用于编程入门和教育领域。
- EasyX 下载安装
- 访问 EasyX 官网,点击下载按钮开始下载。
- 下载完成后进入目录,双击
.exe
文件完成安装。
接下来,逐步实现跳动爱心。首先,通过数学公式定义爱心形状,如使用参数方程描述轮廓。然后,使用 C++ 图形库绘制形状。绘制完成后,利用 C++ 定时器功能设置时间间隔,让爱心在每个间隔内改变位置或大小,产生连贯的跳动效果。
完整代码
#include <graphics.h>
#include <conio.h>
#include <ctime>
#include <cmath>
#include <cstdlib>
struct Point {
double x, y;
COLORREF color;
};
const int MAX_POINTS = 256;
const COLORREF colors[MAX_POINTS] = {
RGB(255, 192, 203), // 浅粉色 (Light Pink)
RGB(255, 182, 193), // 淡粉红 (LightPink)
RGB(255, 105, 180), // 热粉红 (HotPink)
RGB(255, 20, 147), // 深粉色 (DeepPink)
RGB(219, 112, 147), // 浓粉红 (PaleVioletRed)
RGB(255, 174, 185), // 浅玫瑰红 (LightPink)
RGB(255, 0, 144) // 紫红色 (Crimson)
};
const int xScreen = GetSystemMetrics(SM_CXSCREEN);
const int yScreen = GetSystemMetrics(SM_CYSCREEN) - 100;
const double PI = 3.14159265359;
const double E = 2.71828;
const double AVG_DISTANCE = 0.162;
const int NUM_ORIGIN_POINTS = 506;
const int NUM_CIRCLES = 210;
const int NUM_FRAMES = 20;
const int COLOR_RANGE = 6;
Point origin_points[NUM_ORIGIN_POINTS];
Point points[NUM_CIRCLES * NUM_ORIGIN_POINTS];
IMAGE images[NUM_FRAMES];
int create_random(int min, int max) {
return rand() % (max - min + 1) + min;
}
void create_data() {
int index = 0;
double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
// Generate origin points
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 > AVG_DISTANCE) {
x1 = x2, y1 = y2;
origin_points[index].x = x2;
origin_points[index++].y = y2;
}
}
// Generate points
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 < NUM_ORIGIN_POINTS; ++i) {
if (success_p > create_random(0, 100) / 100.0) {
COLORREF color = colors[create_random(0, COLOR_RANGE)];
points[index].color = RGB(GetRValue(color) / lightness, GetGValue(color) / lightness, GetBValue(color) / lightness);
points[index].x = size * origin_points[i].x + create_random(-4, 4);
points[index++].y = size * origin_points[i].y + create_random(-4, 4);
}
}
}
int points_size = index;
// Generate images
for (int frame = 0; frame < NUM_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 distance_increase = -0.0009 * distance * distance + 0.35714 * distance + 5;
double x_increase = distance_increase * x / distance / NUM_FRAMES;
double y_increase = distance_increase * y / distance / NUM_FRAMES;
points[index].x += x_increase;
points[index].y += y_increase;
setfillcolor(points[index].color);
solidcircle(points[index].x, points[index].y, 1);
}
……
代码分析
这段代码利用 C++ 中的图形库生成一系列基于爱心形状图案的动画图像。以下将详细解析代码的各个部分,包括结构体定义、常量声明、函数实现和程序执行流程。
1. 引用的头文件
#include <graphics.h>
#include <conio.h>
#include <ctime>
#include <cmath>
#include <cstdlib>
graphics.h
:提供绘制图形和图像的功能。conio.h
:包含_kbhit()
等控制台输入输出功能。ctime
:用于获取系统时间以生成随机数。cmath
:提供数学运算函数,如pow
和sqrt
。cstdlib
:用于生成随机数等操作。
2. 数据结构
struct Point {
double x, y;
COLORREF color;
};
定义了 Point
结构体,存储二维坐标点的 x
和 y
值及颜色属性。COLORREF
包含 RGB 颜色值。
3. 常量声明
const int MAX_POINTS = 256;
const COLORREF colors[MAX_POINTS] = {
RGB(255, 192, 203), RGB(255, 182, 193), RGB(255, 105, 180),
RGB(255, 20, 147), RGB(219, 112, 147), RGB(255, 174, 185), RGB(255, 0, 144)
};
const int xScreen = GetSystemMetrics(SM_CXSCREEN);
const int yScreen = GetSystemMetrics(SM_CYSCREEN) - 100;
const double PI = 3.14159265359;
const double E = 2.71828;
const double AVG_DISTANCE = 0.162;
const int NUM_ORIGIN_POINTS = 506;
const int NUM_CIRCLES = 210;
const int NUM_FRAMES = 20;
const int COLOR_RANGE = 6;
MAX_POINTS
:表示图像中最多可包含 256 个点。colors
:存储 7 种颜色的 RGB 值。xScreen
,yScreen
:获取屏幕尺寸并预留空间。PI
和E
:圆周率和自然常数。AVG_DISTANCE
:计算点间平均距离。NUM_ORIGIN_POINTS
:原始数据点数量。NUM_CIRCLES
:生成的圆形点数量。NUM_FRAMES
:动画帧数。COLOR_RANGE
:颜色选择范围。
4. 全局变量
Point origin_points[NUM_ORIGIN_POINTS];
Point points[NUM_CIRCLES * NUM_ORIGIN_POINTS];
IMAGE images[NUM_FRAMES];
origin_points
:存储原始点数据。points
:存储每个点的数据,包括坐标和颜色。images
:存储每一帧生成的图像。
5. 创建随机数的辅助函数
int create_random(int min, int max) {
return rand() % (max - min + 1) + min;
}
生成指定范围内的随机整数。
6. create_data()
函数
该函数是核心,负责生成原始点数据、计算点位置,并生成动画帧。
6.1 生成原始数据点
for (double radian = 0.1; radian <= 2 * PI; radian += 0.005) {
double x2 = 16 * pow(sin(radian), 3);
double 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 > AVG_DISTANCE) {
x1 = x2;
y1 = y2;
origin_points[index].x = x2;
origin_points[index++].y = y2;
}
}
使用参数方程生成心形曲线的原始数据点,通过遍历角度 radian
计算坐标,并过滤过于接近的点。
6.2 生成圆形点数据
通过变化 size
和 lightness
,生成不同大小和亮度的点,决定点是否生成,并随机设置颜色加入 points
数组。
6.3 生成动画帧
计算每个点的位置,绘制心形点,生成动态效果。
7. 总结
该代码实现了基于心形图案的动态生成动画,涉及数学公式、图形绘制和随机数生成等知识,通过逐帧绘制创建动画效果,修改颜色、位置和大小参数实现动态展示。
写在后面
我是一只有趣的兔子,感谢你的喜欢!