小学生python游戏编程arcade----碰撞精灵消失问题
- 前言
- 碰撞精灵消失问题
- 1、多余的精灵不能及时消失
- 1.1 问题
- 1.2 失败代码
- 1.3 记录备忘
- 1.4 代码实现
 
- 2、放置位置
- 2.1 代码放在ondraw中可以
- 2.2 在update中也可以
- 2.3 碰撞中
 
- 3、玩家子弹击中敌坦克后的爆炸效果
- 3.1 爆炸类
- 3.2 爆炸列表准备(setup中)
- 3.3 碰撞检测中加入后出现如此错误
- 3.4 代码修改`
- 3.5 效果
 
 
- 源码获取
 
前言
在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.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.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)
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)
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()
最终先确定放在碰撞中吧
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
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()
3.2 爆炸列表准备(setup中)
    # 爆炸
    self.setup_explosion_piclist()
    self.explosions_list = arcade.SpriteList()
    同时在ondraw中增加
            self.explosions_list.draw()
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)
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()
3.5 效果

源码获取
可关注博主后,私聊博主免费获取
 需要技术指导,育娃新思考,企业软件合作等更多服务请联系博主
今天是以此模板持续更新此育儿专栏的第 29/50次。
 可以关注我,点赞我、评论我、收藏我啦。



















