• 一个失败的案例


    from arcadegame.guigl import *
    from arcadegame.mysprite import *
    from arcadegame.tank import *
    import os
    
    
    class GameView(arcade.View):
        def __init__(self):
            super().__init__()
            self.scene = None
            self.wanjia = None
    
            file_path = os.path.dirname(os.path.abspath(__file__))
            os.chdir(file_path)
    
            arcade.set_background_color(arcade.csscolor.BLUE)
    
            self.physics_engine = None
            self.camera = None  # 摄象机
            self.gui_camera = None  # 第二摄象机
            self.score = 0
            # 加载声音
            self.collect_coin_sound = arcade.load_sound("sounds/coin2.wav")
            self.jump_sound = arcade.load_sound("sounds/s3.wav")
            self.game_over = arcade.load_sound(":resources:sounds/gameover1.wav")
            self.shoot_sound = arcade.load_sound(":resources:sounds/hurt5.wav")
            self.hit_sound = arcade.load_sound(":resources:sounds/hit5.wav")
    
            # 设置地图
            self.tile_map = None
            # 是否重新设置分数
            self.reset_score = True
            # 地图的最右边
            self.end_of_map = 0
            # 关卡级别
            self.level = 1
    
            # 射击
            self.shoot_pressed = False
            self.can_shoot = False
            self.shoot_timer = 0
    
            self.tank_direction = 0.0  # # 前进和后退油门
            self.tank_turning = 0.0  # 向左或向右转的力度
            self.mouse_pos = 0, 0
    
            self.view_bottom = 0
            self.view_left = 0
    
        def setup(self):
            # 摄象机
            self.camera = arcade.Camera(SCREEN_width, SCREEN_height)
            self.gui_camera = arcade.Camera(SCREEN_width, SCREEN_height)
    
            # 初始化场景
            map_name = f"地图\家2.json"  # jia{self.level}.json"
            # 层属性
            layer_options = {
                LAYER_platforms: {
                    "use_spatial_hash": True,
                },
                LAYER_tree: {
                    "use_spatial_hash": False,
                },
                'fz': {
                    "use_spatial_hash": True,
                },
                # 'tizi': {
                #     "use_spatial_hash": True,
                # },
                'Enemies': {
                    "use_spatial_hash": True,
                },
            }
    
            # 读地图文件
            self.tile_map = arcade.load_tilemap(map_name, TILE_Scaling, layer_options)
             # 使用我们的TileMap初始化场景,这将自动添加所有层,以正确的顺序在场景中显示为SpriteList。
            self.scene = arcade.Scene.from_tilemap(self.tile_map)
            print('精灵列表', self.scene['fz'])
    
            if self.reset_score:
                self.score = 0
            self.reset_score = True
    
            self.end_of_map = self.tile_map.width * GRID_pixel_size
    
    
            # 添加角色.
            self.wanjia = Tanke()
            self.wanjia.tank.center_x = PLAYER_start_x
            self.wanjia.center_y = PLAYER_start_y
            self.scene.add_sprite("wj", self.wanjia.tank)
            self.scene.add_sprite("wj", self.wanjia.barrel)
    
            self.scene.add_sprite_list_after("wj", LAYER_platforms)  # 添加精灵列表,把玩家放在哪一层,前后层在此关健
            self.scene.add_sprite("wj",self.wanjia)
            self.physics_engine = arcade.PhysicsEngineSimple(
                self.wanjia,
                walls=self.scene['fz'])
    
            # -- 敌人 Enemies
            enemies_layer = self.tile_map.object_lists['Enemies']
    
            for my_object in enemies_layer:
                cartesian = self.tile_map.get_cartesian(
                    my_object.shape[0], my_object.shape[1]
                )
    
                enemy_type = my_object.properties["type"]
                if enemy_type == "robot":
                    enemy = RobotEnemy()
                elif enemy_type == "zombie":
                    enemy = ZombieEnemy()
                else:
                    raise Exception(f"Unknown enemy type {enemy_type}.")
                enemy.center_x = math.floor(
                    cartesian[0] * TILE_Scaling * self.tile_map.tile_width
                )
                enemy.center_y = math.floor(
                    (cartesian[1] + 1) * (self.tile_map.tile_height * TILE_Scaling)
                )
                self.scene.add_sprite(LAYER_enemies, enemy)
    
                if "boundary_left" in my_object.properties:
                    enemy.boundary_left = my_object.properties["boundary_left"]
                if "boundary_right" in my_object.properties:
                    enemy.boundary_right = my_object.properties["boundary_right"]
                if "change_x" in my_object.properties:
                    enemy.change_x = my_object.properties["change_x"]
    
            # 子弹
            self.can_shoot = True
            self.shoot_timer = 0
            # 增加子弹层
            self.scene.add_sprite_list(LAYER_bullet)
    
        def on_show_view(self):
            self.setup()
    
        def on_key_press(self, key: int, modifiers: int):
            if key == arcade.key.W or key == arcade.key.UP:
                self.tank_direction += 1
            elif key == arcade.key.DOWN or key == arcade.key.S:
                self.tank_direction -= 1
            elif key == arcade.key.LEFT or key == arcade.key.A:
                self.tank_turning += 1
            elif key == arcade.key.RIGHT or key == arcade.key.D:
                self.tank_turning -= 1
            elif key == arcade.key.SPACE:
                self.shoot_pressed = True
    
        def on_key_release(self, key: int, modifiers: int):
            if key == arcade.key.W or key == arcade.key.UP:
                self.tank_direction -= 1
            elif key == arcade.key.DOWN or key == arcade.key.S:
                self.tank_direction += 1
            elif key == arcade.key.LEFT or key == arcade.key.A:
                self.tank_turning -= 1
            elif key == arcade.key.RIGHT or key == arcade.key.D:
                self.tank_turning += 1
            elif key == arcade.key.SPACE:
                self.shoot_pressed = False
    
        def on_mouse_motion(self, x: int, y: int, dx: int, dy: int):
            self.mouse_pos = x, y
    
        def on_click_start(self, event):
            print("自定义方法调用--开始:", event)
    
        def on_draw(self):
            self.clear()
            self.camera.use()  # 摄象机
            self.scene.draw()  # 摄相机与scence的顺序不能放错,否则不会移动
            self.gui_camera.use()
            # 在屏幕上绘制分数,用屏幕滚动
            score_text = f"得分: {self.score}"
            arcade.draw_text(score_text, 10, 500, arcade.csscolor.RED, 18, )
            score_text = f"view-left-top: {self.view_left},{self.view_bottom}"
            arcade.draw_text(score_text, 10, 400, arcade.csscolor.RED, 18, )
            score_text = f"玩家: {self.wanjia.tank.center_x}"
            arcade.draw_text(score_text, 10, 600, arcade.csscolor.RED, 18, )
            # for enemy in self.scene[LAYER_enemies]:
            #     arcade.draw_text(enemy.string, enemy.left, enemy.top-80, arcade.csscolor.RED, 30, )
    
            # arcade.draw_text(str(int(self.wanjia.barrel.top))+';'+str(int(self.wanjia.barrel.left)), 10, 300, arcade.csscolor.RED, 18, )
    
        def center_camera_to_player(self):
            """摄相机随角色移动"""
            screen_center_x = self.wanjia.tank.center_x - (self.camera.viewport_width / 2)
            screen_center_y = self.wanjia.center_y - (self.camera.viewport_height / 2)
    
            # 防止相机出界
            if screen_center_x < 0:
                screen_center_x = 0
            if screen_center_y < 0:
                screen_center_y = 0
    
            player_centered = screen_center_x, screen_center_y
            # print(player_centered)
            self.camera.move_to(player_centered)
            print(self.wanjia.tank.center_x)
    
            # 定义一个相机边框的左边距离
            left_boundary = self.view_left + (self.camera.viewport_width / 2)
            if self.wanjia.tank.center_x < left_boundary:
                self.view_left -= left_boundary - self.wanjia.tank.center_x
            else:
                self.view_left += self.wanjia.tank.center_x - left_boundary
    
            top_boundary = self.view_bottom + (self.camera.viewport_height / 2)
            if self.wanjia.center_y < top_boundary:
                self.view_bottom -= left_boundary - self.wanjia.center_y
            else:
                self.view_bottom += self.wanjia.center_y - top_boundary
    
        def gxzidan(self):
            # 子弹加载
            if self.can_shoot:
                if self.shoot_pressed:
                    arcade.play_sound(self.shoot_sound)
                    bullet = arcade.Sprite(
                        ":resources:images/space_shooter/laserBlue01.png",
                        BULLET_scale,
                    )
                    # 开始点位置
                    start_x = self.wanjia.barrel.center_x
                    start_y = self.wanjia.barrel.center_y
    
    
                    # 从鼠标中获取项目符号的目标位置
                    # #重要!如果你有滚动屏幕,你还需要
                    # #添加self.view_bottom和self.view_left。
                    dest_x = self.mouse_pos[0]
                    dest_y = self.mouse_pos[1]
    
                    # Do math to calculate how to get the bullet to the destination.
                    # Calculation the angle in radians between the start points
                    # and end points. This is the angle the bullet will travel.
                    x_diff = dest_x - start_x
                    y_diff = dest_y - start_y
                    angle = math.atan2(y_diff, x_diff)
    
                    # Angle the bullet sprite so it doesn't look like it is flying
                    # sideways.
                    bullet.angle = math.degrees(angle)
                    print(f"子弹: {bullet.angle:.2f}")
                    print(f"炮台: {self.wanjia.barrel.angle:.2f}")
    
                    # Taking into account the angle, calculate our change_x
                    # and change_y. Velocity is how fast the bullet travels.
                    bullet.change_x = math.cos(angle) * BULLET_speed
                    bullet.change_y = math.sin(angle) * BULLET_speed
    
    
                    bullet.center_x = start_x+ math.cos(angle) *80
                    bullet.center_y = start_y+ math.sin(angle) *80
    
                    self.scene.add_sprite(LAYER_bullet, bullet)
    
                    self.can_shoot = False
            else:
                self.shoot_timer += 1
                if self.shoot_timer == SHOOT_speed:
                    self.can_shoot = True
                    self.shoot_timer = 0
    
        def bengchuang(self):
            # 子弹的碰撞检测
            for bullet in self.scene[LAYER_bullet]:
                hit_list = arcade.check_for_collision_with_lists(
                    bullet,
                    [
                        self.scene[LAYER_enemies],
                        self.scene[LAYER_tree],
                    ],
                )
    
                if hit_list:
                    bullet.remove_from_sprite_lists()
    
                    for collision in hit_list:
                        if (self.scene[LAYER_enemies] in collision.sprite_lists):
                            # The collision was with an enemy
                            collision.health -= BULLET_shanghai
    
                            if collision.health <= 0:
                                collision.remove_from_sprite_lists()
                                self.score += 100
    
                            # Hit sound
                            arcade.play_sound(self.hit_sound)
    
                    return
    
                if (bullet.right < 0) or (
                        bullet.left
                        > (self.tile_map.width * self.tile_map.tile_width) * TILE_Scaling
                ):
                    bullet.remove_from_sprite_lists()
    
            # 碰撞检测
            player_collision_list = arcade.check_for_collision_with_lists(
                self.wanjia,
                [
                    # self.scene[LAYER_tree],
                    self.scene[LAYER_enemies],
                ],
            )
    
            # 检测磁到的是硬币还是敌人
            for collision in player_collision_list:
                if self.scene[LAYER_enemies] in collision.sprite_lists:
                    arcade.play_sound(self.game_over)
                    self.setup()
                    return
                else:
                    # 算出这枚硬币值多少分
                    if "Points" not in collision.properties:
                        print("警告,收集的硬币没有点数属性.")
                    else:
                        points = int(collision.properties["Points"])
                        self.score += points
    
                    # Remove the coin
                    collision.remove_from_sprite_lists()
                    arcade.play_sound(self.collect_coin_sound)
    
            # # 是否走到地图尽头
            # if self.wanjia.tank.center_x >= self.end_of_map:
            #     # 关卡升级
            #     self.level += 1
            #     # 不需重新积分
            #     self.reset_score = False
            #     # 加载下个场景
            #     self.setup()
    
        def on_update(self, delta_time: float):
            # print(self.physics_engine)
            self.physics_engine.update()  # 运用引擎移动角色
            # dest = self.mouse_pos[0]+self.view_left, self.mouse_pos[1]+self.view_bottom
            self.wanjia.move_tank(delta_time,self.tank_turning,self.tank_direction,self.mouse_pos)
    
            # # 掉下或level达到最后一关时,游戏结束,或重新开始
            # if self.wanjia.center_y < -100 or self.level == 3:
            #     self.wanjia.tank.center_x = PLAYER_start_x
            #     self.wanjia.center_y = PLAYER_start_y
            #     arcade.play_sound(self.game_over)
    
            # 更新动画
            self.scene.update_animation(delta_time, [LAYER_enemies])
    
            # 看看敌人是否达到了边界,需要改变方向.
            for enemy in self.scene[LAYER_enemies]:
                if (
                        enemy.boundary_right
                        and enemy.right > enemy.boundary_right
                        and enemy.change_x > 0
                ):
                    enemy.change_x *= -1
    
                if (
                        enemy.boundary_left
                        and enemy.left < enemy.boundary_left
                        and enemy.change_x < 0
                ):
                    enemy.change_x *= -1
                # print(enemy.string)
                arcade.draw_text(enemy.string, enemy.center_x, enemy.center_y, arcade.csscolor.RED, 18, )
    
            # 子弹加载
            self.gxzidan()
            # 更新敌人及子弹
            self.scene.update([LAYER_enemies, LAYER_bullet])  #
    
    
            self.center_camera_to_player()  # 摄象机
    
    
    class MainMenu(arcade.View):
        """Class that manages the 'menu' view."""
    
        def on_show_view(self):
            """设置背景"""
            arcade.set_background_color(arcade.color.WHITE)
            self.g = GuiGL()
            # 初始化场景
            self.background = arcade.Sprite("images/坦克12.png", 1.4)
            self.background.center_x = SCREEN_width / 2
            self.background.center_y = SCREEN_height / 2
            # 设置背景色
            arcade.set_background_color(arcade.color.DARK_BLUE_GRAY)
    
            #  事件方法2,自定义方法函数
            self.g.start_button.on_click = self.on_click_start
    
        def on_draw(self):
            self.clear()
            self.background.draw()
            self.g.manager.draw()
            score_text = f"坦克大战"
            arcade.draw_text(
                score_text,
                SCREEN_width / 2-80,
                SCREEN_height / 2+220,
                arcade.csscolor.GOLD,
                30,
            )
    
        def on_click_start(self, event):
            print("自定义方法调用--开始:", event)
            game_view = GameView()
            self.window.show_view(game_view)
    
    
    class GameOverView(arcade.View):
        """结整界面"""
    
        def on_show_view(self):
            """设置背景"""
            arcade.set_background_color(arcade.color.BLACK)
    
        def on_draw(self):
            """Draw the game overview"""
            self.clear()
            arcade.draw_text(
                "游戏结束,点击重新开始",
                SCREEN_width / 2,
                SCREEN_height / 2,
                arcade.color.WHITE,
                30,
                anchor_x="center",
            )
    
        def on_mouse_press(self, _x, _y, _button, _modifiers):
            """Use a mouse press to advance to the 'game' view."""
            game_view = GameView()
            self.window.show_view(game_view)
    
    
    
    def main():
        """主函数"""
        window = arcade.Window(SCREEN_width, SCREEN_height, SCREEN_title)
        menu_view = MainMenu()
        window.show_view(menu_view)
        arcade.run()
    
    
    if __name__ == "__main__":
        main()
    
  • 相关阅读:
    vue项目升级vue3中小坑记录
    OSI参考模型个人总结
    Linux系统中如何更改用户密码,以及验证用户密码是否更改成功
    风景如画 全立交
    Vue---反向传值
    jQuery插件【validate】国际化校验插件
    JAVA设计模式-责任链模式
    【408】操作系统知识点(查漏补缺)
    集合深度学习09—HashMap源码解析
    在英特尔 CPU 上微调 Stable Diffusion 模型
  • 原文地址:https://blog.csdn.net/fqfq123456/article/details/127874609