在pygame中是否有递归的方法?

2024-06-08 08:31:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我想做一个自定义分形

this is my fractal

我所做的是创建一个半径为R的圆,假设我们有三个小圆在里面,它们和大的圆接触,它们的大小都一样,我想找到小圆的半径,它是大圆半径的函数

我可以用一个函数计算出半径的公式:

def formula(R):
    return ((sqrt(3)*R)/(sqrt(3)+2))

如果有人需要我可以解释

我现在要做的是编写一个递归函数,用pygame再次对每个小圆圈执行此操作


Tags: 函数returndef半径sqrtpygame公式分形
2条回答

作为一种小吃/练习,我将其实现为一个带有React的交互式玩具(使用@Yevhenii M.的答案公式计算半径)。(向下滚动并点击“Run”查看它的运行情况!)你知道吗

分形的实质(自然)在drawFractal函数中;您应该能够将它改编成Python/PyGame,用drawCircle代替框架中画圆的东西。你知道吗

const nextRadius = (r1, n) => (r1 * Math.sin(Math.PI / n)) / (1 + Math.sin(Math.PI / n)); function drawFractal( circleStyle, levels, branches, startRadius, anglePerLevel ) { const circles = []; function drawCircle(cx, cy, r, transform = null) { circles.push( <circle cx={cx} cy={cy} r={r} style={circleStyle} key={circles.length} /> ); } function drawLevel(centerX, centerY, lastRadius, n, levelsLeft) { const radius = nextRadius(lastRadius, n); const distance = lastRadius - radius; const level = levels - levelsLeft; for (var i = 0; i < n; i++) { const angle = (i / n + level * anglePerLevel) * Math.PI * 2; const x = Math.sin(angle) * distance; const y = Math.cos(angle) * distance; drawCircle(centerX + x, centerY + y, radius); if (levelsLeft > 0) { drawLevel(centerX + x, centerY + y, radius, n, levelsLeft - 1); } } } drawCircle(0, 0, startRadius); drawLevel(0, 0, startRadius, branches, levels); return circles; } function App() { const [branches, setBranches] = React.useState(3); const [levels, setLevels] = React.useState(3); const [twist, setTwist] = React.useState(0); const contents = drawFractal( { fill: "none", stroke: "red", strokeWidth: 1 }, levels, branches, 250, twist ); return ( <div className="App"> <label> Branches <input type="range" min={1} max={15} value={branches} onInput={e => setBranches(e.target.valueAsNumber)} /> </label> <label> Levels <input type="range" min={1} max={7} value={levels} onInput={e => setLevels(e.target.valueAsNumber)} /> </label> <label> Twist <input type="range" min={-1} max={1} step={0.001} value={twist} onInput={e => setTwist(e.target.valueAsNumber)} /> </label> <hr /> <svg viewbox="0 0 1000 1000" width={500} height={500} style={{ border: "1px solid black" }} > <g transform="translate(250 250)">{contents}</g> </svg> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement); ; ^{pr2}$ ;

定义从原点(0,0)到Equilateral triangle的角点的规范化向量:

sin60 = math.sin(math.pi/3) # math.sqrt(3) / 2
tri_pt = [[-sin60, 0.5], [sin60, 0.5], [0, -1]]

使用"Radius of inner circles given radius of outer circle and number of inner circles in circular fractal"中给出的公式计算内圆的半径和从中心到内圆中心点的距离:

in_r     = radius * math.sin(math.pi/3) / (math.sin(math.pi/3)+1)
in_cpt_d = radius - in_r

计算回路中内圆的中心点:

colors = [(255, 0, 0), (0, 0, 255), (255, 255, 0)]

for pt, color in zip(tri_pt, colors):
    in_cpt = (cpt[0] + pt[0] * in_cpt_d), (cpt[1] + pt[1] * in_cpt_d)

    pygame.draw.circle(window, color, (round(in_cpt[0]), round(in_cpt[1])), round(in_r), 1)

请参见使用递归函数的示例:

import pygame, math

def innerCircles(cpt, radius, depth):
    if depth == 4:
        return

    sin60    = math.sin(math.pi/3) # math.sqrt(3) / 2
    tri_pt   = [[-sin60, 0.5], [sin60, 0.5], [0, -1]]
    in_r     = radius * sin60 / (sin60+1)
    in_cpt_d = radius - in_r

    colors = [(255, 0, 0), (0, 0, 255), (255, 255, 0)]
    for pt, color in zip(tri_pt, colors):
        in_cpt = (cpt[0] + pt[0] * in_cpt_d), (cpt[1] + pt[1] * in_cpt_d)
        pygame.draw.circle(wnd, color, (round(in_cpt[0]), round(in_cpt[1])), round(in_r), 1)
        innerCircles(in_cpt, in_r, depth+1)

pygame.init()
wnd = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    wnd.fill(0)
    cpt = (250, 250)
    radius = 200
    pygame.draw.circle(wnd, (255, 255, 255), cpt, radius+1, 3)
    innerCircles(cpt, radius, 0)
    pygame.display.flip()

相关问题 更多 >