小学生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.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次。
可以关注我,点赞我、评论我、收藏我啦。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 我可以帮你使用Pythonarcade库来创建一个平台类游戏arcade库提供了一个简单而强大的API,可以帮助你创建2D游戏。它还有一个文档,可以帮助你开始创建游戏,并且拥有许多示例代码,可以让你学习如何使用这个库。 ### 回答2: 使用Pythonarcade库可以很方便地制作平台类游戏arcade库提供了许多内置函数和类,用于处理游戏循环、精灵碰撞检测等常见的游戏开发任务。 首先,我们需要创建一个游戏窗口。通过arcade库提供的Window类,我们可以创建一个指定大小的窗口,并设置背景颜色。 接下来,我们可以创建角色或者其他游戏中的物体,这些物体被称为精灵arcade库提供了Sprite类用于创建精灵。我们可以设置精灵的外观、位置、大小等属性。 在游戏循环中,我们可以监听用户输入,例如键盘按键、鼠标点击等事件。通过事件处理函数,我们可以根据用户的操作来更新精灵的状态。 在平台类游戏中,通常会涉及到角色的跳跃、移动、碰撞检测等功能。arcade库提供了一些内置函数和方法来处理这些功能。例如,我们可以使用移动函数来控制角色的水平和垂直移动。我们还可以使用碰撞检测函数来判断角色是否与其他物体发生了碰撞。 此外,arcade库还可以处理音效、动画等高级功能,以及绘制背景、地图等元素。它还提供了一些内置的工具函数,用于计算距离、旋转等常见操作。 总的来说,使用Pythonarcade库可以实现一个简单而又有趣的平台类游戏。通过利用arcade库提供的丰富功能,可以很方便地创建精灵、处理用户输入、实现碰撞检测等游戏开发任务。无论是新手还是有经验的开发者,都可以轻松上手使用arcade库制作自己的平台类游戏。 ### 回答3: 使用Pythonarcade库可以很方便地制作平台类游戏。首先,我们需要导入arcade库。然后创建一个继承自arcade.Window的类,作为游戏窗口。 在窗口类中,我们可以定义一些属性,比如玩家的位置和角色模型等。然后,我们可以使用arcade库提供的绘图函数来渲染游戏界面。 接着,我们可以定义一些事件处理函数,比如按键事件或鼠标事件。根据不同的事件,我们可以更新游戏状态,比如移动玩家或触发一些特殊的效果。 在游戏循环中,我们可以使用arcade库提供的定时器函数来设定游戏帧率。每一帧,我们可以调用draw函数来绘制游戏界面,并在需要时更新游戏状态。 此外,我们可以使用arcade库提供的物理引擎功能,比如重力或碰撞检测,来增加游戏的真实性和挑战性。 最后,当玩家达到游戏的胜利条件或失败条件时,我们可以显示游戏结束画面,并提供一些重新开始或退出游戏的选项。 总的来说,使用Pythonarcade库可以很方便地制作一个平台类游戏。通过定义游戏窗口、绘制游戏界面、处理事件和更新游戏状态等步骤,我们可以创建一个有趣且具有挑战性的游戏体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信息化未来

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值