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