""" 行星破碎机,按空格键射击太空中的小行星,方向键操作飞船移动。 """ import random import math import arcade 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 class TurningSprite(arcade.Sprite): """ 把角色的移动向量转换成角度值。 """ def update(self): super().update() self.angle = math.degrees(math.atan2(self.change_y, self.change_x)) class ShipSprite(arcade.Sprite): """ 飞船角色,继承自内置的arcade.Sprite类 """ 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() class AsteroidSprite(arcade.Sprite): """ 行星类 """ 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() class MyGame(arcade.Window): """ 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 # 射击音效 self.laser_sound = arcade.load_sound("sounds/laser1.wav") 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): """ 渲染屏幕 """ # 开始渲染 arcade.start_render() # 画所有的角色 self.all_sprites_list.draw() # 放置得分情况 output = f"得分: {self.score}" arcade.draw_text(output, 10, 70, arcade.color.WHITE, 14) output = f"小行星数量: {len(self.asteroid_list)}" arcade.draw_text(output, 10, 50, arcade.color.WHITE, 14) 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 = \ math.cos(math.radians(self.player_sprite.angle)) * bullet_speed bullet_sprite.change_x = \ -math.sin(math.radians(self.player_sprite.angle)) \ * 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) arcade.play_sound(self.laser_sound) 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 = \ arcade.check_for_collision_with_list(self.player_sprite, 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() arcade.run() if __name__ == "__main__": main()
李兴球
李兴球的博客是Python创意编程原创博客
要发表评论,您必须先登录。
发表评论