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

小学生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 问题


小学生python游戏编程arcade----碰撞精灵消失问题_第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次。
可以关注我,点赞我、评论我、收藏我啦。

你可能感兴趣的:(助孩成长,python,游戏,开发语言)