Python 趣味程序:星空模拟器
这个程序可以生成随机的星空图案,并且模拟星星的闪烁效果。这个程序使用了Python的Pygame库来创建图形界面,非常适合学习python不久的程序员们,因为它视觉效果很棒且代码有教育意义。完整代码放在最后。
1.导入必要的库
import pygame
import random
import math
import sys
from pygame.locals import *
-
pygame:游戏开发库,用于创建图形界面和处理用户输入 -
random:生成随机数,用于星星的随机属性 -
math:数学函数库,用于计算三角函数和几何运算 -
sys:系统相关功能,用于程序退出 -
pygame.locals:包含Pygame的常量定义
2. 初始化设置
# 初始化pygame
pygame.init()
# 设置窗口大小
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("星空模拟器 - 按ESC退出")
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (100, 100, 255)
YELLOW = (255, 255, 100)
RED = (255, 100, 100)
-
pygame.init():初始化Pygame的所有模块 -
设置窗口尺寸为800x600像素
-
screen是主要的绘制表面 -
预定义几种颜色(RGB格式),用于星星和流星
3. Star类 - 星星的实现
class Star:
def __init__(self):
self.x = random.randint(0, WIDTH)
self.y = random.randint(0, HEIGHT)
self.size = random.uniform(0.5, 3)
self.brightness = random.uniform(0.3, 1.0)
self.speed = random.uniform(0.9, 1.1)
self.color = random.choice([WHITE, BLUE, YELLOW, RED])
self.twinkle_speed = random.uniform(0.01, 0.05)
self.twinkle_factor = 0
def update(self):
# 星星闪烁效果
self.twinkle_factor += self.twinkle_speed
self.brightness = 0.5 + 0.5 * math.sin(self.twinkle_factor)
# 星星移动效果(缓慢)
self.x += (random.random() - 0.5) * 0.1 * self.speed
self.y += (random.random() - 0.5) * 0.1 * self.speed
# 确保星星不会移出屏幕
if self.x < 0: self.x = WIDTH
if self.x > WIDTH: self.x = 0
if self.y < 0: self.y = HEIGHT
if self.y > HEIGHT: self.y = 0
def draw(self):
# 根据亮度计算实际颜色
color = [int(c * self.brightness) for c in self.color]
# 绘制星星
pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.size)
# 为大星星添加光晕效果
if self.size > 1.5:
surf = pygame.Surface((int(self.size*6), int(self.size*6)), pygame.SRCALPHA)
pygame.draw.circle(surf, (*color, 100), (int(self.size*3), int(self.size*3)), self.size*3)
screen.blit(surf, (int(self.x - self.size*3), int(self.y - self.size*3)))
-
__init__:初始化星星的随机属性(位置、大小、亮度、颜色等) -
update:更新星星状态,实现闪烁效果和缓慢移动 -
draw:绘制星星,大星星有光晕效果 -
使用正弦函数
math.sin()实现自然的闪烁效果 -
SRCALPHA参数创建带透明度的表面,用于光晕效果
4. ShootingStar类 - 流星的实现
class ShootingStar:
def __init__(self):
self.reset()
def reset(self):
self.x = random.randint(0, WIDTH)
self.y = random.randint(0, HEIGHT//4)
self.speed = random.uniform(5, 15)
self.angle = random.uniform(math.pi/4, math.pi/2)
self.length = random.randint(20, 50)
self.active = random.random() < 0.01 # 小概率出现流星
self.color = random.choice([WHITE, BLUE, YELLOW])
def update(self):
if not self.active:
# 随机决定是否激活流星
if random.random() < 0.001:
self.reset()
self.active = True
return
# 移动流星
self.x += math.cos(self.angle) * self.speed
self.y += math.sin(self.angle) * self.speed
# 如果流星飞出屏幕,重置它
if self.x > WIDTH or self.y > HEIGHT:
self.reset()
def draw(self):
if not self.active:
return
# 绘制流星尾巴
end_x = self.x - math.cos(self.angle) * self.length
end_y = self.y - math.sin(self.angle) * self.length
pygame.draw.line(screen, self.color, (self.x, self.y), (end_x, end_y), 2)
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), 3)
-
流星有位置、速度、角度、长度等属性
-
使用三角函数计算流星移动轨迹
-
只有小概率激活流星,增加惊喜感
-
流星飞出屏幕后自动重置
5. 初始化对象和界面元素
# 创建星星
stars = [Star() for _ in range(200)]
shooting_star = ShootingStar()
# 显示说明文字
font = pygame.font.SysFont(None, 24)
instructions = [
"星空模拟器",
"按ESC键退出",
"按空格键添加更多星星",
"按C键清除所有星星",
"按R键重置星空"
]
# 主循环
clock = pygame.time.Clock()
running = True
-
创建200个初始星星
-
创建一个流星实例
-
设置字体和说明文字
-
创建时钟对象控制帧率
-
running变量控制主循环
6. 主游戏循环
while running:
screen.fill(BLACK)
# 处理事件
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.key == K_SPACE:
# 添加更多星星
stars.extend([Star() for _ in range(20)])
elif event.key == K_c:
# 清除所有星星
stars = []
elif event.key == K_r:
# 重置星空
stars = [Star() for _ in range(200)]
# 更新和绘制星星
for star in stars:
star.update()
star.draw()
# 更新和绘制流星
shooting_star.update()
shooting_star.draw()
# 显示说明文字
for i, text in enumerate(instructions):
text_surface = font.render(text, True, WHITE)
screen.blit(text_surface, (10, 10 + i * 25))
# 显示星星数量
count_text = f"星星数量: {len(stars)}"
count_surface = font.render(count_text, True, WHITE)
screen.blit(count_surface, (WIDTH - 150, 10))
pygame.display.flip()
clock.tick(60)
-
screen.fill(BLACK):每帧清空屏幕为黑色 -
事件处理:检测退出、键盘输入等
-
更新和绘制所有星星
-
更新和绘制流星
-
显示说明文字和星星数量
-
pygame.display.flip():更新整个屏幕显示 -
clock.tick(60):限制帧率为60FPS
7. 退出程序
pygame.quit()
sys.exit()
-
正确关闭Pygame
-
退出程序
这个程序展示了面向对象编程、图形界面开发、动画效果和用户交互的完整实现,是一个很好的学习项目。
完整代码
import pygame
import random
import math
import sys
from pygame.locals import *
# 初始化pygame
pygame.init()
# 设置窗口大小
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("星空模拟器 - 按ESC退出")
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
BLUE = (100, 100, 255)
YELLOW = (255, 255, 100)
RED = (255, 100, 100)
# 星星类
class Star:
def __init__(self):
self.x = random.randint(0, WIDTH)
self.y = random.randint(0, HEIGHT)
self.size = random.uniform(0.5, 3)
self.brightness = random.uniform(0.3, 1.0)
self.speed = random.uniform(0.9, 1.1)
self.color = random.choice([WHITE, BLUE, YELLOW, RED])
self.twinkle_speed = random.uniform(0.01, 0.05)
self.twinkle_factor = 0
def update(self):
# 星星闪烁效果
self.twinkle_factor += self.twinkle_speed
self.brightness = 0.5 + 0.5 * math.sin(self.twinkle_factor)
# 星星移动效果(缓慢)
self.x += (random.random() - 0.5) * 0.1 * self.speed
self.y += (random.random() - 0.5) * 0.1 * self.speed
# 确保星星不会移出屏幕
if self.x < 0: self.x = WIDTH
if self.x > WIDTH: self.x = 0
if self.y < 0: self.y = HEIGHT
if self.y > HEIGHT: self.y = 0
def draw(self):
# 根据亮度计算实际颜色
color = [int(c * self.brightness) for c in self.color]
# 绘制星星
pygame.draw.circle(screen, color, (int(self.x), int(self.y)), self.size)
# 为大星星添加光晕效果
if self.size > 1.5:
surf = pygame.Surface((int(self.size*6), int(self.size*6)), pygame.SRCALPHA)
pygame.draw.circle(surf, (*color, 100), (int(self.size*3), int(self.size*3)), self.size*3)
screen.blit(surf, (int(self.x - self.size*3), int(self.y - self.size*3)))
# 创建流星类
class ShootingStar:
def __init__(self):
self.reset()
def reset(self):
self.x = random.randint(0, WIDTH)
self.y = random.randint(0, HEIGHT//4)
self.speed = random.uniform(5, 15)
self.angle = random.uniform(math.pi/4, math.pi/2)
self.length = random.randint(20, 50)
self.active = random.random() < 0.01 # 小概率出现流星
self.color = random.choice([WHITE, BLUE, YELLOW])
def update(self):
if not self.active:
# 随机决定是否激活流星
if random.random() < 0.001:
self.reset()
self.active = True
return
# 移动流星
self.x += math.cos(self.angle) * self.speed
self.y += math.sin(self.angle) * self.speed
# 如果流星飞出屏幕,重置它
if self.x > WIDTH or self.y > HEIGHT:
self.reset()
def draw(self):
if not self.active:
return
# 绘制流星尾巴
end_x = self.x - math.cos(self.angle) * self.length
end_y = self.y - math.sin(self.angle) * self.length
pygame.draw.line(screen, self.color, (self.x, self.y), (end_x, end_y), 2)
pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), 3)
# 创建星星
stars = [Star() for _ in range(200)]
shooting_star = ShootingStar()
# 显示说明文字
font = pygame.font.SysFont(None, 24)
instructions = [
"星空模拟器",
"按ESC键退出",
"按空格键添加更多星星",
"按C键清除所有星星",
"按R键重置星空"
]
# 主循环
clock = pygame.time.Clock()
running = True
while running:
screen.fill(BLACK)
# 处理事件
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.key == K_SPACE:
# 添加更多星星
stars.extend([Star() for _ in range(20)])
elif event.key == K_c:
# 清除所有星星
stars = []
elif event.key == K_r:
# 重置星空
stars = [Star() for _ in range(200)]
# 更新和绘制星星
for star in stars:
star.update()
star.draw()
# 更新和绘制流星
shooting_star.update()
shooting_star.draw()
# 显示说明文字
for i, text in enumerate(instructions):
text_surface = font.render(text, True, WHITE)
screen.blit(text_surface, (10, 10 + i * 25))
# 显示星星数量
count_text = f"星星数量: {len(stars)}"
count_surface = font.render(count_text, True, WHITE)
screen.blit(count_surface, (WIDTH - 150, 10))
pygame.display.flip()
clock.tick(60)
pygame.quit()
sys.exit()
-
按空格键:添加更多星星
-
按C键:清除所有星星
-
按R键:重置星空
-
按ESC键:退出程序
更多推荐


所有评论(0)