这个程序可以生成随机的星空图案,并且模拟星星的闪烁效果。这个程序使用了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键:退出程序

更多推荐