Python街机模块制作的巫婆和仙女漫游太阳系小故事交互动画by lixingqiu。

```"""

"""
import time
import math
import random

SCREEN_WIDTH = 1350
SCREEN_HEIGHT = 780
SCREEN_TITLE = "Python街机动画：巫婆和仙女漫游太阳系动画,作者：李兴球"
MOVEMENT_SPEED = 5

def __init__(self,image,position,period):
"""image:造型图片,position：初始坐标，初始角度"""
super().__init__(image)
x,y = position
self.center_x = SCREEN_WIDTH / 2
self.center_y = SCREEN_HEIGHT / 2
self.a = y * 1.5                        # 长半轴
self.b = y                              # 短半轴
self.period = period
self.direction = 90

def update(self):
self.direction = self.direction +   MyGame.timespace * 365 / self.period
self.direction = self.direction % 360
x = SCREEN_WIDTH / 2 + self.a * math.cos(math.radians(self.direction)) # 根据椭圆参数方程算起始坐标
y = SCREEN_HEIGHT / 2 + self.b * math.sin(math.radians(self.direction))
self.center_x = x
self.center_y = y
super().update()

"""氧气瓶类"""
def __init__(self,image):
super().__init__(image,0.5)
self.center_x = random.randrange(SCREEN_WIDTH)
self.center_y = random.randrange(SCREEN_HEIGHT)
self.alpha = 80

"""
继承自窗口的MyGame类.
"""
timespace = 1                                             # 游戏的时空变量
can_home = False                                          # 能回家的逻辑变量
def __init__(self, width, height, title):
super().__init__(width, height, title)
self.frame_counter = 0                                # 帧计数器

def setup(self):
""" 这里是对游戏中的各个对象进行设置 """

# 背景角色生成
self.background.center_x = SCREEN_WIDTH / 2
self.background.center_y = SCREEN_HEIGHT / 2

# 太阳角色生成
self.sun.center_x = SCREEN_WIDTH//2
self.sun.center_y = SCREEN_HEIGHT//2
for i in range(0,27):
self.all_stars_list.append(self.sun)

# 行星角色生成
self.days = [88,225,365,687,4333,10760,30799,60192]
self.angle_list = [0,32,76,102,47,180,220,330]       # 每个行星的初始旋转角度

self.planets_image = ['m.gif','v.gif','e.gif','mars.gif','j.gif','s.gif','u.gif','n.gif']  # 每个行星的图像
self.xy_list = [(0,y) for y in range(80,510,60)]      # 每个行星的初始坐标

for i in range(8):                                    # 生成8个行星
angle = self.angle_list[i]
position = self.xy_list[i]
image = self.planets_image[i]
period = self.days[i]
if i == 2 :          # 如果是地球的参数
self.earth = Planet(image,position,period)  # 地球不添加到所有行星列表
self.all_stars_list.append(self.earth)
else:
aplanet = Planet(image,position,period)         # 新建行星
self.planet_list.append(aplanet)                 # 添加到所有行星列表
self.all_stars_list.append(aplanet)              # 添加到所有星星列表

# 宇航员角色生成
self.astronaut1.status = "live"                       # 自定义属生，
self.astronaut1.oxygens = 1000                        # 自定义属性，氧气数量
self.astronaut1.center_x = 100
self.astronaut1.center_y = 100
self.astronaut2.status = "live"                       # 自定义属生，
self.astronaut2.oxygens = 1000                        # 自定义属性，氧气数量
self.astronaut2.center_x = SCREEN_WIDTH-100
self.astronaut2.center_y = SCREEN_HEIGHT-100
self.astronaut_list.append(self.astronaut1)
self.astronaut_list.append(self.astronaut2)

# 按钮角色生成
self.switchbutton.center_x = 100
self.switchbutton.center_y = 500

# 回地球的道具
self.home_glob.center_x = SCREEN_WIDTH//2 + 100
self.home_glob.center_y = SCREEN_HEIGHT//2 - 100

# 在随机位置产生几个氧气瓶  ，可以单独定义函数让它不在星星的位置生成
[self.oxygen_list.append(Oxygen("cloud.png")) for i in range(3)]

def on_key_press(self,key,modifiers):

if self.astronaut1.status == "live":
self.astronaut1.change_y = MOVEMENT_SPEED

self.astronaut1.angle = 90
self.astronaut1.change_y = -MOVEMENT_SPEED
self.astronaut1.angle = -90
self.astronaut1.change_x = -MOVEMENT_SPEED

self.astronaut1.angle =  180
self.astronaut1.change_x = MOVEMENT_SPEED

self.astronaut1.angle =  0

if self.astronaut2.status == "live":
self.astronaut2.change_y = MOVEMENT_SPEED
self.astronaut2.angle = 90
self.astronaut2.change_y = -MOVEMENT_SPEED
self.astronaut2.angle = -90
self.astronaut2.change_x = -MOVEMENT_SPEED
self.astronaut2.angle =  180
self.astronaut2.change_x = MOVEMENT_SPEED
self.astronaut2.angle =  0

def on_key_release(self, key, modifiers):
"""松开按键. """
if self.astronaut1.status == "live":
self.astronaut1.change_y = 0
self.astronaut1.change_x = 0

if self.astronaut2.status == "live":
self.astronaut2.change_y = 0
self.astronaut2.change_x = 0

def update(self, x):
"""每帧更新游戏内在逻辑"""

self.frame_counter += 1                                 # 帧计数
if self.frame_counter % 180 == 0 and len(self.oxygen_list)<20: # 2秒左右产生一个氧气瓶
self.oxygen_list.append(Oxygen("cloud.png"))

if self.astronaut1.status == "live":
if self.frame_counter % 10 == 0:                     # 宇航员的氧气数减1
if self.astronaut1.oxygens > 0:                  # 氧气数大于0，则不断减少，否则坠
self.astronaut1.oxygens -= 1

if self.astronaut1.oxygens == 0:                 # 宇航员1氧气为0，死了
self.astronaut1.change_y = -10

if self.astronaut2.status == "live":
if self.frame_counter % 10 == 0:                     # 宇航员2的氧气数减1
if self.astronaut2.oxygens > 0:                  # 氧气数大于0，则不断减少，否则坠
self.astronaut2.oxygens -= 1

if self.astronaut2.oxygens == 0:                 # 宇航员2氧气为0，死了
self.astronaut2.change_y = -10

# 宇航员1的碰撞检测
if  self.astronaut1.status  == "live":
for oxygen in oxygen_list1:
oxygen.kill()
self.astronaut1.oxygens += 100

if len(p) > 0:
self.astronaut1.oxygens = 0

# 宇航员2的碰撞检测
if  self.astronaut2.status  == "live":
for oxygen in oxygen_list2:
oxygen.kill()
self.astronaut2.oxygens += 100

if len(p) > 0:
self.astronaut2.oxygens = 0

if b :
self.switchbutton.set_texture(1)                                                    # 切换到橙色按钮
MyGame.timespace = 0.1
else:
self.switchbutton.set_texture(0)
MyGame.timespace = 1

if not MyGame.can_home:
if b : MyGame.can_home = True
else:
for a in a_list:
a.kill()

self.all_stars_list.update()
self.home_glob.update()
self.oxygen_list.update()
self.astronaut_list.update()
if self.astronaut1.status=="live":
if self.astronaut1.left <=0  :self.astronaut1.left=0
if self.astronaut1.right >= SCREEN_WIDTH-1:self.astronaut1.right=SCREEN_WIDTH-1
if self.astronaut1.bottom <=0  :self.astronaut1.bottom=0
if self.astronaut1.top >= SCREEN_HEIGHT-1:self.astronaut1.top=SCREEN_HEIGHT-1
if self.astronaut2.status=="live":
if self.astronaut2.left <=0  :self.astronaut2.left=0
if self.astronaut2.right >= SCREEN_WIDTH-1:self.astronaut2.right=SCREEN_WIDTH-1
if self.astronaut2.bottom <=0  :self.astronaut2.bottom=0
if self.astronaut2.top >= SCREEN_HEIGHT-1:self.astronaut2.top=SCREEN_HEIGHT-1

i = int(1/MyGame.timespace)     # 时空变慢，太阳换造型的时间变慢
if self.frame_counter % i == 0:
self.sun.update_animation() # 太阳的坐标不变，所以没有调用它的update

def on_draw(self):
"""
渲染屏幕        """

self.background.draw()       #  画背景
self.switchbutton.draw()
if not MyGame.can_home:self.home_glob.draw()
self.sun.draw()
self.all_stars_list.draw()   # 所有星星一起渲染
self.oxygen_list.draw()
self.astronaut_list.draw()

if  self.astronaut1.status  == "live":
output = f"宇航员1氧气数: {self.astronaut1.oxygens}"
if  self.astronaut2.status  == "live":
output = f"宇航员2氧气数: {self.astronaut2.oxygens}"

if MyGame.can_home and len(self.astronaut_list) == 0 :
output = f"恭喜，宇航员们安全返回了地球"

def main():
""" Main method """
window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
window.setup()