趣味编程:爱心

发布于:2025-05-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

概述:五月十一号就是母亲节了,本篇博客主要是为母亲所写,这是属于程序员的浪漫,这篇博客是对母亲这么多年无微不至爱的情书。

目录

 1. 效果展示

2. 源码展示 

3. 代码逻辑详解 

3.1 头文件与常量定义

 3.2 心形曲线参数方程

3.3 颜色渐变方程

3.4 绘制动态爱心函数

3.5 绘制跳动文字函数 

3.6 主函数 

 4. 运行问题

4.1 解决Unicode字符集下编译报错

5. 完整效果  ​编辑

6.小结


 1. 效果展示

 

 这是一个动态的效果,因此实际运行会比文章展示的更有动态感,这也是这个程序的核心。

2. 源码展示 

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

// 使用 const 定义常量,提高类型安全性
const float PI = 3.14159265f;
const int WIDTH = 800;  // 窗口宽度
const int HEIGHT = 600; // 窗口高度

// 心形曲线参数方程
float heartX(float t) {
    return 16 * powf(sinf(t), 3);
}

float heartY(float t) {
    return 13 * cosf(t) - 5 * cosf(2 * t) - 2 * cosf(3 * t) - cosf(4 * t);
}

// 颜色渐变函数
COLORREF getRainbowColor(float progress) {
    int r = (int)(sinf(progress) * 127 + 128);
    int g = (int)(sinf(progress + PI / 1.5) * 127 + 128);
    int b = (int)(sinf(progress + PI / 3) * 127 + 128);
    return RGB(r, g, b);
}

// 绘制动态爱心
void drawHeart(int offsetX, int offsetY, float scale, COLORREF color) {
    setfillcolor(color);
    setlinecolor(color);

    POINT pts[100];
    for (int i = 0; i < 100; i++) {
        float t = (float)i / 100 * 2 * PI;
        pts[i].x = offsetX + heartX(t) * scale;
        pts[i].y = offsetY - heartY(t) * scale;
    }
    solidpolygon(pts, 100);
}

// 绘制跳动文字
void drawText(int frame) {
    static const char* text = "母亲节快乐!";
    int textWidth = textwidth(text);
    int x = (WIDTH - textWidth) / 2;
    int y = HEIGHT - 300 + 10 * sinf(frame * 0.1);

    settextstyle(30, 0, "Consolas");
    settextcolor(HSVtoRGB(frame % 360, 1, 1));
    setbkmode(TRANSPARENT);
    outtextxy(x, y, text);
}

int main() {
    // 初始化图形窗口
    if (initgraph(WIDTH, HEIGHT) == NULL) {
        printf("无法初始化图形窗口!\n");
        return 1;
    }
    setbkcolor(WHITE);
    cleardevice();

    BeginBatchDraw();

    int frame = 0;
    float hue = 0;
    int isGrowing = 1;
    float scale = 10.0f;

    while (!_kbhit()) {
        cleardevice();

        // 计算颜色和缩放
        hue += 0.02f;
        if (hue > 2 * PI) hue -= 2 * PI;

        if (scale > 15) isGrowing = 0;
        if (scale < 10) isGrowing = 1;
        scale += isGrowing ? 0.1f : -0.1f;

        // 绘制渐变背景
        for (int y = 0; y < HEIGHT; y++) {
            COLORREF color = HSVtoRGB(fmodf(y * 0.5f + frame, 360), 0.3f, 1);
            setlinecolor(color);
            line(0, y, WIDTH, y);
        }

        // 绘制主爱心
        drawHeart(WIDTH / 2, HEIGHT / 2, scale, getRainbowColor(hue));

        // 绘制环绕小爱心
        for (int i = 0; i < 6; i++) {
            float angle = frame * 0.02f + i * PI / 3;
            int x = WIDTH / 2 + (int)(cosf(angle) * 150);
            int y = HEIGHT / 2 + (int)(sinf(angle) * 150);
            drawHeart(x, y, 3, HSVtoRGB((frame * 2 + i * 60) % 360, 1, 1));
        }
        // 绘制文字
        drawText(frame);
        FlushBatchDraw();
        frame++;
        Sleep(30);
    }

    EndBatchDraw();
    closegraph();
    return 0;
}

3. 代码逻辑详解 

3.1 头文件与常量定义
#define _CRT_SECURE_NO_WARNINGS
#include <graphics.h>
#include <conio.h>
#include <math.h>
#include <time.h>
#include<stdio.h>

// 使用 const 定义常量,提高类型安全性
const float PI = 3.14159265f;
const int WIDTH = 800;  // 窗口宽度
const int HEIGHT = 600; // 窗口高度
  • #define _CRT_SECURE_NO_WARNINGS:为了避免一些编译器对于不安全函数(如scanfstrcpy等)的警告。
  • 包含了多个头文件,其中graphics.h用于图形绘制conio.h用于控制台输入输出,算math.h用于数学运算time.h用于时间处理stdio.h用于标准输入输出
  • 定义了常量PIWIDTHHEIGHT,分别表示圆周率、窗口宽度和窗口高度。
 3.2 心形曲线参数方程
// 心形曲线参数方程
float heartX(float t) {
    return 16 * powf(sinf(t), 3);
}

float heartY(float t) {
    return 13 * cosf(t) - 5 * cosf(2 * t) - 2 * cosf(3 * t) - cosf(4 * t);
}
  • heartXheartY函数根据参数t计算心形曲线上点的xy坐标,这是基于心形曲线的参数方程实现的。
3.3 颜色渐变方程
// 颜色渐变函数
COLORREF getRainbowColor(float progress) {
    int r = (int)(sinf(progress) * 127 + 128);
    int g = (int)(sinf(progress + PI / 1.5) * 127 + 128);
    int b = (int)(sinf(progress + PI / 3) * 127 + 128);
    return RGB(r, g, b);
}
  • getRainbowColor函数根据传入的progress参数,通过正弦函数计算红、绿、蓝三个颜色通道的值,从而实现颜色渐变效果。
3.4 绘制动态爱心函数
// 绘制动态爱心
void drawHeart(int offsetX, int offsetY, float scale, COLORREF color) {
    setfillcolor(color);
    setlinecolor(color);

    POINT pts[100];
    for (int i = 0; i < 100; i++) {
        float t = (float)i / 100 * 2 * PI;
        pts[i].x = offsetX + heartX(t) * scale;
        pts[i].y = offsetY - heartY(t) * scale;
    }
    solidpolygon(pts, 100);
}
  • drawHeart函数用于绘制动态爱心。它首先设置填充颜色和线条颜色,然后根据心形曲线参数方程计算 100 个点的坐标,最后使用solidpolygon函数绘制实心多边形。
3.5 绘制跳动文字函数 
// 绘制跳动文字
void drawText(int frame) {
    static const char* text = "母亲节快乐!";
    int textWidth = textwidth(text);
    int x = (WIDTH - textWidth) / 2;
    int y = HEIGHT - 300 + 10 * sinf(frame * 0.1);

    settextstyle(30, 0, "Consolas");
    settextcolor(HSVtoRGB(frame % 360, 1, 1));
    setbkmode(TRANSPARENT);
    outtextxy(x, y, text);
}
  • drawText函数用于绘制跳动的文字。它首先计算文字的宽度和位置,然后根据帧数frame计算文字的y坐标,实现跳动效果。接着设置文字样式、颜色和背景模式,最后使用outtextxy函数输出文字。
3.6 主函数 
int main() {
    // 初始化图形窗口
    if (initgraph(WIDTH, HEIGHT) == NULL) {
        printf("无法初始化图形窗口!\n");
        return 1;
    }
    setbkcolor(WHITE);
    cleardevice();

    BeginBatchDraw();

    int frame = 0;
    float hue = 0;
    int isGrowing = 1;
    float scale = 10.0f;

    while (!_kbhit()) {
        cleardevice();

        // 计算颜色和缩放
        hue += 0.02f;
        if (hue > 2 * PI) hue -= 2 * PI;

        if (scale > 15) isGrowing = 0;
        if (scale < 10) isGrowing = 1;
        scale += isGrowing ? 0.1f : -0.1f;

        // 绘制渐变背景
        for (int y = 0; y < HEIGHT; y++) {
            COLORREF color = HSVtoRGB(fmodf(y * 0.5f + frame, 360), 0.3f, 1);
            setlinecolor(color);
            line(0, y, WIDTH, y);
        }

        // 绘制主爱心
        drawHeart(WIDTH / 2, HEIGHT / 2, scale, getRainbowColor(hue));

        // 绘制环绕小爱心
        for (int i = 0; i < 6; i++) {
            float angle = frame * 0.02f + i * PI / 3;
            int x = WIDTH / 2 + (int)(cosf(angle) * 150);
            int y = HEIGHT / 2 + (int)(sinf(angle) * 150);
            drawHeart(x, y, 3, HSVtoRGB((frame * 2 + i * 60) % 360, 1, 1));
        }
        // 绘制文字
        drawText(frame);
        FlushBatchDraw();
        frame++;
        Sleep(30);
    }

    EndBatchDraw();
    closegraph();
    return 0;
}
  • 初始化图形窗口,如果初始化失败则输出错误信息并退出程序。
  • 设置背景颜色为白色并清空绘图设备。
  • 开启批量绘图模式
  • 定义变量framehueisGrowingscale,分别表示帧数、色调、缩放状态和缩放比例。
  • 进入主循环,直到用户按下任意键退出循环。
    • 清空绘图设备。
    • 计算色调和缩放比例,实现颜色渐变和爱心缩放效果。
    • 绘制渐变背景。
    • 绘制主爱心。
    • 绘制 6 个环绕小爱心。
    • 绘制跳动文字。
    • 刷新批量绘图。
    • 帧数加 1,程序暂停 30 毫秒。
  • 关闭批量绘图模式,关闭图形窗口。

 4. 运行问题

博主是使用 Visual Studio2022 来编写程序,运行程序的,在运行本程序前,需要先下好 EasyX图形库。以及在 Unicode字符集 下会编译报错的解决方式。

4.1 解决Unicode字符集下编译报错

 在 Unicode字符集下会出现这样的错误。

对于这样的“没有与参数列表匹配的重载函数的”错误, 我们就需要用到 多字节字符集 能解决问题,博主展示一种简单快捷的解决方式。

 之后打开最下面的“调试属性”

 最后点击“应用”即可

5. 完整效果  

6.小结

以上便是本篇博客的所有内容,如果大家学到知识的话,还请给博主点点赞,记得在5月11号的晚上对母亲说出那句:“爱你老妈,明天见!”哦。

 


网站公告

今日签到

点亮在社区的每一天
去签到