• 小学生python游戏编程arcade----碰撞精灵消失问题


    前言

    在arcade游戏编程中的碰撞精灵消失问题,敌人子弹打中角色后,如有多个子弹,坦克的消失问题分析,动画爆炸效果的实现及过程中注意事项及错误试验分析

    碰撞精灵消失问题

    1、多余的精灵不能及时消失

    1.1 问题

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    1.2 失败代码

    失败代码:

            if self.enemy_reset:
                # 重置坦克及子弹
                # for dr in self.scene[LAYER_tanks]:
                #     dr.remove_from_sprite_lists()
                # for zd in self.scene[LAYER_bullet]:
                #     zd.remove_from_sprite_lists()
                #
                # if len(self.scene[LAYER_tanks])>0:
                #     print('重清空坦克')
                #     for dr in self.scene[LAYER_tanks]:
                #         dr.remove_from_sprite_lists()
                #
                # if len(self.scene[LAYER_bullet])>0:
                #     print('重清空')
                #     for zd in self.scene[LAYER_bullet]:
                #         zd.remove_from_sprite_lists()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    1.3 记录备忘

    在update,draw中都会出现此问题,通过查看scene原码
    发现其有个remove_sprite_list_by_name函数,得以解决
    def remove_sprite_list_by_name(
    self,
    name: str,
    ) -> None:
    “”"
    Remove a SpriteList by it’s name.

        This function serves to completely remove the SpriteList from the Scene.
    
        :param str name: The name of the SpriteList to remove.
        """
        sprite_list = self.name_mapping[name]
        self.sprite_lists.remove(sprite_list)
        del self.name_mapping[name]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1.4 代码实现
            if self.enemy_reset:
                # 重置坦克及子弹
                # for dr in self.scene[LAYER_tanks]:
                #     dr.remove_from_sprite_lists()
                # for zd in self.scene[LAYER_bullet]:
                #     zd.remove_from_sprite_lists()
                #
                # if len(self.scene[LAYER_tanks])>0:
                #     print('重清空坦克')
                #     for dr in self.scene[LAYER_tanks]:
                #         dr.remove_from_sprite_lists()
                #
                # if len(self.scene[LAYER_bullet])>0:
                #     print('重清空')
                #     for zd in self.scene[LAYER_bullet]:
                #         zd.remove_from_sprite_lists()
                self.scene.remove_sprite_list_by_name(LAYER_bullet)
                self.scene.remove_sprite_list_by_name(LAYER_tanks)
                self.scene.add_sprite_list_after(LAYER_bullet, 'wj')
                self.scene.add_sprite_list_after(LAYER_tanks, 'wj')
                print('清空后',len(self.scene[LAYER_bullet]))
                print('清空后坦克',len(self.scene[LAYER_tanks]))
                self.setup_enemy()
                self.enemy_reset = False
                return
            else:
                self.scene.draw()  # 摄相机与scence的顺序不能放错,否则不会移动
                for aa in self.scene[LAYER_tanks]:
                    aa.draw_word(aa.left, aa.top + 20)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    2、放置位置

    2.1 代码放在ondraw中可以
        def on_draw(self):
            self.clear()
            self.camera.use()  # 摄象机
            # if self.enemy_reset:
            #     # 重置坦克及子弹
            #     self.scene.remove_sprite_list_by_name(LAYER_bullet)
            #     self.scene.remove_sprite_list_by_name(LAYER_tanks)
            #     self.scene.add_sprite_list_after(LAYER_bullet, 'wj')
            #     self.scene.add_sprite_list_after(LAYER_tanks, 'wj')
            #     self.setup_enemy()
            #     self.enemy_reset = False
            # else:
            self.scene.draw()  # 摄相机与scence的顺序不能放错,否则不会移动
            for aa in self.scene[LAYER_tanks]:
                aa.draw_word(aa.left, aa.top + 20)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    2.2 在update中也可以
        def on_update(self, delta_time: float):
            self.physics_engine.update()  # 运用引擎移动角色
            self.collision_all()
    
            self.update_remind()
            self.scene['wj'].update()
            
            if self.enemy_reset:
                # 重置坦克及子弹
                self.scene.remove_sprite_list_by_name(LAYER_bullet)
                self.scene.remove_sprite_list_by_name(LAYER_tanks)
                self.scene.add_sprite_list_after(LAYER_bullet, 'wj')
                self.scene.add_sprite_list_after(LAYER_tanks, 'wj')
                self.setup_enemy()
                self.enemy_reset = False
    
            self.scene[LAYER_bullet].update()
            self.scene[LAYER_explosions].update()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    最终先确定放在碰撞中吧

    2.3 碰撞中
        # 碰撞检测
        def collision_all(self):
            self.collision_bullet_enemy()
            self.collision_bullet_player()
            if self.enemy_reset:
                # 重置坦克及子弹
                self.scene.remove_sprite_list_by_name(LAYER_bullet)
                self.scene.remove_sprite_list_by_name(LAYER_tanks)
                self.scene.add_sprite_list_after(LAYER_bullet, 'wj')
                self.scene.add_sprite_list_after(LAYER_tanks, 'wj')
                self.setup_enemy()
                self.enemy_reset = False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3、玩家子弹击中敌坦克后的爆炸效果

    3.1 爆炸类
    # 爆炸动画
    class Explosion(arcade.Sprite):
        """ 爆炸动画 """
    
        def __init__(self, texture_list):
            super().__init__()
    
            #开始的第一幁
            self.current_texture = 0
            self.textures = texture_list
    
        def update(self):
            # 更新到动画的下一帧。如果我们到了终点,然后删除这个精灵。
            self.current_texture += 1
            if self.current_texture < len(self.textures):
                self.set_texture(self.current_texture)
            else:
                self.remove_from_sprite_lists()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    3.2 爆炸列表准备(setup中)
        # 爆炸
        self.setup_explosion_piclist()
        self.explosions_list = arcade.SpriteList()
        同时在ondraw中增加
                self.explosions_list.draw()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    3.3 碰撞检测中加入后出现如此错误

    在这里插入图片描述

                        # 爆炸(动画效果)
        def baozha(self,hit_list):
            # 制造爆炸
            explosion = Explosion(self.explosion_texture_list)
    
            # 位置
            explosion.center_x = hit_list[0].center_x
            explosion.center_y = hit_list[0].center_y
    
            # 更新爆炸
            explosion.update()
    
            # 添加列表
            self.explosions_list.append(explosion)
                    
                    for cc in hit_list:
                        if (self.scene[LAYER_tanks] in cc.sprite_lists):
                            # 磁撞的是敌人 根据子弹伤害及敌人生命值确定争分数及消失
                            cc.remove_from_sprite_lists()
                            # 声音
                            arcade.play_sound(self.hit_sound1)
                            # 爆炸效果
                            self.baozha(hit_list)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    3.4 代码修改`

    增加# 调用更新
    self.scene[LAYER_bullet_player].update()
    self.explosions_list.update()

    这句很关健

        def collision_bullet_player(self):
            # 调用更新
            ***self.scene[LAYER_bullet_player].update()
            self.explosions_list.update()***
            # 子弹的碰撞检测
            for bullet in self.scene[LAYER_bullet_player]:
                hit_list = arcade.check_for_collision_with_lists(
                    bullet,
                    [
                        self.scene[LAYER_tanks],
                        # self.scene[LAYER_tree],
                        self.scene['建筑物'],
                    ],
                )
    
                if hit_list:
                    bullet.remove_from_sprite_lists()
    
                    for cc in hit_list:
                        if (self.scene[LAYER_tanks] in cc.sprite_lists):
                            # 磁撞的是敌人 根据子弹伤害及敌人生命值确定争分数及消失
                            cc.remove_from_sprite_lists()
                            # 声音
                            arcade.play_sound(self.hit_sound1)
                            # 爆炸效果
                            self.baozha(hit_list)
    
                            if cc.hz == self.key:
                                self.score += 100
                                self.wanjia.bullets +=5
                                self.enemy_reset = True
    
                            else:
                                self.wanjia.life -= 2
                                print('打错了')
    
    
    
                        if (self.scene['建筑物'] in cc.sprite_lists):
                            # 磁撞的是建筑物,  制造爆炸
                            for i in range(20):
                                particle = Particle(self.scene[LAYER_explosions])
                                particle.position = cc.position  # 粒子位置,也即敌人位置
                                self.scene[LAYER_explosions].append(particle)
    
                            smoke = Smoke(30)
                            smoke.position = cc.position  # 烟雾位置
                            self.scene[LAYER_explosions].append(smoke)
    
                            cc.remove_from_sprite_lists()
    
                            # 爆炸声音
                            arcade.sound.play_sound(self.hit_sound2)
                    return
    
                # 如过子弹超过屏幕则删掉.
                if (bullet.right < 0) or (bullet.bottom > SCREEN_height) or (
                        bullet.left > (self.tile_map.width * self.tile_map.tile_width) * TILE_Scaling) :
                    bullet.remove_from_sprite_lists()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    3.5 效果

    在这里插入图片描述

    源码获取

    关注博主后,私聊博主免费获取
    需要技术指导,育娃新思考,企业软件合作等更多服务请联系博主

    今天是以此模板持续更新此育儿专栏的第 29/50次。
    可以关注我,点赞我、评论我、收藏我啦。

  • 相关阅读:
    【信号与系统】奇异信号的性质
    Spring Boot Controller
    内置数据库H2和内置Redis(测试结果来啦)
    【Designing ML Systems】第 11 章 :机器学习的人性方面
    地球人口承载力估计(c++基础)
    【博客542】k8s使用EndpointSlices扩展大规模service后端服务数量
    基于PyQt5和OpenCV库的简单的文档对齐扫描应用程序
    2023-mac rz sz 安装
    【快应用】实现自定义导航栏组件
    NEFU离散数学实验2-容斥原理
  • 原文地址:https://blog.csdn.net/fqfq123456/article/details/127979108