C/C++李峋同款跳动的爱心代码

一、写在前面

在编程的世界里,代码不仅仅是冷冰冰的命令,它也可以成为表达情感、传递浪漫的工具。今天,就让小编带着大家用C++语言打造出李峋同款跳动的爱心吧!

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

环境需求

环境:C/C++

软件:Visual Studio 2022

安装教程:https://want595.blog.csdn.net/article/details/134608094

EasyX是什么

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

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

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

下载安装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);
        }

        for (double size = 17; size < 23; size += 0.3) {
            for (index = 0; index < NUM_ORIGIN_POINTS; ++index) {
                if ((create_random(0, 100) / 100.0 > 0.6 && size >= 20) || (size < 20 && create_random(0, 100) / 100.0 > 0.95)) {
                    double x, y;
                    if (size >= 20) {
                        x = origin_points[index].x * size + create_random(-frame * frame / 5 - 15, frame * frame / 5 + 15);
                        y = origin_points[index].y * size + create_random(-frame * frame / 5 - 15, frame * frame / 5 + 15);
                    }
                    else {
                        x = origin_points[index].x * size + create_random(-5, 5);
                        y = origin_points[index].y * size + create_random(-5, 5);
                    }
                    setfillcolor(colors[create_random(0, COLOR_RANGE)]);
                    solidcircle(x, y, 1);
                }
            }
        }

        setaspectratio(1, 1);
        settextstyle(100, 0, _T("宋体"));
        settextcolor(RGB(255, 182, 193));
        outtextxy(-150, -50, _T("我爱你"));

        saveimage(_T("爱心.png"), &images[frame]);
        setorigin(0, 0);
        setaspectratio(1, 1);
        loadimage(&images[frame], _T("爱心.png"));
    }
    SetWorkingImage();
}

void init_graphics() {
    HWND hwnd = initgraph(xScreen, yScreen);
    RECT rect;
    SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
    ShowWindow(hwnd, SW_MAXIMIZE);
    SetWindowPos(hwnd, HWND_TOP, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW);
    BeginBatchDraw();
    setorigin(xScreen / 2, yScreen / 2);
    setaspectratio(1, -1);
    srand(static_cast<unsigned>(time(0)));
}

int main() {
    init_graphics();
    create_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;
}

完成这些步骤后,我们就成功打造出了一个李峋同款跳动的爱心(在代码的第112行可以修改文字哦)。每当你运行这段代码时,这个爱心就会在屏幕上跳动起来,为你的编程之旅增添一份浪漫和乐趣。

代码分析

这段代码使用C语言和Turbo C++图形库来创建一个动态的心形图案动画。

1. 定义结构体和常量

  • Point 结构体包含点的坐标(x 和 y)以及颜色值(COLORREF)。
  • 预定义的颜色数组 colors[],包括多种粉红色调。
  • 屏幕尺寸 xScreen 和 yScreen 通过系统函数获取。
  • 数学常数 PI 和 E。
  • 其他常量如 MAX_POINTS,AVG_DISTANCE 等,用于控制生成点的数量和分布。

2. 随机数生成函数 create_random()

  • 返回指定范围内的随机整数。

3. 数据生成函数 create_data()

  • 生成 origin_points[]:这些点用于描绘心形的基本轮廓,通过参数方程计算得到。
  • 生成 points[]:这些点基于 origin_points[] 生成,通过缩放和随机偏移来形成心形的纹理。
  • 生成 images[]:这是一系列帧,每一帧都是在前一帧的基础上对点的位置进行微调,并添加新的点,最终保存为图像文件。

4. 图形初始化函数 init_graphics()

  • 初始化图形窗口,设置屏幕尺寸,并准备绘图环境。

5. 主函数 main()

  • 调用 init_graphics() 准备图形环境。
  • 调用 create_data() 生成动画数据。
  • 在循环中按顺序显示每一帧,实现动画效果,直到检测到键盘输入为止。

6. 动画的具体实现

  • 心形图案通过调整点的位置和大小随时间变化来产生脉动效果。
  • 随机添加新点以增强视觉效果。
  • 每一帧被保存为图像文件 ("爱心.png"),然后加载并显示,形成连续动画

由于代码中涉及到大量图形库特定的函数和概念,理解它们需要一定的图形编程基础,尤其是Turbo C++图形库。如果您对此不熟悉,我建议可以先从基本的图形编程概念入手,逐步学习和理解。

通过这个项目,我们不仅学会了如何使用C++语言制作动画效果,还学会了如何将情感融入到代码中。这让我们更加深刻地认识到,编程不仅仅是一种技能,更是一种表达自我、传递情感的方式。所以,无论你是编程初学者还是资深开发者,都不妨尝试一下用C++打造一款跳动的爱心吧!相信在这个过程中,你会收获到很多的乐趣。

运行效果

三、系列文章

序号目录直达链接
1爱心代码https://want595.blog.csdn.net/article/details/136360684
2李峋同款跳动的爱心https://want595.blog.csdn.net/article/details/139722249
3满屏飘字代码https://want595.blog.csdn.net/article/details/136342476
4大雪纷飞代码
5新春烟花代码
6《黑客帝国》代码雨

四、写在后面

感谢小伙伴们的支持,更多精彩内容等你发现喔~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/714099.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

常见的宽基指数基金

指数基金投资指南 ❝ 这篇博客里面的内容主要来自于银行螺丝钉的《定投十年&#xff0c;财务自由》和《指数基金投资指南》这两本书中章“常见的宽基指数”&#xff0c;最近第三次读这本书&#xff0c;打算做一点笔记加深自己的印象。 博客中很多内容是从书中摘抄的&#xff0c…

二十六、办公用品管理系统

随着计算机技术的迅猛发展,相关技术进入商业和社会应用阶段,设备的种类、数量越来越多,如何有效利用先进的互联网技术和日新月异的计算机设备来有效地收集、处理这些设备,建立以信息化为核心的管理体制,减轻管理人员和业务人员的数据处理负担,极大地提高设备管理效率和管…

Jmeter多个请求按照比例并发压测的几种方式

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、需求 在压测的过程中&#xff0c;为了能够压测整个链路&#xff0c;通常需要多个接口进行并…

HarmongOS打包[保姆级]

创建应用 首先进入 华为开发者联盟-HarmonyOS开发者官网 然后进行登录。 登录成功后&#xff0c;鼠标悬停在在登录右上角那个位置后再点击管理中心&#xff0c;进入下面这个界面。 再点击&#xff1a;应用服务–>应用发布–>新建–>完善信息 构建和生成私钥和证书请求…

SQL Server Management Studio (SSMS) 20.1 - 微软数据库管理工具

SQL Server Management Studio (SSMS) 20.1 - 微软数据库管理工具 请访问原文链接&#xff1a;https://sysin.org/blog/ssms/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 笔者注&#xff1a;SQL Server 2014 及之前版本内置…

[Linux] UDP协议介绍:UDP协议格式、端口号在网络协议栈那一层工作...

TCP/IP网络模型, 将网络分为了四层: 之前的文章中以HTTP和HTTPS这两个协议为代表, 简单介绍了应用层协议. 实际上, 无论是HTTP还是HTTPS等应用层协议, 都是在传输层协议的基础上实现的 而传输层协议中最具代表性的就是: UDP和TCP协议了. 以HTTP为例, 在使用HTTP协议通信之前, …

调度算法(SSTF,SCAN,CSCAN)c语言

假定当前磁头位于100号磁道&#xff0c;有9个进程先后提出了磁盘I/O请求&#xff1a;55 58 39 18 90 160 150 38 184&#xff0c;如果采用扫描算法或循环扫描算法&#xff0c;则磁头向磁道号增加的方向访问。 设计一个磁盘调度模拟系统&#xff0c;编程序演示下述算法的具体实…

线程池ThreadPoolExecutor源码分析

一、线程池基本概念和线程池前置知识 1.1 Java中创建线程的方式有哪些 传统答案&#xff1a; 继承Thread类 通过继承Thread类并重写其run方法来创建线程。具体步骤包括定义Thread类的子类&#xff0c;在子类中重写run方法以实现线程的具体逻辑&#xff0c;然后创建子类的实例…

举例说明 如何通过SparkUI和日志定位任务莫名失败?

有一个Task OOM&#xff1a; 通过概览信息&#xff0c;发现Stage 10的Task 36失败了4次导致Job失败。概览信息中显示最后一次失败的退出代码&#xff08;exit code&#xff09;是143&#xff0c;意味着发生了内存溢出&#xff08;OOM&#xff0c;即Out of Memory&#xff09;。…

QQ登录测试用例

QQ登录测试用例 常见测试方法&#xff08;可参考软件测试<用例篇>&#xff09; 等价类&#xff1a; 1、有效等价类 &#xff1a;满足需求的数据集合 2、无效等价类&#xff1a;不满足需求的数据集合 边界值错误猜测法场景法 QQ测试用例设计&#xff1a;xmind 需要完整…

C++ 55 之 多继承

#include <iostream> #include <string> using namespace std;class Base08_1{ public:int m_a;Base08_1(){this->m_a 10;} };class Base08_2{ public:// int m_b;int m_a;Base08_2(){// this->m_b 20;this->m_a 30;} };// 多继承 继承的类型都要…

九、BGP路由属性和选路

目录 一、属性分类 1.1、公认属性 1.2、可选属性 二、选路原则 0、丢弃不可达 取值越大越优 1、Preferred-Value 2、Local_Preference 取值越小越优 3、路由优先级 4、AS_Path 5、Origin 6、MED 7、路由来源 8、Next_Hop的IGP度量值 BGP路由等价负载分担&#…

流媒体传输协议HTTP-FLV、WebSocket-FLV、HTTP-TS 和 WebSocket-TS的详细介绍、应用场景及对比

一、前言 HTTP-FLV、WS-FLV、HTTP-TS 和 WS-TS 是针对 FLV 和 TS 格式视频流的不同传输方式。它们通过不同的协议实现视频流的传输&#xff0c;以满足不同的应用场景和需求。接下来我们对这些流媒体传输协议进行剖析。 二、传输协议 1、HTTP-FLV 介绍&#xff1a;基于 HTTP…

雷击保险丝选取

雷击保险丝的估算方法&#xff1a; 1、雷击浪涌实验规定的差模内阻是 2欧姆&#xff1a;(一般差模都是2欧姆) 2、差模雷击浪涌实验等级的确定。 3、差模雷击L-N防雷电路的确定&#xff08;估算防雷电路的钳位电压&#xff09;。 4、估算防雷电路中保险丝的 I^2t 的值来确定…

如何从索尼存储卡恢复数据?

Sony 存储卡广泛用于在数码相机、数码摄像机等中存储照片和视频。如果您从 Sony 存储卡中删除重要数据而未备份&#xff0c;您仍然可以找回丢失的数据。实际上&#xff0c;已删除的视频/照片或文档不会永远丢失&#xff0c;它们仍存储在 Sony 存储卡上&#xff0c;可以通过数据…

计算机组成原理之定点乘法运算

文章目录 原码并行乘法与补码并行乘法原码算法运算规则存在的问题带符号的阵列乘法器习题原码阵列乘法器间接补码阵列乘法器直接补码阵列乘法器 补码与真值的转换 原码并行乘法与补码并行乘法 原码算法运算规则 存在的问题 理解流水式阵列乘法器&#xff08;并行乘法器&#x…

会声会影色彩校正在哪里 会声会影色彩素材栏在哪 会声会影中文免费版下载

会声会影是一款功能强大的视频编辑软件&#xff0c;它可以帮助用户轻松地编辑和制作视频。在进行视频编辑时&#xff0c;色彩校正是一个重要的步骤&#xff0c;它可以调整视频的色调、亮度和对比度等参数&#xff0c;使视频更加生动和鲜明。在会声会影中&#xff0c;色彩校正功…

C#(C Sharp)学习笔记_封装【十八】

什么是封装&#xff1f; 封装是面向对象思维的三大特性之一。封装是将数据和对数据进行操作的函数绑定到一起的机制。它隐藏了对象的内部状态和实现细节&#xff0c;只对外提供必要的接口&#xff0c;从而确保对象内部状态的完整性和安全性。封装的主要目的是增强安全性和简化…

【教学类-64-02】20240610色块眼力挑战(二)-2-25宫格色差10-100(10倍)(星火讯飞)

背景需求 以下的色块眼里挑战需要人工筛选图片&#xff0c;非常繁琐。 【教学类-64-01】20240607色块眼力挑战&#xff08;一&#xff09;-0-255随机底色-CSDN博客文章浏览阅读446次&#xff0c;点赞12次&#xff0c;收藏5次。【教学类-64-01】20240607色块眼力挑战&#xff…

C语言——自定义类型:结构体

前言 本篇博客位大家介绍C语言中一块儿重要的内容&#xff0c;那就是结构体&#xff0c;关于结构体的内容&#xff0c;大家需要深入掌握&#xff0c;在后面的学习中依然会用到&#xff0c;如果你对本文感兴趣&#xff0c;麻烦点进来的老铁一键三连。多多支持&#xff0c;下面我…