利用Python做一个五角星在平面上滚动

“利用Python做一个五角星在平面上滚动,把其中一定点的轨迹用matplotlib画出来

现只有五角星代码

import numpy as np
import matplotlib.pyplot as plt

r = 1 # 旋转半径
five_corners = np.linspace(18, 378, 5, endpoint=False) # 五角星初始位置
rotations = np.linspace(0, 360, 361) # 旋转序列:旋转一周,间隔1°
x_shift = np.linspace(0, 2*r*np.pi, 361) # 旋转过程中五角星水平位移序列
theta = np.radians(five_corners.reshape(-1,1) - rotations) # 计算五角星每个角的旋转弧度序列
x, y = r*np.cos(theta) + x_shift,  r*np.sin(theta) # 计算旋转轨迹上每个角的坐标

plt.plot([x[0][0], x[2][0]], [y[0][0], y[2][0]], color='m', ls='dashed')
plt.plot([x[0][0], x[3][0]], [y[0][0], y[3][0]], color='m', ls='dashed')
plt.plot([x[1][0], x[3][0]], [y[1][0], y[3][0]], color='m', ls='dashed')
plt.plot([x[1][0], x[4][0]], [y[1][0], y[4][0]], color='m', ls='dashed')
plt.plot([x[2][0], x[4][0]], [y[2][0], y[4][0]], color='m', ls='dashed')

for i in range(5):
    plt.plot(x[i], y[i]) # 绘制5个角的旋转轨迹

plt.axis('equal') # xy轴等比例保持
plt.show()

img

这个得花点心思。首先,滚动是绕着某点旋转吧。然后检测碰撞。重现饶新的原点旋转。然后把图形绘画出来,更新

滚动的五角星实际上可以看作是五角星的外接圆在滚动,五角星随之滚动,假设要画轨迹的点是五角星左上的角的顶点,这个点的Y坐标与圆滚动的距离x的关系是可以换算出来的,所以应该是先把五角星的起始点坐标算出来,然后x坐标每增加1,五角星的起始划线角度也是能计算出来的,根据这个理论,有如下实现代码


import turtle as t
import time
from matplotlib import pyplot as plt
import numpy as np
x_list = np.arange(1,600)
r = 40/np.cos(0.1)
y_list = r*(1+np.sin(0.1+x_list/r))
t.Turtle().screen.setworldcoordinates(0,-400,800,400)
t.pensize(2)
t.colormode(255)
t.color(255,215,0)
for x,y in zip(x_list,y_list):
    t.clear()
    t.goto(x,y)
    t.seth(0)
    t.right(x*180/(r*np.pi))
    t.tracer(10,1)
    t.begin_fill()
    for i in range(5):
        t.fd(80)
        t.right(144)
    t.end_fill()
    t.hideturtle()
    t.update()
    time.sleep(0.01)

plt.plot(x_list,y_list)
plt.show()

img


def plant_star_with_color(star_sides, length, colour):
    # suggest: star_sides >= 5
    color(colour, colour)
    begin_fill()
    pensize(10)
    for s in range(star_sides):
        forward(length)
        right(720 / star_sides)
        # 设置绘制哪一个顶点的轨迹
        if s == 2:
            place = pos()
        forward(length)
        left(360 / star_sides)
    end_fill()
    return place


setup(1000 + 10, 1000 * 0.618 + 10)
screensize(1000, 1000 * 0.618, 'blue')
amount = 150
star_sides = 5
speed(0)
tracer(False)
hideturtle()
start = (-400, 0)
points = []
for i in range(amount):
    up()
    goto(i * 5 - 400, 0)
    down()
    # 绘制当前图形
    point = plant_star_with_color(star_sides, 20, 'yellow')
    update()
    # 用于擦除当前绘制的图形,防止出现残影
    if i != amount - 1:
        time.sleep(0.02)
        plant_star_with_color(star_sides, 20, 'blue')
        update()
    points.append(point)
    pencolor('red')
    pensize(5)
    # 用于绘制轨迹
    if len(points) >= 20:
        select_points = points[-20:]
        select_start = points[-20]
    else:
        select_points = points
        select_start = points[0]
    up()
    goto(select_start)
    down()
    for point in select_points:
        goto(point)
    update()
    # 设置旋转角度
    seth(0)
    right(i * 5)
done()

供参考,通过不断绘制擦除实现滚动效果,滚动的轨迹不是直线,通过turtle库绘制

img