# python街机游戏行星破碎机

### Python海龟宝典含200多个原创的用turtle模块制作的创意程序，原名《Python趣味编程200例》。准备参加全国创意编程与智能设计大赛的同学们可以用来做参考。

```"""

"""
import random
import math
import os

SCALE = 0.5
OFFSCREEN_SPACE = 300
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
LEFT_LIMIT = -OFFSCREEN_SPACE
RIGHT_LIMIT = SCREEN_WIDTH + OFFSCREEN_SPACE
BOTTOM_LIMIT = -OFFSCREEN_SPACE
TOP_LIMIT = SCREEN_HEIGHT + OFFSCREEN_SPACE

""" 把角色的移动向量转换成角度值。 """
def update(self):
super().update()
self.angle = math.degrees(math.atan2(self.change_y, self.change_x))

"""
"""
def __init__(self, filename, scale):
""" 初始化飞船 """

# 调用父类的初始化方法
super().__init__(filename, scale)

# Info on where we are going.
# Angle comes in automatically from the parent class.
self.thrust = 0
self.speed = 0
self.max_speed = 4
self.drag = 0.05
self.respawning = 0

# Mark that we are respawning.
self.respawn()

def respawn(self):
"""
当飞船碰到小行星时要重生，respawning变量是无敌时间计时器
"""
# If we are in the middle of respawning, this is non-zero.
self.respawning = 1
self.center_x = SCREEN_WIDTH / 2
self.center_y = SCREEN_HEIGHT / 2
self.angle = 0

def update(self):
"""
更新坐标和其它值
"""
if self.respawning:
self.respawning += 1
self.alpha = self.respawning / 500.0
if self.respawning > 250:
self.respawning = 0
self.alpha = 1
if self.speed > 0:
self.speed -= self.drag
if self.speed < 0:
self.speed = 0

if self.speed < 0:
self.speed += self.drag
if self.speed > 0:
self.speed = 0

self.speed += self.thrust
if self.speed > self.max_speed:
self.speed = self.max_speed
if self.speed < -self.max_speed:
self.speed = -self.max_speed

self.change_x = -math.sin(math.radians(self.angle)) * self.speed
self.change_y = math.cos(math.radians(self.angle)) * self.speed

self.center_x += self.change_x
self.center_y += self.change_y

"""调用父类的方法. """
super().update()

""" 行星类 """

def __init__(self, image_file_name, scale):
super().__init__(image_file_name, scale=scale)
self.size = 0

def update(self):
""" 移动小行星. """
super().update()
if self.center_x < LEFT_LIMIT:
self.center_x = RIGHT_LIMIT
if self.center_x > RIGHT_LIMIT:
self.center_x = LEFT_LIMIT
if self.center_y > TOP_LIMIT:
self.center_y = BOTTOM_LIMIT
if self.center_y < BOTTOM_LIMIT:
self.center_y = TOP_LIMIT

class BulletSprite(TurningSprite):
"""
代表一个子弹的类
"""

def update(self):
super().update()
if self.center_x < -100 or self.center_x > 1500 or \
self.center_y > 1100 or self.center_y < -100:
self.kill()

""" Main application class. """

def __init__(self):
super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT,"行星破碎机:翻译：李兴球")

self.frame_count = 0

self.game_over = False

# 角色列表
self.all_sprites_list = None
self.asteroid_list = None
self.bullet_list = None
self.ship_life_list = None

# 玩家角色
self.score = 0
self.player_sprite = None
self.lives = 3

# 射击音效

def start_new_game(self):
""" 设置游戏和初始化变量. """

self.frame_count = 0
self.game_over = False

self.all_sprites_list = arcade.SpriteList() # 实例化所有角色列表
self.asteroid_list = arcade.SpriteList()    # 实例化小行星列表
self.bullet_list = arcade.SpriteList()      # 实例化子弹列表
self.ship_life_list = arcade.SpriteList()   #实例化显示飞般生命个数的列表

# 设置玩家
self.score = 0
self.player_sprite = ShipSprite("images/playerShip1_orange.png", SCALE)
self.all_sprites_list.append(self.player_sprite)
self.lives = 3

# 代表飞船生命个数.
cur_pos = 10
for i in range(self.lives):
life = arcade.Sprite("images/playerLife1_orange.png", SCALE)
life.center_x = cur_pos + life.width
life.center_y = life.height
cur_pos += life.width
self.all_sprites_list.append(life)
self.ship_life_list.append(life)

# 生成小行星
image_list = ("images/meteorGrey_big1.png",
"images/meteorGrey_big2.png",
"images/meteorGrey_big3.png",
"images/meteorGrey_big4.png")
for i in range(3):                      # 生成三个大的小行星
image_no = random.randrange(4)      # 随机选择一图
enemy_sprite = AsteroidSprite(image_list[image_no], SCALE)

enemy_sprite.center_y = random.randrange(BOTTOM_LIMIT, TOP_LIMIT)
enemy_sprite.center_x = random.randrange(LEFT_LIMIT, RIGHT_LIMIT)

enemy_sprite.change_x = random.random() * 2 - 1
enemy_sprite.change_y = random.random() * 2 - 1

enemy_sprite.change_angle = (random.random() - 0.5) * 2
enemy_sprite.size = 4
self.all_sprites_list.append(enemy_sprite)
self.asteroid_list.append(enemy_sprite)

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

# 开始渲染

# 画所有的角色
self.all_sprites_list.draw()

# 放置得分情况
output = f"得分: {self.score}"

output = f"小行星数量: {len(self.asteroid_list)}"

def on_key_press(self, symbol, modifiers):
""" 按任意键时调用此方法. """
# 如果我们不在重生阶段，并且按了空格键就射击
if not self.player_sprite.respawning and symbol == arcade.key.SPACE:
bullet_sprite = BulletSprite("images/laserBlue01.png", SCALE)

bullet_speed = 13
bullet_sprite.change_y = \
bullet_sprite.change_x = \
* bullet_speed

bullet_sprite.center_x = self.player_sprite.center_x
bullet_sprite.center_y = self.player_sprite.center_y
bullet_sprite.update()

self.all_sprites_list.append(bullet_sprite)
self.bullet_list.append(bullet_sprite)

if symbol == arcade.key.LEFT:
self.player_sprite.change_angle = 3
elif symbol == arcade.key.RIGHT:
self.player_sprite.change_angle = -3
elif symbol == arcade.key.UP:
self.player_sprite.thrust = 0.15
elif symbol == arcade.key.DOWN:
self.player_sprite.thrust = -.2

def on_key_release(self, symbol, modifiers):
""" 松开某键时调用此方法. """
if symbol == arcade.key.LEFT:
self.player_sprite.change_angle = 0
elif symbol == arcade.key.RIGHT:
self.player_sprite.change_angle = 0
elif symbol == arcade.key.UP:
self.player_sprite.thrust = 0
elif symbol == arcade.key.DOWN:
self.player_sprite.thrust = 0

def split_asteroid(self, asteroid: AsteroidSprite):
""" 行星分裂. """
x = asteroid.center_x
y = asteroid.center_y
self.score += 1

if asteroid.size == 4:
for i in range(3):
image_no = random.randrange(2)
image_list = ["images/meteorGrey_med1.png",
"images/meteorGrey_med2.png"]

enemy_sprite = AsteroidSprite(image_list[image_no],
SCALE * 1.5)

enemy_sprite.center_y = y
enemy_sprite.center_x = x

enemy_sprite.change_x = random.random() * 2.5 - 1.25
enemy_sprite.change_y = random.random() * 2.5 - 1.25

enemy_sprite.change_angle = (random.random() - 0.5) * 2
enemy_sprite.size = 3

self.all_sprites_list.append(enemy_sprite)
self.asteroid_list.append(enemy_sprite)
elif asteroid.size == 3:
for i in range(3):
image_no = random.randrange(2)
image_list = ["images/meteorGrey_small1.png",
"images/meteorGrey_small2.png"]

enemy_sprite = AsteroidSprite(image_list[image_no],
SCALE * 1.5)

enemy_sprite.center_y = y
enemy_sprite.center_x = x

enemy_sprite.change_x = random.random() * 3 - 1.5
enemy_sprite.change_y = random.random() * 3 - 1.5

enemy_sprite.change_angle = (random.random() - 0.5) * 2
enemy_sprite.size = 2

self.all_sprites_list.append(enemy_sprite)
self.asteroid_list.append(enemy_sprite)
elif asteroid.size == 2:
for i in range(3):
image_no = random.randrange(2)
image_list = ["images/meteorGrey_tiny1.png",
"images/meteorGrey_tiny2.png"]

enemy_sprite = AsteroidSprite(image_list[image_no],
SCALE * 1.5)

enemy_sprite.center_y = y
enemy_sprite.center_x = x

enemy_sprite.change_x = random.random() * 3.5 - 1.75
enemy_sprite.change_y = random.random() * 3.5 - 1.75

enemy_sprite.change_angle = (random.random() - 0.5) * 2
enemy_sprite.size = 1

self.all_sprites_list.append(enemy_sprite)
self.asteroid_list.append(enemy_sprite)

def update(self, x):
""" Move everything """

self.frame_count += 1

if not self.game_over:
self.all_sprites_list.update()

for bullet in self.bullet_list:
# 如果碰到行星，就分裂
asteroids = arcade.check_for_collision_with_list(bullet, self.asteroid_list)
for asteroid in asteroids:
self.split_asteroid(asteroid)
asteroid.kill()
bullet.kill()

if not self.player_sprite.respawning:
asteroids = \
self.asteroid_list)
if len(asteroids) > 0:
if self.lives > 0:
self.lives -= 1
self.player_sprite.respawn()
self.split_asteroid(asteroids[0])
asteroids[0].kill()
self.ship_life_list.pop().kill()
print("Crash")
else:
self.game_over = True
print("Game over")

def main():
window = MyGame()
window.start_new_game()