循环黑洞:用Python生成银河系特效图
循环黑洞:用Python生成银河系特效图
"程序就像宇宙,循环是其中的星辰大海。掌握它,你就能创造整个数字银河系。"
—— 代码宇宙探索者
引言:当循环遇见星辰
你是否曾仰望夜空,被璀璨的银河所震撼?今天,我将带你揭开一个神奇的奥秘:用Python的简单循环结构,结合强大的turtle库,生成令人惊叹的银河系特效图!
这不仅仅是编程教学,更是一场视觉盛宴。我们会从最基础的循环概念开始,一步步构建复杂壮丽的银河系图像,让你在创造美的过程中,彻底掌握Python循环的精髓。
学完之后,你将能够创造这样的神奇效果:
第一章:循环基础 - Python中的"时间魔法"
1.1 为什么循环如此重要?
想象你要在夜空中点出1000颗星星。如果没有循环,你需要写1000行代码。但有了循环,只需几行:
for i in range(1000):draw_star()
这就是循环的魔力!在Python中,有两种主要的循环结构:for
循环和while
循环。
1.2 For循环 - 精确控制的太空画笔
for
循环适合在明确知道循环次数时使用。让我们画一个简单的星空背景:
import turtle
import random# 设置画布
screen = turtle.Screen()
screen.bgcolor('black')
screen.setup(1000, 800)# 创建画笔
pen = turtle.Turtle()
pen.speed(0) # 最快速度
pen.hideturtle()# 用for循环绘制100颗星星
for _ in range(100):pen.penup()x = random.randint(-450, 450)y = random.randint(-350, 350)pen.goto(x, y)pen.dot(2, 'white')turtle.done()
运行这段代码,你就能在黑色背景上看到100颗随机分布的白点,犹如星空!
1.3 While循环 - 创造无限宇宙
当我们需要创建不断变化的动态效果时,while
循环是首选。比如模拟星星闪烁:
import turtle
import random
import time# 初始化设置
screen = turtle.Screen() # 定义screen变量
screen.bgcolor('black')
screen.setup(1000, 800)
screen.title("闪烁星空特效")
screen.tracer(0) # 关闭自动刷新,手动刷新提升性能# 存储所有星星
stars = []# 创建100颗初始星星
for _ in range(100):star = turtle.Turtle()star.shape('circle')star.shapesize(0.1)star.color('white')star.penup()star.goto(random.randint(-450, 450), random.randint(-350, 350))stars.append(star)# 用while循环让星星闪烁
while True:for star in stars:# 随机改变星星的亮度(大小)size = random.uniform(0.05, 0.3)star.shapesize(size)# 随机改变星星的位置,产生缓慢移动效果star.setx(star.xcor() + random.uniform(-0.5, 0.5))star.sety(star.ycor() + random.uniform(-0.5, 0.5))# 确保星星不会离开屏幕if star.xcor() > 450 or star.xcor() < -450:star.setx(random.randint(-450, 450))if star.ycor() > 350 or star.ycor() < -350:star.sety(random.randint(-350, 350))# 添加新星星并移除旧星星if random.random() > 0.95: # 5%的几率添加新星星new_star = turtle.Turtle()new_star.shape('circle')new_star.shapesize(random.uniform(0.05, 0.2))new_star.color('white')new_star.penup()new_star.goto(random.randint(-450, 450), random.randint(-350, 350))stars.append(new_star)if len(stars) > 150: # 控制星星数量oldest_star = stars.pop(0)oldest_star.hideturtle()screen.update() # 更新屏幕time.sleep(0.05) # 控制刷新速度turtle.mainloop() # 保持窗口打开
这段代码会创建100颗随机分布的星星,它们的大小不断变化,产生闪烁效果,就像真实星空一样。
第二章:turtle库 - 你的宇宙画笔
2.1 turtle库基础操作
turtle是Python标准库中一个强大的绘图工具,特别适合可视化和教学。以下是关键功能:
turtle.Turtle()
创建画笔forward()/backward()
前进/后退left()/right()
左转/右转penup()/pendown()
提笔/落笔goto(x, y)
移动到指定位置color()
设置颜色circle()
画圆
2.2 构建基础宇宙元素
绘制恒星:
def draw_star(x, y, size, color):pen.penup()pen.goto(x, y)pen.pendown()pen.color(color)pen.begin_fill()for _ in range(5): # 五角星pen.forward(size)pen.right(144)pen.end_fill()
绘制行星环:
def draw_planet(x, y, size, color):pen.penup()pen.goto(x, y - size)pen.pendown()pen.color(color)pen.circle(size)# 添加行星环pen.penup()pen.goto(x - size * 1.5, y)pen.pendown()pen.setheading(60)pen.color('lightgray')pen.circle(size * 2.5, 45) # 画部分椭圆
第三章:构建银河系 - 循环的艺术
3.1 基础星系结构
让我们创建一个简单的螺旋星系:
def draw_spiral_galaxy(arms=4, stars_per_arm=100):pen.penup()for arm in range(arms): # 每个旋臂angle = arm * (360 / arms) # 每个旋臂的角度for i in range(stars_per_arm): # 每臂中的星星# 计算位置 (螺旋公式)distance = i * 3pen.setheading(angle + i * 2) # 逐步增加角度# 移动到位置pen.penup()pen.forward(distance)# 随机星星属性star_size = random.uniform(0.1, 1)star_color = random.choice(['white', 'yellow', 'blue'])# 绘制星星pen.dot(star_size, star_color)# 回到原点pen.goto(0, 0)
3.2 添加星云效果
def draw_nebula(layers=10, size=300):colors = ['#FF007F', '#9400D3', '#4B0082', '#0000FF', '#00FF00', '#FFFF00', '#FF7F00', '#FF0000']for layer in range(layers, 0, -1):# 为每层星云选择随机颜色r, g, b = random.choice(colors)r = min(255, int(r * (layer/layers) * 1.5))g = min(255, int(g * (layer/layers) * 1.5))b = min(255, int(b * (layer/layers) * 1.5))color = (r/255, g/255, b/255)# 绘制星云层pen.penup()pen.goto(0, -size * layer / layers)pen.pendown()pen.color(color)pen.begin_fill()pen.circle(size * layer / layers)pen.end_fill()
3.3 添加黑洞效果
def draw_black_hole(x=0, y=0, size=80, detail=100):# 创建黑洞核心pen.penup()pen.goto(x, y - size)pen.pendown()pen.color('black')pen.begin_fill()pen.circle(size)pen.end_fill()# 创建吸积盘for i in range(1, detail + 1):radius = size + i * 0.5brightness = 1 - i/detail# 旋转颜色hue = (0.65 + 0.05 * math.sin(i/10)) % 1# 创建动态颜色效果pen.penup()pen.goto(x, y - radius)pen.pendown()pen.color(tuple(int(c * 255) for c in colorsys.hsv_to_rgb(hue, 0.8, brightness)))pen.circle(radius)
第四章:进阶技巧 - 打造个性化宇宙
4.1 参数调整指南
通过调整以下参数,创造属于你的独特银河系:
# 在draw_galaxy函数中修改这些参数
def draw_galaxy():create_starfield(1500) # 减少星星数量create_spiral_galaxy(arms=6, stars_per_arm=400) # 6臂星系create_black_hole(size=100) # 更大的黑洞# ...
4.2 添加超新星爆炸效果
# 添加超新星爆炸效果
def create_supernova(x, y):"""在指定位置创建超新星爆炸效果"""pen.penup()pen.goto(x, y)# 爆炸的彩色冲击波for i in range(100, 0, -10):# 随半径变化颜色hue = (0.1 + i / 500) % 1color = colorsys.hsv_to_rgb(hue, 0.9, 1)# 绘制爆炸环pen.dot(i, color)screen.update()time.sleep(0.01)# 爆炸核心pen.dot(50, (1.0, 1.0, 0.88)) # 淡黄色核心# 添加闪光效果for _ in range(5):flash_size = random.randint(10, 30)pen.dot(flash_size, (1.0, 1.0, 1.0))screen.update()time.sleep(0.05)pen.dot(flash_size, (1.0, 1.0, 0.88))screen.update()
4.3 添加流星效果
# 添加流星效果 - 增强版
def create_shooting_star():"""创建更明显的流星效果"""# 随机选择起点start_x = random.randint(-550, 550)start_y = 420# 随机结束点end_x = start_x + random.randint(-300, 300)end_y = random.randint(-400, 300)# 随机速度和大小 - 增大尺寸speed = random.uniform(0.8, 1.8)size = random.uniform(1.5, 3.5) # 增大流星尺寸# 创建流星star = turtle.Turtle()star.speed(0)star.shape('circle')star.shapesize(size / 10)star.color('white')star.penup()star.goto(start_x, start_y)# 移动流星distance_x = end_x - start_xdistance_y = end_y - start_ysteps = max(abs(distance_x), abs(distance_y)) / 2# 创建尾迹 - 更长更明显trail = []for _ in range(8): # 增加尾迹长度t = turtle.Turtle()t.speed(0)t.shape('circle')t.color('white')t.penup()t.hideturtle()trail.append(t)for step in range(int(steps)):if not star.isvisible():break# 更新流星位置progress = step / stepsstar.goto(start_x + progress * distance_x,start_y + progress * distance_y)# 更新尾迹 - 更亮更明显for i, t in enumerate(trail):if step > i:t_pos = max(0, step - i * 2)t_progress = t_pos / stepst.goto(start_x + t_progress * distance_x,start_y + t_progress * distance_y)t_size = size * (1 - t_progress) * (1 - i / 10)t.shapesize(t_size / 10)# 使用更亮的颜色brightness = 1.0 - i / 15t.color((brightness, brightness, brightness))t.showturtle()screen.update()time.sleep(0.01)# 隐藏并删除star.hideturtle()for t in trail:t.hideturtle()del starfor t in trail:del t
第五章:完整银河系特效 - 整合艺术与代码
5.1 完整实现
import turtle
import random
import math
import colorsys
import time
import sys# 设置画布
screen = turtle.Screen()
screen.setup(1200, 900)
screen.bgcolor("black")
screen.title("银河系特效:含超新星爆炸")
screen.tracer(0) # 关闭自动刷新,手动刷新提升性能# 创建画笔
pen = turtle.Turtle()
pen.speed(0)
pen.hideturtle()# 创建背景画笔
bg_pen = turtle.Turtle()
bg_pen.speed(0)
bg_pen.hideturtle()# 性能优化:使用更高效的绘图方法
def optimized_dot(t, x, y, size, color):"""优化点绘制方法,减少turtle移动"""t.penup()t.goto(x, y)t.dot(size, color)# 创建星空背景函数 - 优化版
def create_starfield(stars=800):"""创建星空背景,优化性能"""for _ in range(stars):x = random.randint(-550, 550)y = random.randint(-400, 400)# 随机星星属性star_size = random.uniform(0.1, 1.5)star_brightness = random.uniform(0.2, 1)star_hue = random.random()star_color = colorsys.hsv_to_rgb(star_hue, 0.3, star_brightness)optimized_dot(bg_pen, x, y, star_size, star_color)# 创建星云函数 - 增强版
def create_nebula(x=0, y=0, size=400, layers=10):"""创建更大更明显的彩色星云"""# 使用更鲜艳的颜色colors = [(1.0, 0.0, 0.5), # 粉红(0.6, 0.0, 1.0), # 紫色(0.0, 0.0, 1.0), # 蓝色(0.0, 1.0, 0.0), # 绿色(1.0, 1.0, 0.0), # 黄色(1.0, 0.5, 0.0), # 橙色(1.0, 0.0, 0.0) # 红色]base_color = random.choice(colors)bg_pen.penup()# 创建渐变效果for layer in range(layers, 0, -1):layer_size = size * layer / layers# 选择颜色并调整亮度brightness = (0.4 + 0.6 * (layer / layers))# 创建透明效果if layer < layers * 0.7:alpha = layer / (layers * 0.7)color = tuple(c * brightness * alpha for c in base_color)else:color = tuple(c * brightness for c in base_color)# 绘制星云点 - 增加点的大小和数量for _ in range(80): # 增加点的数量angle = random.uniform(0, 2 * math.pi)distance = random.uniform(0, layer_size)nx = x + distance * math.cos(angle)ny = y + distance * math.sin(angle)size_factor = random.uniform(1.0, 3.0) # 增大点的大小optimized_dot(bg_pen, nx, ny, size_factor, color)# 创建小行星带
def create_asteroid_belt(x=0, y=0, radius=300, width=80, count=200):"""在星系周围创建小行星带"""for _ in range(count):# 随机角度angle = random.uniform(0, 2 * math.pi)# 随机距离(在环形区域内)distance = random.uniform(radius - width / 2, radius + width / 2)# 计算位置asteroid_x = x + distance * math.cos(angle)asteroid_y = y + distance * math.sin(angle)# 小行星属性 - 增大尺寸size = random.uniform(0.5, 2.0)brightness = random.uniform(0.4, 0.8)color = colorsys.hsv_to_rgb(0.1, 0.3, brightness) # 棕灰色optimized_dot(pen, asteroid_x, asteroid_y, size, color)# 创建螺旋星系函数 - 增强版
def create_spiral_galaxy(x=0, y=0, arms=4, stars_per_arm=300, rotation=0):"""创建更大更明显的螺旋星系"""# 绘制星系核心 - 增大核心尺寸core_size = 50for i in range(15):size = core_size * (1 - i / 20)brightness = 0.9 - i * 0.05optimized_dot(pen, x, y, size, colorsys.hsv_to_rgb(0.12, 0.3, brightness))# 预计算星星位置star_positions = []for arm in range(arms):angle = arm * (360 / arms) + rotation # 每个旋臂的起始角度for i in range(stars_per_arm):# 螺旋公式 - 增大螺旋范围distance = math.sqrt(i) * 5current_angle = angle + i * 10# 添加随机偏移使旋臂更自然distance += random.uniform(-4, 4)current_angle += random.uniform(-5, 5)# 计算位置rad_angle = math.radians(current_angle)star_x = x + distance * math.cos(rad_angle)star_y = y + distance * math.sin(rad_angle)# 星星属性 - 增大尺寸star_size = random.uniform(0.2, 1.2)distance_factor = min(1, i / (stars_per_arm / 2))# 内圈偏黄,外圈偏蓝if distance < 150:hue = 0.12 # 淡黄色saturation = 0.3else:hue = 0.6 # 淡蓝色saturation = 0.5brightness = min(1, 0.8 + distance_factor * 0.5)star_color = colorsys.hsv_to_rgb(hue + random.uniform(-0.05, 0.05),saturation,brightness)star_positions.append((star_x, star_y, star_size, star_color))# 批量绘制星星for pos in star_positions:optimized_dot(pen, pos[0], pos[1], pos[2], pos[3])# 添加小行星带 - 增大尺寸create_asteroid_belt(x, y, radius=350, width=100)# 创建黑洞函数 - 增强版
def create_black_hole(x=0, y=0, size=80, detail=60, rotation=0):"""创建更大更明显的黑洞效果"""# 绘制吸积盘 - 增大尺寸for i in range(detail):radius = size + i * 1.0 # 增大间距pen.penup()pen.goto(x, y - radius)# 动态色彩angle = time.time() * 0.5 + rotation # 随时间旋转# 旋转色彩hue = (0.7 + 0.1 * math.sin(angle + i / 10)) % 1saturation = 0.9 # 增加饱和度brightness = max(0.3, 1 - i / detail) # 外侧更亮disk_color = colorsys.hsv_to_rgb(hue, saturation, brightness)pen.color(disk_color)pen.circle(radius)# 绘制黑洞核心 - 使用纯黑色pen.penup()pen.goto(x, y - size)pen.pendown()pen.color("black")pen.begin_fill()pen.circle(size)pen.end_fill()# 绘制事件视界pen.penup()pen.goto(x, y - size)pen.pendown()pen.color("darkgray")pen.circle(size, steps=100)# 添加光晕效果 - 更明显for i in range(8): # 增加光晕层数glow_size = size * (1.1 + i * 0.15) # 增大光晕范围pen.penup()pen.goto(x, y - glow_size)pen.pendown()# 使用RGB元组glow_factor = 1.0 - i / 8.0glow_color = (0.4 * glow_factor, 0.4 * glow_factor, 1.0 * glow_factor)pen.color(glow_color)pen.circle(glow_size, steps=100)# 添加发光点 - 更多更亮if i % 2 == 0:for _ in range(12): # 增加发光点数量angle = random.uniform(0, 2 * math.pi)dist = size * (1.3 + i * 0.1)px = x + dist * math.cos(angle)py = y + dist * math.sin(angle)optimized_dot(pen, px, py, 1.8, (0.9, 0.9, 1.0)) # 增大发光点尺寸# 添加流星效果 - 增强版
def create_shooting_star():"""创建更明显的流星效果"""# 随机选择起点start_x = random.randint(-550, 550)start_y = 420# 随机结束点end_x = start_x + random.randint(-300, 300)end_y = random.randint(-400, 300)# 随机速度和大小 - 增大尺寸speed = random.uniform(0.8, 1.8)size = random.uniform(1.5, 3.5) # 增大流星尺寸# 创建流星star = turtle.Turtle()star.speed(0)star.shape('circle')star.shapesize(size / 10)star.color('white')star.penup()star.goto(start_x, start_y)# 移动流星distance_x = end_x - start_xdistance_y = end_y - start_ysteps = max(abs(distance_x), abs(distance_y)) / 2# 创建尾迹 - 更长更明显trail = []for _ in range(8): # 增加尾迹长度t = turtle.Turtle()t.speed(0)t.shape('circle')t.color('white')t.penup()t.hideturtle()trail.append(t)for step in range(int(steps)):if not star.isvisible():break# 更新流星位置progress = step / stepsstar.goto(start_x + progress * distance_x,start_y + progress * distance_y)# 更新尾迹 - 更亮更明显for i, t in enumerate(trail):if step > i:t_pos = max(0, step - i * 2)t_progress = t_pos / stepst.goto(start_x + t_progress * distance_x,start_y + t_progress * distance_y)t_size = size * (1 - t_progress) * (1 - i / 10)t.shapesize(t_size / 10)# 使用更亮的颜色brightness = 1.0 - i / 15t.color((brightness, brightness, brightness))t.showturtle()screen.update()time.sleep(0.01)# 隐藏并删除star.hideturtle()for t in trail:t.hideturtle()del starfor t in trail:del t# 添加超新星爆炸效果
def create_supernova(x, y):"""在指定位置创建超新星爆炸效果"""pen.penup()pen.goto(x, y)# 爆炸的彩色冲击波for i in range(100, 0, -10):# 随半径变化颜色hue = (0.1 + i / 500) % 1color = colorsys.hsv_to_rgb(hue, 0.9, 1)# 绘制爆炸环pen.dot(i, color)screen.update()time.sleep(0.01)# 爆炸核心pen.dot(50, (1.0, 1.0, 0.88)) # 淡黄色核心# 添加闪光效果for _ in range(5):flash_size = random.randint(10, 30)pen.dot(flash_size, (1.0, 1.0, 1.0))screen.update()time.sleep(0.05)pen.dot(flash_size, (1.0, 1.0, 0.88))screen.update()# 创建背景(只执行一次)
def create_background():"""创建静态背景"""bg_pen.clear()# 绘制星空背景create_starfield(1000)# 绘制背景星云 - 更大更多for _ in range(5): # 增加星云数量x = random.randint(-450, 450)y = random.randint(-350, 350)size = random.uniform(300, 500) # 增大星云尺寸create_nebula(x, y, size)screen.update()# 主绘图函数
def draw_galaxy(rotation=0):"""绘制整个银河系场景(前景)"""pen.clear()# 1. 绘制主星系create_spiral_galaxy(0, 0, arms=4, stars_per_arm=350, rotation=rotation)# 2. 绘制黑洞create_black_hole(0, 0, 80, rotation=rotation)# 3. 添加随机流星if random.random() > 0.5: # 50%几率添加流星screen.ontimer(create_shooting_star, 100)# 4. 随机添加超新星爆炸if random.random() > 0.3: # 70%几率添加超新星# 在星系外围随机位置angle = random.uniform(0, 2 * math.pi)distance = random.uniform(300, 400)supernova_x = distance * math.cos(angle)supernova_y = distance * math.sin(angle)create_supernova(supernova_x, supernova_y)screen.update()# 初始绘制
create_background()
draw_galaxy()# 旋转动画控制
is_rotating = False
rotation_speed = 0.5
rotation_angle = 0def toggle_rotation():"""切换旋转状态"""global is_rotatingis_rotating = not is_rotatingif is_rotating:rotate_galaxy()def rotate_galaxy():"""旋转整个星系"""global is_rotating, rotation_angleif is_rotating:# 增加旋转角度rotation_angle += rotation_speed# 重绘星系draw_galaxy(rotation_angle)screen.ontimer(rotate_galaxy, 30)def increase_speed():"""增加旋转速度"""global rotation_speedrotation_speed = min(2.0, rotation_speed + 0.1)def decrease_speed():"""降低旋转速度"""global rotation_speedrotation_speed = max(0.1, rotation_speed - 0.1)def regenerate():"""重新生成星系"""global rotation_anglerotation_angle = 0create_background()draw_galaxy()def create_random_supernova():"""在随机位置创建超新星爆炸"""# 在屏幕范围内随机位置x = random.randint(-500, 500)y = random.randint(-350, 350)create_supernova(x, y)# 绑定键盘事件
screen.onkey(toggle_rotation, "space")
screen.onkey(regenerate, "r") # 重置
screen.onkey(increase_speed, "Up") # 增加速度
screen.onkey(decrease_speed, "Down") # 降低速度
screen.onkey(create_random_supernova, "s") # 手动触发超新星爆炸
screen.onkey(sys.exit, "Escape") # 退出程序
screen.listen()# 添加说明文字
instructions = turtle.Turtle()
instructions.speed(0)
instructions.color("white")
instructions.penup()
instructions.goto(0, -420)
instructions.write("空格键: 开始/停止旋转 | R键: 重新生成 | 上下箭头: 调整速度 | S键: 超新星爆炸 | ESC: 退出",align="center", font=("Arial", 12, "normal"))
instructions.hideturtle()# 添加标题
title = turtle.Turtle()
title.speed(0)
title.color("cyan")
title.penup()
title.goto(0, 400)
title.write("银河系特效:含超新星爆炸", align="center", font=("Arial", 24, "bold"))
title.hideturtle()turtle.mainloop()
5.2 功能详解
这个程序实现了:
- 1000颗随机分布的背景星星,颜色丰富多样
- 3个随机位置和大小的彩色星云
- 4臂螺旋星系,包含500颗/臂恒星(总计2000颗)
- 星系中心的旋转黑洞及吸积盘特效
- 按空格键开关旋转动画
- 按"r"键重新生成星系
第六章:运行与优化
6.1 运行环境
- 系统要求:Windows/macOS/Linux
- Python版本:3.6+
- 依赖库:
pip install PythonTurtle
6.2 性能优化技巧
当绘制数千颗星星时,可以应用以下优化:
# 1. 禁用自动刷新
screen.tracer(0)# 2. 批量绘制后再刷新
# 在大量操作完成后执行
screen.update()# 3. 简化图形元素
# 使用点而非复杂形状# 4. 减少不必要的绘制
# 只重绘变化的部分# 5. 使用更高效的屏幕实现
screen = turtle.Screen()
screen.tracer(0, 0) # 每0毫秒刷新一次
第七章:从视觉艺术到编程思维
通过创建这些令人惊叹的视觉效果,我们其实是在训练编程的核心能力:
7.1 编程思维训练
- 问题分解:如何将复杂的银河系分解为可编程的元素?
- 模式识别:识别星系中的数学模式(螺旋、辐射状)
- 抽象化:用代码表示物理现象(星云、黑洞)
- 算法思维:优化绘制算法实现实时动画
- 调试思维:视觉反馈帮助快速定位错误
7.2 创造你的宇宙
现在,请尝试修改代码,创建属于你的独特宇宙。以下是几个创意点子:
- 双星系系统:创建两个互相环绕的星系
- 行星系统:在星系中创建围绕恒星的系列行星
- 外星舰队:添加移动的飞船,穿越你的银河系
- 时间操控:让星系以不同速度旋转
- 星门隧道:创建星际旅行通道
结语:代码即宇宙
通过本次教程,你已经掌握了:
- Python循环的深度理解与应用
- turtle库的高级可视化技巧
- 复杂系统的构建和优化方法
- 将数学公式转化为视觉效果的秘籍
- 创建专业级天文特效的能力
宇宙就在你的指尖,启动Python,释放你的创造力吧!你的编程旅程才刚刚开始...
附录:学习资源
- Python turtle官方文档