Python跳动的爱心

Posted Want595

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python跳动的爱心相关的知识,希望对你有一定的参考价值。

目录

前言 

表白界面 

爱心类 

其他函数 


前言 

跳动的爱心,这又是谁的青春吖,源码在文末公众号自取哈

表白界面 

   

def OK():            #同意按钮
    root.destroy()
    love()           #同意后显示漂浮爱心
def NO():            #拒绝按钮,拒绝不会退出,必须同意才可以退出哦~
    tk.messagebox.showwarning('❤','再给你一次机会!')
def closeWindow():
    tk.messagebox.showwarning('❤','逃避是没有用的哦')

爱心类 

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 = 1000
        self.generate_frame = generate_frame
        for 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)
            self._points.add((x, y))
        for _x, _y in list(self._points):
            for _ in range(3):
                x, y = scatter_inside(_x, _y, 0.05)
                self._edge_diffusion_points.add((x, y))
        point_list = list(self._points)
        for _ in range(4000):
            x, y = random.choice(point_list)
            x, y = scatter_inside(x, y, 0.17)
            self._center_diffusion_points.add((x, y))
    @staticmethod
    def calc_position(x, y, ratio):
        force = 1 / (((x - heartx) ** 2 + (y - hearty) ** 2) ** 0.520)  # 魔法参数
        dx = ratio * force * (x - heartx) + random.randint(-1, 1)
        dy = ratio * force * (y - hearty) + random.randint(-1, 1)
        return x - dx, y - dy
    def calc(self, generate_frame):
        ratio = 10 * curve(generate_frame / 10 * pi)  # 圆滑的周期的缩放比例
        halo_radius = int(4 + 6 * (1 + curve(generate_frame / 10 * pi)))
        halo_number = int(3000 + 4000 * abs(curve(generate_frame / 10 * pi) ** 2))
        all_points = []
        heart_halo_point = set()
        for _ in range(halo_number):
            t = random.uniform(0, 2 * pi)
            x, y = heart_function(t, shrink_ratio=11.6)
            x, y = shrink(x, y, halo_radius)
            if (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))
        for x, y in self._center_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_points
    def render(self, render_canvas, render_frame):
        for x, y, size in self.all_points[render_frame % self.generate_frame]:
            render_canvas.create_rectangle(x, y, x + size, y + size, width=0, fill=heartcolor)

其他函数 

def heart_function(t, shrink_ratio: float = side):
    x = 16 * (sin(t) ** 3)
    y = -(13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t))
    x *= shrink_ratio
    y *= shrink_ratio
    x += heartx
    y += hearty
    return int(x), int(y)
def scatter_inside(x, y, beta=0.15):
    ratio_x = - beta * log(random.random())
    ratio_y = - beta * log(random.random())
    dx = ratio_x * (x - heartx)
    dy = ratio_y * (y - hearty)
    return x - dx, y - dy
def shrink(x, y, ratio):
    force = -1 / (((x - heartx) ** 2 + (y - hearty) ** 2) ** 0.6)  # 这个参数...
    dx = ratio * force * (x - heartx)
    dy = ratio * force * (y - hearty)
    return x - dx, y - dy
def curve(p):
    return 2 * (2 * sin(4 * p)) / (2 * pi)
def draw(main: tk.Tk, render_canvas: tk.Canvas, render_heart: Heart, render_frame=0):
    render_canvas.delete('all')
    render_heart.render(render_canvas, render_frame)
    main.after(160, draw, main, render_canvas, render_heart, render_frame + 1)

这是一篇用python画3D爱心的代码

浅浅写一个最近很火的爱心代码

最近你是否也被李峋的爱心跳动代码所感动,心动不如行动,相同的代码很多,我们今天换一个玩法!构建一个三维的跳动爱心!嗯!这篇博客本着开源的思想!不是说谁对浪漫过敏的!

文章目录

环境介绍

  • python3.8
  • numpy
  • matplotlib

第一步,绘制一个三维的爱心

关于这一步,我采用的是大佬博客中的最后一种绘制方法。当然,根据我的代码习惯,我还是稍做了一点点修改的。

class Guess:
    def __init__(self, bbox=(-1.5, 1.5), resolution=50, lines=20) -> None:
        """
        bbox: 控制画格的大小
        resolution: 控制爱心的分辨率
        lines: 控制等高线的数量
        """
        self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax = bbox*3
        A = np.linspace(self.xmin, self.xmax, resolution)
        self.B = np.linspace(self.xmin, self.xmax, lines)
        self.A1, self.A2 = np.meshgrid(A, A)
        

    def coordinate(self, x, y, z):
        """
        生成坐标
        """
        return (x**2+(9/4)*y**2+z**2-1)**3-x**2*z**3-(9/80)*y**2*z**3

    def draw(self, ax):
        """
        绘制坐标
        """
        for z in self.B:
            X, Y = self.A1, self.A2
            Z = self.coordinate(X, Y, z)+z
            cset = ax.contour(X, Y, Z, [z], zdir='z', colors=('pink',))

        for y in self.B:
            X, Z = self.A1, self.A2
            Y = self.coordinate(X, y, Z)+y
            cset = ax.contour(X, Y, Z, [y], zdir='y', colors=('pink',))

        for x in self.B:
            Y, Z = self.A1, self.A2
            X = self.coordinate(x, Y, Z) + x
            cset = ax.contour(X, Y, Z, [x], zdir='x', colors=('pink',))

    def run(self):
        fig = plt.figure()
        ax = fig.add_subplot(projection='3d')
        ax.set_zlim3d(self.zmin, self.zmax)
        ax.set_xlim3d(self.xmin, self.xmax)
        ax.set_ylim3d(self.ymin, self.ymax)
        plt.show()

但是这可以达到我们想要的效果吗?

显然不能!于是我们开始加入亿点点细节!

亿点点细节

加入时间序列

想要心脏跳起来,我们就需要有时间维度的变化。那怎么做最合理呢?这里仅展示修改的代码位置。


class Guess:
    def __init__(self, bbox=(-1.5, 1.5), resolution=50, lines=20) -> None:
        plt.ion()                                         # 开启画布的动态图模式
        self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax = bbox*3
        self.time = time.time()                           # 这里有一个衡量的时间坐标,很合理吧
        A = np.linspace(self.xmin, self.xmax, resolution)
        self.B = np.linspace(self.xmin, self.xmax, lines)
        self.A1, self.A2 = np.meshgrid(A, A)

    def run(self, count):
        """
        加入count是我们想循环的次数
        """
        fig = plt.figure()
        for i in range(count):
            plt.clf()                               # 每次清除画布
            ax = fig.add_subplot(projection='3d')
            ax.set_zlim3d(self.zmin, self.zmax)
            ax.set_xlim3d(self.xmin, self.xmax)
            ax.set_ylim3d(self.ymin, self.ymax)
            times = time.time()-self.t/ime          # 计算画布的当前时间状态
            self.draw(ax, coef)
            plt.show()

加入心脏的跳动

心脏的跳动当然不会是线性的了,我们需要心脏的跳动是有层次感的,并且还是可以做往返运动的。

emmmmm… 这么说来,cos是不是就是做这个用的?

于是…

    def __init__(self, bbox=(-1.5, 1.5), resolution=50, lines=20, scale=1.2) -> None:
        """
        scale: 心脏缩放的系数
        """
        self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax = bbox*3
        plt.ion() 
        self.scale = scale   # scale: 心脏缩放的系数 设置为全局变量
        self.time = time.time()
        A = np.linspace(self.xmin, self.xmax, resolution)
        self.B = np.linspace(self.xmin, self.xmax, lines)
        self.A1, self.A2 = np.meshgrid(A, A)

    def draw(self, ax, coef):
        """
        coef: 使得心脏可以按照时间跳动
        """
        for z in self.B:
            X, Y = self.A1, self.A2
            Z = self.coordinate(X, Y, z)+z
            cset = ax.contour(X * coef, Y * coef, Z * coef, [z * coef], zdir='z', colors=('pink',))

        for y in self.B:
            X, Z = self.A1, self.A2
            Y = self.coordinate(X, y, Z)+y
            cset = ax.contour(X * coef, Y * coef, Z * coef, [y * coef], zdir='y', colors=('pink',))

        for x in self.B:
            Y, Z = self.A1, self.A2
            X = self.coordinate(x, Y, Z) + x
            cset = ax.contour(X * coef, Y * coef, Z * coef, [x * coef], zdir='x', colors=('pink',))

    def run(self, count):
        """
        加入count是我们想循环的次数
        """
        fig = plt.figure()
        for i in range(count):
            plt.clf()                               # 每次清除画布
            ax = fig.add_subplot(projection='3d')
            ax.set_zlim3d(self.zmin, self.zmax)
            ax.set_xlim3d(self.xmin, self.xmax)
            ax.set_ylim3d(self.ymin, self.ymax)
            times = time.time()-self.time
            coef = np.cos(times) * (self.scale-1) + 1
            # coef 是用来放缩心脏的大小的,加入cos来使它有节奏的跳动
            self.draw(ax, coef)
            plt.pause(0.01)
            plt.show()

很好,这样我们就有了一个可以跳动的心脏,那么到这结束了嘛?

一个好的展示

当然没有!我们希望对象看到的时候他稍微有点东西,所以让它跳动却不能改变方向,岂不是看的不够全面?所以我们在加最后亿点点细节:

    def run(self, count):
        fig = plt.figure()
        for i in range(count):
            plt.clf()
            ax = fig.add_subplot(projection='3d')
            ax.set_title("你对象的名字?")              # 加上你对象的小name
            ax.set_zlim3d(self.zmin, self.zmax)
            ax.set_xlim3d(self.xmin, self.xmax)
            ax.set_ylim3d(self.ymin, self.ymax)
            times = time.time()-self.time
            ax.view_init(10, 100+np.cos(times) * 10)   # 让三维坐标图可以变换坐标展示
            coef = np.cos(times) * (self.scale-1) + 1
            self.draw(ax, coef)
            plt.pause(0.01)  # 让绘制出来的心脏可以显示
            plt.show()

代码完整版及效果如下

import time
import numpy as np
import matplotlib.pyplot as plt


class Guess:
    def __init__(self, bbox=(-1.5, 1.5), resolution=50, lines=20, scale=1.2) -> None:
        self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax = bbox*3
        plt.ion() 
        self.scale = scale
        self.time = time.time()
        A = np.linspace(self.xmin, self.xmax, resolution)
        self.B = np.linspace(self.xmin, self.xmax, lines)
        self.A1, self.A2 = np.meshgrid(A, A)
        

    def coordinate(self, x, y, z):
        return (x**2+(9/4)*y**2+z**2-1)**3-x**2*z**3-(9/80)*y**2*z**3

    def draw(self, ax, coef):
        for z in self.B:
            X, Y = self.A1, self.A2
            Z = self.coordinate(X, Y, z)+z
            cset = ax.contour(X * coef, Y * coef, Z * coef, [z * coef], zdir='z', colors=('pink',))

        for y in self.B:
            X, Z = self.A1, self.A2
            Y = self.coordinate(X, y, Z)+y
            cset = ax.contour(X * coef, Y * coef, Z * coef, [y * coef], zdir='y', colors=('pink',))

        for x in self.B:
            Y, Z = self.A1, self.A2
            X = self.coordinate(x, Y, Z) + x
            cset = ax.contour(X * coef, Y * coef, Z * coef, [x * coef], zdir='x', colors=('pink',))

    def run(self, count):
        fig = plt.figure()
        for i in range(count):
            plt.clf()
            ax = fig.add_subplot(projection='3d')
            ax.set_title("2LiuYu")
            ax.set_zlim3d(self.zmin, self.zmax)
            ax.set_xlim3d(self.xmin, self.xmax)
            ax.set_ylim3d(self.ymin, self.ymax)
            times = time.time()-self.time
            ax.view_init(10, 100+np.cos(times) * 10)
            coef = np.cos(times) * (self.scale-1) + 1
            self.draw(ax, coef)
            plt.pause(0.01)
            plt.show()


if __name__ == '__main__':
    demo = Guess()
    demo.run(1000)

以上是关于Python跳动的爱心的主要内容,如果未能解决你的问题,请参考以下文章

这是一篇用python画3D爱心的代码

这是一篇用python画3D爱心的代码

「点燃我,温暖你」用Python制作一个动态爱心效果

用Python制作一个动态爱心效果!

爱心代码编程用啥软件

html5网页底部会跳动的小爱心,有大神有源码吗?