趣味编程:爱心
概述:五月十一号就是母亲节了,本篇博客主要是为母亲所写,这是属于程序员的浪漫,这篇博客是对母亲这么多年无微不至爱的情书。
目录
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
:为了避免一些编译器对于不安全函数(如scanf
、strcpy
等)的警告。- 包含了多个头文件,其中
graphics.h
用于图形绘制,conio.h
用于控制台输入输出,算math.h
用于数学运算,time.h
用于时间处理,stdio.h
用于标准输入输出。- 定义了常量
PI
、WIDTH
和HEIGHT
,分别表示圆周率、窗口宽度和窗口高度。
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);
}
heartX
和heartY
函数根据参数t
计算心形曲线上点的x
和y
坐标,这是基于心形曲线的参数方程实现的。
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;
}
- 初始化图形窗口,如果初始化失败则输出错误信息并退出程序。
- 设置背景颜色为白色并清空绘图设备。
- 开启批量绘图模式。
- 定义变量
frame
、hue
、isGrowing
和scale
,分别表示帧数、色调、缩放状态和缩放比例。- 进入主循环,直到用户按下任意键退出循环。
- 清空绘图设备。
- 计算色调和缩放比例,实现颜色渐变和爱心缩放效果。
- 绘制渐变背景。
- 绘制主爱心。
- 绘制 6 个环绕小爱心。
- 绘制跳动文字。
- 刷新批量绘图。
- 帧数加 1,程序暂停 30 毫秒。
- 关闭批量绘图模式,关闭图形窗口。
4. 运行问题
博主是使用 Visual Studio2022 来编写程序,运行程序的,在运行本程序前,需要先下好 EasyX图形库。以及在 Unicode字符集 下会编译报错的解决方式。
4.1 解决Unicode字符集下编译报错
在 Unicode字符集下会出现这样的错误。
对于这样的“没有与参数列表匹配的重载函数的”错误, 我们就需要用到 多字节字符集 能解决问题,博主展示一种简单快捷的解决方式。
之后打开最下面的“调试属性”
最后点击“应用”即可
5. 完整效果 
6.小结
以上便是本篇博客的所有内容,如果大家学到知识的话,还请给博主点点赞,记得在5月11号的晚上对母亲说出那句:“爱你老妈,明天见!”哦。