[python趣味实战]----基于python代码实现浪漫爱心 დ

正文

01-效果演示

        下图是代码运行之后的爱心显示结果:

        下面的视频该爱心是动态效果,较为简洁,如果需要使用,可以进行完善,这里只是一个趣味实战,下面将对代码实现进行非常详细地描述:

浪漫爱心

02-代码实现

        下图是动态爱心代码实现,对所有代码进行详细解释如下:

         import random   // 导入Python中的random模块,用于生成随机数。
        from math import  sin, cos, pi, log   // 从math模块中导入sin、cos、pi和log函数,用于数学计算。
        from tkinter import *    // 从tkinter模块中导入所有内容,用于创建GUI界面。


        CANVAS_WIDTH = 640
        CANVAS_HEIGHT = 480
        CANVAS_CENTER_X = CANVAS_WIDTH / 2
        CANVAS_CENTER_Y = CANVAS_HEIGHT / 2

        // 定义了一些常量:CANVAS_WIDTH, CANVAS_HEIGHT, CANVAS_CENTER_X, CANVAS_CENTER_Y,用于定义画布的大小和中心位置。


        def center_window(root, width, height):  // 定义了一个函数center_window,接受三个参数root(窗口对象),width(窗口宽度),height(窗口高度)

        screenwidth = root.winfo_screenwidth():  // 使用winfo_screenwidth()方法获取屏幕的宽度,并将值赋给screenwidth变量

        screenheight = root.winfo_screenheight():  // 使用winfo_screenheight()方法获取屏幕的高度,并将值赋给screenheight变量

        size = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2):  // 建一个字符串size,其中包括窗口的宽度和高度,以及窗口左上角的位置(居中显示计算)

        root.geometry(size):  // 使用geometry方法将窗口的大小和位置设置为size字符串中描述的值,从而将窗口居中显示在屏幕上


        def heart_function(t, shrink_ratio):  // 定义了一个心形函数heart_function,接受两个参数t(参数值)和shrink_ratio(缩小比率)

        x = 16 * (sin(t) ** 3):   // 计算心形曲线上点的x坐标,根据参数t的正弦值的三次方乘以16来计算

        y = -(13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t)):   // 计算心形曲线上点的y坐标,根据参数t的余弦值的线性组合来计算

        x *= shrink_ratio:   // 将计算出的x坐标乘以缩小比率shrink_ratio,用于对心形曲线进行缩放

        y *= shrink_ratio:   // 将计算出的y坐标乘以缩小比率shrink_ratio,用于对心形曲线进行缩放

        x += CANVAS_CENTER_X:   // 将x坐标移动到画布横向中心位置

        y += CANVAS_CENTER_Y:   // 将y坐标移动到画布纵向中心位置

        return int(x), int(y):   // 返回计算出的x和y坐标,使用int()函数将结果转换为整数类型。这样就得到了在画布上绘制心形图案所需要的坐标


         Heart类用于生成心形图案,初始化时会生成心形曲线上的点,并根据一定的规则进行扩散。生成心形图案后,可以根据指定的帧数进行渲染。下面逐个分析:

        def __init__(self, generate_frame=20):  // 定义了Heart类的初始化方法,接受一个参数generate_frame,默认值为20。在这个方法中进行了一些初始化操作

        self._points = set():   // 创建一个空集合_points,用于存储心形图案的点

        self._edge_diffusion_points = set():   // 创建一个空集合_edge_diffusion_points,用于存储心形图案的边缘扩散点

        self._center_diffusion_points = set():  // 创建一个空集合_center_diffusion_points,用于存储心形图案的中心扩散点

        self.all_points = {}:   // 创建一个空字典all_points,用于存储所有计算出的点

        self.build(2000):   // 调用build方法,传入参数2000,用于构建心形图案

        self.random_halo = 1000:   // 设置random_halo属性为1000,用于表示随机光晕的大小

        self.generate_frame = generate_frame:  // 将传入的generate_frame参数赋值给实例属性generate_frame,表示生成帧数

        for frame in range(generate_frame)::   // 遍历生成帧数的范围

        self.calc(frame):   // 调用calc方法,传入当前帧数frame作为参数,用于计算心形图案的点的位置。通过循环生成帧数次来完整绘制心形图案


        def build(self, number):  // 定义了Heart类中的build方法,接受一个参数number,用于生成指定数量的点

        for _ in range(number)::   // 遍历指定数量的次数

        t = random.uniform(0, 2 * pi):   // 生成一个随机的角度t,范围在0到2π之间

        x, y = heart_function(t, 11):   // 调用之前定义的heart_function函数,传入角度t和缩小比率11,计算得到心形曲线上的点的x和y坐标

        self._points.add((x, y)):   // 将计算出的点的坐标添加到_points集合中,第一个for循环结束后,_points集合中包含了心形曲线上的点

        for _x, _y in list(self._points)::   // 遍历_points集合中的所有点

        for _ in range(3)::   // 嵌套循环,执行3次

        self._edge_diffusion_points.add((x, y)):   // 将当前点加入_edge_diffusion_points集合中,实现边缘扩散

        point_list = list(self._points):   // 将_points集合转换为列表point_list

        for _ in range(4000)::   // 遍历4000次

        x, y = random.choice(point_list):   // 从point_list中随机选择一个点的坐标

        self._center_diffusion_points.add((x, y)):   // 将选定的点作为中心点,加入_center_diffusion_points集合中,实现中心扩散


         @staticmethod:  // 标记下面的calc_position方法为静态方法,即不需要实例化对象也可以直接调用该方法

        def calc_position(x, y, ratio):   // 定义了静态方法calc_position,接受三个参数x(x坐标)、y(y坐标)和ratio(比率)

        force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.520):   // 计算力(force),根据点到画布中心的距离的0.520次方来计算

        dx = ratio * force * (x - CANVAS_CENTER_X) + random.randint(-1, 1):   // 计算x方向上的偏移量,根据比率、力和距离画布中心的偏移,再加上一个随机值

        dy = ratio * force * (y - CANVAS_CENTER_Y) + random.randint(-1, 1):   // 计算y方向上的偏移量,同样根据比率、力和距离画布中心的偏移,再加上一个随机值

        return x - dx, y - dy:   // 返回新计算出的x和y坐标,通过减去对应的偏移量,实现点的位置更新

        这个静态方法calc_position用于根据点与画布中心的距离,以及指定的比率,计算点的新位置偏移量,从而实现点的移动。同时添加了一些随机性以增加点的变化


        def calc(self, generate_frame):  // 定义了Heart类中的calc方法,接受一个参数generate_frame,用于计算心形图案的点的位置

        ratio = 10:   // 设置比率为10

        halo_radius = int(4 + 6):   // 计算光晕的半径为10

        halo_number = int(3000 + 4000):   // 设置生成的光晕点的数量在7000左右

        all_points = []:   // 创建一个空列表all_points,用于存储所有计算出的点

        heart_halo_point = set():   // 创建一个空集合heart_halo_point,用于存储心形光晕点

        第一个循环用于生成心形光晕点,并添加到all_points列表中。随机选取角度t,计算心形曲线上的点坐标,加入heart_halo_point集合,加入随机偏移,选择大小,将点信息加入all_points列表

        第二个循环遍历心形曲线上的点,通过调用calc_position方法计算新的位置坐标,加入all_points列表

        第三个循环遍历边缘扩散点,同样通过调用calc_position方法计算新的位置坐标,加入all_points列表

        self.all_points[generate_frame] = all_points:   // 将生成的所有点信息存储在all_points字典中,以当前帧数generate_frame作为键值

        通过这些步骤,calc方法计算了心形图案上的点的新的位置,并将结果存储在all_points字典中


         def render(self, render_canvas, render_frame):  // 定义了Heart类中的render方法,接受两个参数render_canvas(用于绘制点的画布)和render_frame(当前帧数)

        for x, y, size in self.all_points[render_frame % self.generate_frame]::   // 遍历all_points字典中与当前帧数对应的点的信息

        alpha = int(((render_frame % self.generate_frame) / self.generate_frame) * 255):   // 计算当前帧数对总帧数取余再除以总帧数后的比例,并将其转换为alpha值(0-255范围)

        color = f"#{alpha:02X}0000":   // 根据计算得到的alpha值生成颜色字符串,格式为RGBA中的R=alpha,G=0,B=0,表示红色

        render_canvas.create_rectangle(x, y, x + size, y + size, width=0, fill=color):   // 在绘制点的画布上创建一个矩形,以(x, y)为左上角坐标,(x+size, y+size)为右下角坐标,填充颜色为之前计算得到的红色


        root = Tk():  // 创建一个Tkinter应用程序的根窗口对象root

        root.title("浪漫爱心"):   // 设置窗口的标题为"浪漫爱心"

        center_window(root, CANVAS_WIDTH, CANVAS_HEIGHT):   // 调用center_window函数来将窗口居中显示在屏幕上,参数包括窗口对象root以及指定的画布宽度和高度

        canvas = Canvas(root, bg='black', height=CANVAS_HEIGHT, width=CANVAS_WIDTH):   // 在窗口root上创建一个Canvas对象canvas,背景颜色为黑色,指定画布的高度和宽度为预定义的值CANVAS_HEIGHT和CANVAS_WIDTH

        canvas.pack():   // 将Canvas对象canvas放置到窗口中进行显示

        heart = Heart():   // 创建一个Heart类的实例对象heart,用于生成心形图案并进行后续的计算和渲染

        通过以上代码,创建了一个Tkinter窗口并在窗口中显示了一个黑色背景的Canvas画布,同时生成了一个Heart类的实例对象heart,准备后续使用该对象进行心形图案的绘制和动画效果展示。


        def draw(main, render_canvas, render_heart, render_frame=0):  // 定义了一个名为draw的函数,接受四个参数,分别为main(主窗口对象),render_canvas(用于绘制的画布对象),render_heart(Heart类实例对象),render_frame(当前帧数,默认为0)

        render_canvas.delete('all'):   // 在每次绘制之前,清空画布上的所有内容

        render_heart.render(render_canvas, render_frame):   // 调用Heart类中的render方法,将当前帧数和绘制的画布传入,用于绘制心形图案上的点

        main.after(300, draw, main, render_canvas, render_heart, render_frame + 1):   // 使用Tkinter中的after方法,设置300毫秒后执行draw函数,实现动画效果。同时将main窗口对象、render_canvas画布对象、render_heart对象以及更新后的render_frame作为参数传入

        Label(root, text="I Love You", bg="black", fg="#FF0000", font="Helvetic 20 bold").place(relx=.5, rely=.5, anchor=CENTER):   // 创建一个标签对象,显示文本"I Love You",设置背景颜色为黑色,前景色为红色,字体为Helvetica 20粗体,在窗口中居中显示

        root.mainloop():   // 进入Tkinter的主事件循环,等待响应用户事件,保持窗口显示

        通过以上代码,实现了一个动画效果,不断更新心形图案的点的位置并在画布上绘制,同时在窗口中显示 “I Love You” 的标签文本。整个程序会持续运行,直到用户关闭窗口。

import random   
from math import sin, cos, pi, log   
from tkinter import *CANVAS_WIDTH = 640
CANVAS_HEIGHT = 480
CANVAS_CENTER_X = CANVAS_WIDTH / 2
CANVAS_CENTER_Y = CANVAS_HEIGHT / 2def center_window(root, width, height):screenwidth = root.winfo_screenwidth()  screenheight = root.winfo_screenheight()  size = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)  root.geometry(size)  def heart_function(t, shrink_ratio):x = 16 * (sin(t) ** 3)y = -(13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t))x *= shrink_ratioy *= shrink_ratiox += CANVAS_CENTER_Xy += CANVAS_CENTER_Yreturn int(x), int(y)class Heart:def __init__(self, generate_frame=20):self._points = set()  self._edge_diffusion_points = set()  self._center_diffusion_points = set()  self.all_points = {}  self.build(2000)self.random_halo = 1000self.generate_frame = generate_framefor frame in range(generate_frame):self.calc(frame)def build(self, number):for _ in range(number):t = random.uniform(0, 2 * pi)x, y = heart_function(t, 11)self._points.add((x, y))for _x, _y in list(self._points):for _ in range(3):x, y = _x, _yself._edge_diffusion_points.add((x, y))point_list = list(self._points)for _ in range(4000):x, y = random.choice(point_list)self._center_diffusion_points.add((x, y))@staticmethoddef calc_position(x, y, ratio):force = 1 / (((x - CANVAS_CENTER_X) ** 2 + (y - CANVAS_CENTER_Y) ** 2) ** 0.520)dx = ratio * force * (x - CANVAS_CENTER_X) + random.randint(-1, 1)dy = ratio * force * (y - CANVAS_CENTER_Y) + random.randint(-1, 1)return x - dx, y - dydef calc(self, generate_frame):ratio = 10halo_radius = int(4 + 6)halo_number = int(3000 + 4000)all_points = []heart_halo_point = set()for _ in range(halo_number):t = random.uniform(0, 2 * pi)x, y = heart_function(t, 11.6)x, y = x, yif (x, y) not in heart_halo_point:heart_halo_point.add((x, y))x += random.randint(-14, 14)y += random.randint(-14, 14)size = random.choice((1, 2, 2))all_points.append((x, y, size))for x, y in self._points:x, y = self.calc_position(x, y, ratio)size = random.randint(1, 3)all_points.append((x, y, size))for x, y in self._edge_diffusion_points:x, y = self.calc_position(x, y, ratio)size = random.randint(1, 2)all_points.append((x, y, size))self.all_points[generate_frame] = all_pointsdef render(self, render_canvas, render_frame):for x, y, size in self.all_points[render_frame % self.generate_frame]:alpha = int(((render_frame % self.generate_frame) / self.generate_frame) * 255)color = f"#{alpha:02X}0000"render_canvas.create_rectangle(x, y, x + size, y + size, width=0, fill=color)root = Tk()
root.title("浪漫爱心")
center_window(root, CANVAS_WIDTH, CANVAS_HEIGHT)  canvas = Canvas(root, bg='black', height=CANVAS_HEIGHT, width=CANVAS_WIDTH)
canvas.pack()heart = Heart()def draw(main, render_canvas, render_heart, render_frame=0):render_canvas.delete('all')render_heart.render(render_canvas, render_frame)main.after(300, draw, main, render_canvas, render_heart, render_frame + 1)draw(root, canvas, heart, 0)Label(root, text="I Love You", bg="black", fg="#FF0000", font="Helvetic 20 bold").place(relx=.5, rely=.5, anchor=CENTER)root.mainloop()

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

77、贪心-买卖股票的最佳时机

思路 具体会导致全局最优,这里就可以使用贪心算法。方式如下: 遍历每一位元素找出当前元素最佳卖出是收益是多少。然后依次获取最大值,就是全局最大值。 这里可以做一个辅助数组:右侧最大数组,求右侧最大数组就要从…

Linux专栏03:使用Xshell远程连接云服务器

博客主页:Duck Bro 博客主页系列专栏:Linux专栏关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ 使用Xshell远程连接云服务器 编号:03 文章目录 使用Xsh…

rust疑难杂症

rust疑难杂症解决 边碰到边记录,后续可能会逐步增加,备查 cargo build时碰到 Blocking waiting for file lock on package cache 原因是Cargo 无法获取对包缓存的文件锁, 有时vscode中项目比较多,如果其中某些库应用有问题&…

border-image-slice详细说明

上一篇文章我们介绍了 border-image的用法,其中border-image-source、border-image-width、 border-image-outset都比较简单好理解,这边文章我们重点学一下border-image-slice 属性,它用于定义边框图像如何被切割并应用到元素的边框上。这个属…

排序-八大排序FollowUp

FollowUp 1.插入排序 (1).直接插入排序 时间复杂度:最坏情况下:0(n^2) 最好情况下:0(n)当数据越有序 排序越快 适用于: 待排序序列 已经基本上趋于有序了! 空间复杂度:0(1) 稳定性:稳定的 public static void insertSort(int[] array){for (int i 1; i < array.length; i…

二维码门楼牌管理应用平台建设:实现用户权限的高效管理

文章目录 前言一、用户权限管理的重要性二、用户管理中心的构建三、用户权限管理的实施策略四、用户权限管理的挑战与应对五、结语 前言 随着信息技术的飞速发展&#xff0c;二维码门楼牌管理应用平台已成为城市管理的重要组成部分。本文将深入探讨如何通过用户权限管理&#…

Windows 容器镜像踩坑记录

为什么研究windows容器&#xff1f;emm&#xff0c;公司需要&#xff0c;不想多说。 dotnet后端 问题描述&#xff1a; 基于mcr.microsoft.com/dotnet/aspnet:6.0镜像撰写dockerfile编译.net core后端项目后运行容器出现类库不存在问题&#xff1a; 程序中使用了fastreport&a…

前端 CSS

目录 选择器 复合选择器 伪类-超链接 结构伪装选择器 伪元素选择器 画盒子 字体属性 CSS三大属性 Emmet写法 背景属性 显示模式 盒子模型 盒子模型-组成 盒子模型-向外溢出 盒子模型-圆角 盒子模型-阴影 flex position定位 CSS小精灵 字体图标 垂直对齐方式…

2024HW --->操作系统权限维持

前面不是说要讲隧道吗&#xff0c; 没错&#xff0c;我又鸽了&#x1f54a;&#x1f54a;&#x1f54a;&#x1f54a;&#xff0c;那么今天现在讲一下操作系统的权限维持&#xff01; 在我们提权之后&#xff0c;或者说打穿了整个内网之后&#xff0c;我们需要做权限维持&#…

复旦 北大 | 从头训练中文大模型:CT-LLM

引言 当前&#xff0c;绝大多数大模型&#xff08;LLMs&#xff09;基本上都是以英文语料库训练得到的&#xff0c;然后经过SFT来匹配不同的语种。然而&#xff0c;今天给大家分享的这篇文章旨在从头开始训练中文大模型&#xff0c;在训练过程中「主要纳入中文文本数据」&…

javaScript 判断闰年

接受用户输入年份 如果是闰年就弹出闰年&#xff0c;遇到平年就是弹出平年 var a prompt(请输入年份);if(a%40&&a%100!0||a%4000){alert(闰年);}else{alert(平年);}

【C++】学习笔记——类和对象_5

文章目录 二、类和对象14. 日期类的实现15. const成员16. 取地址重载17. 再谈构造函数初始化列表 18. explicit关键字19. static成员 未完待续 二、类和对象 14. 日期类的实现 上一篇我们已经大致将日期类的重要功能都给实现了&#xff0c;这节将会对日期类进行完善&#xff…