使用C语言EasyX 创建动态爱心背景

news2024/11/27 1:38:16

简介

在计算机图形学的世界中,有很多方法可以使程序的界面更加吸引人。在本篇博客中,我将向大家介绍如何使用 EasyX 图形库在 C++ 中创建一个动态的爱心背景。这不仅是一个简单的动画效果,它还包括背景的星星、旋转的心形以及一个美观的背景渐变。


工具介绍:EasyX 图形库

EasyX 是一个简单易用的 C++ 图形库,特别适合初学者和那些想要快速为其应用程序添加图形的开发者。它提供了一系列函数,可以帮助你绘制形状、设置颜色和实现动画效果。


设计目标

我们的目标是创建一个动态的爱心,它会在背景中旋转。背景将有一个从深空蓝渐变到黑色的效果,并散布有颜色各异的小星星。

图片展示


开始编码

定义星星的结构

每颗星星都有其坐标、颜色和亮度。我们使用一个 struct 来表示:

struct Star {
    int x, y;
    COLORREF color;
    float intensity;
    float intensityChange;
};

3.2 心形绘制函数

我们使用参数方程来绘制心形,并为它添加了旋转效果:

void DrawHeart(int x, int y, COLORREF color, float scale, float angle) {
    BeginBatchDraw();  // 开始批量绘制
    const int thickness = 2;  // 调整这个值来改变心形的粗细
    for (float t = 0; t < 2 * 3.14159; t += 0.01) {
        float x_cord = scale * (16 * pow(sin(t), 3));
        float y_cord = scale * -(13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t));

        // 旋转
        float rotatedX = x_cord * cos(angle) - y_cord * sin(angle);
        float rotatedY = x_cord * sin(angle) + y_cord * cos(angle);

        for (int dx = -thickness; dx <= thickness; dx++) {
            for (int dy = -thickness; dy <= thickness; dy++) {
                putpixel(x + rotatedX + dx, y + rotatedY + dy, color);
            }
        }
    }
    EndBatchDraw();  // 结束批量绘制,并显示在前台
}

主函数逻辑

main() 函数中,我们首先初始化 EasyX 的图形窗口。接着,我们随机生成一组星星,并存储它们的属性。在主循环中,我们绘制背景渐变、星星和心形,并实现心形的动态效果。


源代码分享

#include <graphics.h>
#include <conio.h>
#include <math.h>
#include <vector>

struct Star {
    int x, y;
    COLORREF color;
    float intensity;
    float intensityChange;
};


// 修改后的心形公式函数
void DrawHeart(int x, int y, COLORREF color, float scale, float angle) {
    BeginBatchDraw();  // 开始批量绘制
    const int thickness = 2;  // 调整这个值来改变心形的粗细
    for (float t = 0; t < 2 * 3.14159; t += 0.01) {
        float x_cord = scale * (16 * pow(sin(t), 3));
        float y_cord = scale * -(13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t));

        // 旋转
        float rotatedX = x_cord * cos(angle) - y_cord * sin(angle);
        float rotatedY = x_cord * sin(angle) + y_cord * cos(angle);

        for (int dx = -thickness; dx <= thickness; dx++) {
            for (int dy = -thickness; dy <= thickness; dy++) {
                putpixel(x + rotatedX + dx, y + rotatedY + dy, color);
            }
        }
    }
    EndBatchDraw();  // 结束批量绘制,并显示在前台
}

int main() {
    // 初始化图形窗口
    initgraph(640, 480);
    setbkcolor(BLACK); // 设置背景色为黑色
    cleardevice();     // 清空屏幕

    // 创建星星
    const int numStars = 100;
    std::vector<Star> stars;
    for (int i = 0; i < numStars; i++) {
        Star star = {
            rand() % 640,
            rand() % 480,
            RGB(rand() % 256, rand() % 256, rand() % 256),
            (rand() % 100) / 100.0f,
            (rand() % 5 + 1) / 500.0f
        };
        stars.push_back(star);
    }

    float scale = 10;
    bool increase = true;
    COLORREF heartColor = RED;
    float angle = 0;
    BeginBatchDraw();  // 开始批量绘制

    while (!_kbhit()) { // 直到有键被按下
        cleardevice(); // 清空屏幕

        // 绘制渐变背景
        for (int i = 0; i < 480; i++) {
            float ratio = (float)i / 480;
            COLORREF bgColor = RGB(0, 0, ratio * 50);
            setlinecolor(bgColor);
            line(0, i, 640, i);
        }

        // 绘制星星
        for (auto& star : stars) {
            star.intensity += star.intensityChange;
            if (star.intensity > 1 || star.intensity < 0.5) {
                star.intensityChange = -star.intensityChange;
            }
            COLORREF modifiedColor = RGB(GetRValue(star.color) * star.intensity, GetGValue(star.color) * star.intensity, GetBValue(star.color) * star.intensity);
            putpixel(star.x, star.y, modifiedColor);
        }

        if (increase) {
            scale += 0.1;
        }
        else {
            scale -= 0.1;
        }

        if (scale > 15 || scale < 10) {
            increase = !increase;
        }

        // 改变心的颜色
        int r = GetRValue(heartColor);
        int g = GetGValue(heartColor);
        int b = GetBValue(heartColor);
        r = (r + 1) % 256;
        g = (g + 2) % 256;
        b = (b + 3) % 256;
        heartColor = RGB(r, g, b);

        DrawHeart(320, 240, heartColor, scale, angle);
        angle += 0.005; // 调整这个值来改变旋转速度

        Sleep(10);
        EndBatchDraw();  // 结束批量绘制,并显示在前台
    }
   
    closegraph();
    return 0;
}

结果

当你运行上述代码时,你将看到一个美丽的动态背景,上面有一个不断旋转的爱心和一群闪烁的星星。通过调整参数,你可以轻松改变动画的速度、颜色和其他属性。


参考资源:

  1. EasyX 官方文档
  2. 心形参数方程

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Scrapy爬虫框架实战

Python实现爬虫是很容易的&#xff0c;一般来说就是获取目标网站的页面&#xff0c;对目标页面的分析、解析、识别&#xff0c;提取有用的信息&#xff0c;然后该入库的入库&#xff0c;该下载的下载。以前写过一篇文章《Python爬虫获取电子书资源实战》&#xff0c;以一个电子…

Vite+React+Electron开发入门,10分钟搭建本地环境并打包

前言 想使用vite和react开发跨平台桌面的软件方案有electron和tauri两种&#xff0c;但是我个人更喜欢tauri&#xff0c;无奈electron名声大燥&#xff0c;面试要求里很多都写着&#xff1a;electron...可见这类公司多么落后。但是呢&#xff0c;又秉持着存在即合理的理念&…

Android 12 源码分析 —— 应用层 五(SystemUI的StatusBar类的启动过程和三个窗口的创建)

Android 12 源码分析 —— 应用层 五&#xff08;SystemUI的StatusBar类的启动过程和三个窗口的创建&#xff09; 在前面的文章中&#xff0c;我们介绍了SystemUI App的基本布局和基本概念。接下来&#xff0c;我们进入SystemUI应用的各个UI是如何被加入屏幕的。那么我们就先从…

计算机视觉实战项目(图像分类+目标检测+目标跟踪+姿态识别+车道线识别+车牌识别)

图像分类 教程博客_传送门链接:链接 在本教程中&#xff0c;您将学习如何使用迁移学习训练卷积神经网络以进行图像分类。您可以在 cs231n 上阅读有关迁移学习的更多信息。 本文主要目的是教会你如何自己搭建分类模型&#xff0c;耐心看完&#xff0c;相信会有很大收获。废话不…

Linux——Shell脚本编程(1)

一、为什么要学习 Shell 编程 &#xff1f; 1)Linux运维工程师在进行服务器集群管理时&#xff0c;需要编写Shell程序来进行服务器管理。 2)对于 JavaEE 和 Python 程序员来说&#xff0c;工作的需要&#xff0c;要求你编写一些 Shell脚本进行程序或者是服务器的维护&#xff…

【Linux学习笔记】基础命令2

1. rmdir指令 && rm指令1.1. 基础概念1.2. 命令用法1.2.1. rmdir命令1.2.2. rm命令1.2.3. rm命令的注意事项 2. man命令3. cp指令3.1. cp指令基础概念3.2. cp命令的用法 4. mv命令5. cat命令6. more命令 && less命令6.1. more命令6.2. less命令 7. head命令和t…

C#下使用IronPython来实现热更新

问题 之前我们学习过Roslyn&#xff0c;他可以动态编译代码并运行&#xff0c;然后通过ALC加载即插即用&#xff0c;但是遇到一些问题感觉无法解决&#xff0c;我编写一个类A在ALC中&#xff0c;另外一个类B要实例化这个A&#xff0c;我想让他们都能灵活卸载&#xff0c;但是如…

MySQL与ES数据同步的四种方案及实践演示

文章目录 一、同步双写优点缺点双写失败风险项目演示 二、异步双写&#xff08;MQ方式&#xff09;优点缺点项目演示 三、基于Datax同步核心组件架构图支持的数据源及操作项目演示 四、基于Binlog实时同步实现原理优点缺点项目演示 一、同步双写 也就是同步调用&#xff0c;这…

IPIDEA动态代理IP更适合于哪些业务场景?为什么动态代理IP更经济实惠?

动态代理IP是一种非常有用的工具&#xff0c;在许多业务场景中发挥重要作用。动态代理IP可以帮助用户提高网络速度和稳定性&#xff0c;提高工作效率&#xff0c;对于需要进行跨境业务的企业和个人来说尤为重要。 让我们先来看看动态代理IP更适合于哪些业务场景。 1.数据采集…

StraUML的详细使用步骤

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于JRebel & XRebel的相关操作吧 下载和安装&#xff1a;首先&#xff0c;你需要从StarUML的官方网站或适用于你操作系统的应用商店下载并安装StarUML软件Sta…

人工智能:神经细胞模型到神经网络模型

人工智能领域中的重要流派之一是&#xff1a;从神经细胞模型&#xff08;Neural Cell Model&#xff09;到神经网络模型&#xff08;Neural Network Model&#xff09;。 一、神经细胞模型 第一个人工神经细胞模型是“MP”模型&#xff0c;它是由麦卡洛克、匹茨合作&#xff0…

基于spingboot的websocket订阅、广播、多人聊天室示例

概述 基于spingboot的websocket多人聊天系统。包括订阅&#xff0c;广播、点对点单人聊天&#xff0c;多人聊天室功能。 详细 一、运行效果 简单示例 广播 单人聊天 多人聊天室 二、相关代码 websocket配置 package com.iamgpj.demowebsocket.config;import com.iamgpj.d…

更大的数据库,更多的分析内容!凌恩明星产品鱼类eDNA产品再次大升级!!

喜大普奔&#xff0c;凌恩生物明星产品鱼类eDNA产品再次大升级&#xff01;自建鱼类数据库&#xff0c;本次升级获得了更大的数据库&#xff0c;更全面的物种分类&#xff0c;更多的分析内容&#xff0c;鱼类物种检测更加精准&#xff01;&#xff01; eDNA宏条形码技术在鱼类…

移植FlashDB、SFUD到STM32f407

个人上篇文章 搭建STM32F407的SPI-Flash&#xff08;基于STM32CubeMX&#xff09;_小刚学長的博客-CSDN博客 主要是解决STM32CubeMX这边的配置&#xff0c;对code端侧是简单介绍了下 实际项目上一般都是拿片外flash存储一些东西&#xff0c;比如一些比较多的配置、参数&…

stu01-IDEA怎么创建一个HTML项目

1.打开idea&#xff0c;依次点击file→new→project 2.点击Java&#xff0c;选择你的jdk&#xff0c;没有下载的点击“Download JDK”/已经下载有JDK但在这里没显示的→点击“Add JDK”&#xff0c;选择你安装的JDK的路径&#xff0c;然后next 3.next 4.起好名字&#xff0c;我…

Python之OS模块

os模块负责程序与操作系统的交互&#xff0c;提供了访问操作系统底层的接口;即os模块提供了非常丰富的方法用来处理文件和目录。 使用的时候需要导入该模块:import os

【数据结构】树的基础知识及三种存储结构

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

定时任务执行脚本

1、编写bat脚本 将newman运行测试集的命令编写为bat脚本保存 2、设置定时任务 在计算机上右键->管理&#xff0c;在弹出菜单里的任务计划程序里创建定时任务配置执行

MySQL 8.0 驱动与阿里druid版本兼容操作

注意&#xff1a;这个异常表面druid数据源的版本与MySql 8.0的驱动版本不匹配&#xff0c;解决方法如下&#xff1a; 确保MySql 8.0的驱动如下网址&#xff1a; <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifact…

c语言练习题52:写一个函数判断当前机器是大端还是小端

代码&#xff1a; #include<stdio.h> int check_sys() {int a 1;return *(char*)&a;//小端retrun 1 大端return 0&#xff1b; } int main() {if (check_sys() 1) {printf("小端\n");}elseprintf("大端\n"); } 这里首先取a的地址&#xff0c…