C/C++跳动的爱心

news/2025/2/23 10:40:31

系列文章

序号直达链接
1C/C++李峋同款跳动的爱心
2C/C++跳动的爱心
3C/C++经典爱心
4C/C++满屏飘字
5C/C++大雪纷飞
6C/C++炫酷烟花
7C/C++黑客帝国同款字母雨
8C/C++樱花树
9C/C++奥特曼
10C/C++精美圣诞树
11C/C++俄罗斯方块小游戏
12C/C++贪吃蛇小游戏
13C/C++孤单又灿烂的神
14C/C++闪烁的爱心
15C/C++哆啦A梦
16C/C++简单圣诞树
17C/C++小宇宙
18C/C++冰墩墩
19C/C++七彩花朵
20C/C++玫瑰花
21C/C++小猪佩奇
22C/C++简易爱心
23C/C++流星雨
24C/C++2048小游戏
25C/C++爱心圣诞树
26C/C++文字跑马灯
27C/C++教师工作量管理系统
28C/C++满天繁星
29C/C++漂浮爱心
30C/C++五子棋小游戏
31C/C++球球大作战小游戏
32C/C++走迷宫小游戏
33C/C++粉色爱心
34C/C++跨年烟花
35C/C++棕色小熊
36C/C++粉色动态爱心
37C/C++新春烟花
敬请期待……

写在前面

C/C++语言实现李峋同款跳动的爱心完整代码。

首先,我们需要知道C++作为一种高级编程语言,拥有强大的功能和灵活的语法,非常适合用来制作各种有趣的动画效果。而跳动的爱心,正是一种既简单又富有创意的动画效果,非常适合用来作为编程初学者的练习项目。要实现这个效果,我们需要用到C++的图形库和定时器功能。图形库可以帮助我们在控制台或窗口中绘制出爱心的形状,而定时器则可以让爱心以一定的频率跳动起来。

技术需求

  1. 图形库(Graphics Library):使用 graphics.h 提供的图形功能来绘制点、圆形、文字等图形元素。通过 setfillcolorsolidcircleouttextxy 等函数来控制图形的颜色、形状和位置。

  2. 数学运算与公式:代码使用了数学公式生成心形曲线的点坐标。特别是通过 sincos 函数,结合参数方程绘制心形曲线。同时使用了距离计算公式 sqrt(pow(x, 2) + pow(y, 2)) 来处理点之间的关系。

  3. 随机数生成:通过 rand() 函数生成随机数,用于随机化图形的颜色、大小、位置等,使得动画效果更具动感和变化性。随机数还被用来控制每个点是否生成。

  4. 动画生成:通过逐帧生成图像,利用 saveimageloadimage 函数保存并加载每一帧图像,实现动画效果。每帧的点位置随着时间变化,形成动态效果。

  5. 图像处理:利用 setoriginsetaspectratio 等函数调整图形坐标系,使得图形能适应不同的屏幕分辨率和显示效果。

  6. 文本绘制:使用 outtextxy 函数将文本绘制到图形上,这里用来显示"我爱你"等信息,增强图形的表现力。

  7. 内存与性能管理:通过存储每一帧的图像,使用 images[frame] 数组来管理图像数据,确保每一帧能够被独立处理和保存。

环境搭建

环境:C/C++

软件:Visual Studio 2022

安装教程:C语言环境搭建教程(Visual Studio)

1. EasyX是什么

EasyX是一个专为C++初学者和爱好者设计的图形库。该库以简洁易用、功能实用为宗旨,通过封装Windows GDI接口,极大降低了C++编程中图形界面设计的复杂度,使得用户能够快速上手并实现各类图形图像处理任务。

EasyX提供了一系列丰富的API函数,涵盖了绘制基本图形(如线段、圆形、矩形等)、填充图形、显示文本、加载与保存图片、颜色设置以及鼠标键盘事件处理等功能。通过简单的函数调用,开发者可以高效地进行2D图形绘制和交互式程序设计。

总的来说,EasyX以其友好的学习曲线和高效的图形处理能力,极大地激发了C++初学者对计算机图形学的兴趣,是广大编程入门者和教育领域广泛采用的一款图形库工具。

2. 下载安装EasyX

1.进入EasyX官网,点击下载按钮开始下载

2.下载完成后进入下载目录,双击.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++ 中的图形库(可能是 Turbo C++ 图形库)来生成一系列动画图像,并展示一个基于爱心形状的图案。下面将详细分析该代码的各个部分,包括结构体定义、常量声明、函数实现和程序的执行流程。

1. 引用的头文件

#include <graphics.h>
#include <conio.h>
#include <ctime>
#include <cmath>
#include <cstdlib>
  • graphics.h:是 C++ 中的图形处理库,提供了用于绘制图形和图像的函数。
  • conio.h:用于控制台输入输出,包括 _kbhit()(检测是否有按键输入)等功能。
  • ctime:用于获取系统时间,主要用于生成随机数。
  • cmath:提供数学运算函数,如 powsqrt 等。
  • cstdlib:用于生成随机数等操作。

2. 数据结构

struct Point {
    double x, y;
    COLORREF color;
};

定义了一个 Point 结构体,用来存储二维坐标点的 xy 值,以及一个 color 属性,代表该点的颜色。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:获取屏幕的宽度和高度,并为绘制图像留出一些空间。
  • PIE:圆周率和自然常数。
  • 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;
}

这个函数用来生成一个指定范围内的随机整数。通过 rand() 函数生成一个随机数,然后通过模运算限制其在给定的区间内。

6. create_data() 函数

该函数是整个程序的核心,负责生成原始点数据、计算点的位置,并生成动画的帧。

6.1 生成原始数据点

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;
    }
}

这段代码生成了一个心形曲线的原始数据点,使用了 parametric equations 来绘制心形。通过遍历角度 radian,计算 x2y2 的坐标,并根据距离过滤掉过于接近的点。

6.2 生成圆形点数据

这一部分通过变化 sizelightness,生成了不同大小、不同亮度的点。通过 success_p 来决定点是否应当被生成,最终生成的点被随机设置颜色,并加入到 points 数组中。

6.3 生成动画帧

这一段代码是核心部分,负责绘制和动画生成。

通过计算每个点的位置,绘制心形的各个点,并生成动态的效果。

7. 总结

这段代码实现了一个基于心形图案的动态生成动画,涉及到数学公式、图形绘制、随机数生成等多个方面的知识。它通过逐帧绘制来创建动画效果,并通过修改颜色、位置、大小等参数来实现动态展示。

写在后面

我是一只有趣的兔子,感谢你的喜欢!


http://www.niftyadmin.cn/n/5863332.html

相关文章

MySQL要点总结一

大纲 一.InnoDB的内存结构和更新机制 二.InnoDB的存储模型 三.并发事务原理 四.索引原理和索引优化 一.InnoDB的内存模型 1.SQL的执行流程 2.InnoDB的内存模型 3.Buffer Pool中的空闲缓存页与free链表 4.Buffer Pool中的脏页和flush链表 5.Buffer Pool通过LRU链表来淘…

antv G6绘制流程图

效果图&#xff08;优点&#xff1a;可以自定义每一条折线的颜色&#xff0c;可以自定义节点的颜色&#xff0c;以及折线的计算样式等&#xff09;&#xff1a; 代码&#xff1a; <!-- 流程图组件 --> <template><div id"container"></div>…

前端面试-JavaScript 数据类型详解

目录 一、数据类型分类 二、核心区别对比 1. 存储方式 2. 比较方式 3. 类型检测方法 三、特殊类型详解 1. Symbol 2. BigInt 3. null vs undefined 四、常见面试扩展问题 五、总结 一、数据类型分类 JavaScript 数据类型分为 基本数据类型&#xff08;原始类型&…

hot100_74. 搜索二维矩阵

hot100_74. 搜索二维矩阵 思路 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否…

网络空间安全(2)应用程序安全

前言 应用程序安全&#xff08;Application Security&#xff0c;简称AppSec&#xff09;是一个综合性的概念&#xff0c;它涵盖了应用程序从开发到部署&#xff0c;再到后续维护的整个过程中的安全措施。 一、定义与重要性 定义&#xff1a;应用程序安全是指识别和修复应用程序…

二级公共基础之数据结构与算法篇(五)树和二叉树

目录 前言 一、树的基本概念 1.父结点和根节点 2.子节点和叶子节点 3.度和深度 4.子树 二、二叉树及其基本性质 1. 二叉树的定义 2. 二叉树的基本性质 性质1 性质2 性质3 性质4 性质5 性质6 三、二叉树的存储结构 四、二叉树的遍历 1.遍历二叉树的概念 1. 前…

基于ffmpeg+openGL ES实现的视频编辑工具-添加贴纸(八)

在当下丰富多元的音视频编辑应用领域,添加贴纸已然成为一项广受欢迎的功能,它能够为音视频作品注入独特的趣味与创意元素。本文将深入探究音视频添加贴纸背后所涉及的技术原理与实现路径。 一、技术原理概述 音视频从本质上来说,是由一系列连续的图像帧(针对视频部分)以…

排序链表--字节跳动

少年的书桌上没有虚度的光阴 题目描述 请你对链表进行排序 思路分析 核心思想&#xff1a;归并排序 有三个部分 链表排序实现 1. merge 函数 21.见 合并两个有序链表&#xff0c; 首先创建一个虚拟头节点 newhead&#xff0c;并使用指针 tail 来构建合并后的链表。 通过…