Pygame飞机大战为什么飞机与敌机碰撞后不再有图片动态切换效果
程序员文章站
2024-03-16 19:37:52
...
这是原来的错误代码(只是其中一部分,主模块(未写完的)),其中的错误是自定义的delay引起的
import pygame as pg
import sys
import traceback
import Plane
import Enemy
import Bullet
pg.init()
pg.mixer.init()
pm = pg.mixer
pg.display.set_caption('飞机大战') #屏幕设置
running = True
clock = pg.time.Clock()
size = width,height = 480,700
screen = pg.display.set_mode(size)
bg = pg.image.load(r'images\background.png').convert()
pm.music.load('sound/game_music.ogg') #载入音乐
pm.music.set_volume(0.05)
bullet_sound = pm.Sound('sound/bullet.wav')
bullet_sound.set_volume(0.2)
bomb_sound = pm.Sound('sound/use_bomb.wav')
bomb_sound.set_volume(0.2)
supply_sound = pm.Sound('sound/supply.wav')
supply_sound.set_volume(0.2)
get_bomb_sound = pm.Sound('sound/get_bomb.wav')
get_bomb_sound.set_volume(0.2)
get_bullet_sound = pm.Sound('sound/get_bullet.wav')
get_bullet_sound.set_volume(0.2)
upgrade_sound = pm.Sound('sound/upgrade.wav')
upgrade_sound.set_volume(0.2)
enemy3_fly_sound = pm.Sound('sound/enemy3_flying.wav')
enemy3_fly_sound.set_volume(0.7)
enemy1_down_sound = pm.Sound('sound/enemy1_down.wav')
enemy1_down_sound.set_volume(0.1)
enemy2_down_sound = pm.Sound('sound/enemy2_down.wav')
enemy2_down_sound.set_volume(0.2)
enemy3_down_sound = pm.Sound('sound/enemy3_down.wav')
enemy3_down_sound.set_volume(0.5)
me_down_sound = pm.Sound('sound/me_down.wav')
me_down_sound.set_volume(0.05)
def add_enemys1(group1,group2,num):
for i in range(num):
e1 = Enemy.enemy1(size)
group1.add(e1)
group2.add(e1)
def add_enemys2(group1,group2,num):
for i in range(num):
e1 = Enemy.enemy2(size)
group1.add(e1)
group2.add(e1)
def add_enemys3(group1,group2,num):
for i in range(num):
e1 = Enemy.enemy3(size)
group1.add(e1)
group2.add(e1)
def add_bullets_1(group1,group2,num,plane):
for i in range(num):
e1 = Bullet.Bullet_1(size,plane)
group1.add(e1)
group2.add(e1)
def main():
me_switch = True #我方飞机动态切换
delay = 10
pm.music.play(-1) #-1意为无限循环此音乐
bullets_1 = [] #创建对象容器
enemys1 = []
enemys2 = []
enemys3 = []
me = Plane.MyPlane(size) #我方飞机实例化
groups = pg.sprite.Group()
enemys1 = pg.sprite.Group() #生成小型敌机
add_enemys1(enemys1,groups,15)
enemys2 = pg.sprite.Group() #生成中型敌机
add_enemys2(enemys2,groups,15)
enemys3 = pg.sprite.Group() #生成大型敌机
add_enemys3(enemys3,groups,15)
bullets_1 = pg.sprite.Group() #生成子弹
add_bullets_1(bullets_1,groups,150,me)
e1_destory_index = 0 #毁灭图像集合索引
e2_destory_index = 0
e3_destory_index = 0
me_destory_index = 0
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit() #这个必须在sys.quit前面,否则程序冲突
sys.exit()
key_pressed = pg.key.get_pressed() #获得哪些按键被长按
if key_pressed[pg.K_w]: #游戏操作
me.moveUp()
if key_pressed[pg.K_s]:
me.moveDown()
if key_pressed[pg.K_a]:
me.moveLeft()
if key_pressed[pg.K_d]:
me.moveRight()
screen.blit(bg,(0,0))
collide = pg.sprite.spritecollide(me,groups,False,pg.sprite.collide_mask) #碰撞检测
if collide:
me.alive = False
for each in collide:
each.alive = False
delay -= 1 #我方飞机动态切换
if me.alive:
if me_switch:
screen.blit(me.image1,me.rect)
else:
screen.blit(me.image2,me.rect)
if not delay :
me_switch = not me_switch
delay = 10
else: #毁灭
if not (delay % 3):
me_down_sound.play()
screen.blit(me.destory_images[me_destory_index],me.rect)
me_destory_index = (me_destory_index+1) % 4
if me_destory_index == 0:
me.reset()
for each in bullets_1:
if not (delay%10):
each.Flying(me)
screen.blit(each.image,each.rect)
for each in enemys3: #引入大型敌机
if each.alive:
each.moveEnemy3(enemy3_fly_sound)
if each.rect.bottom == -0.5*each.rect.height or each.rect.bottom == 0:
enemy3_fly_sound.play(-1)
if me_switch:
screen.blit(each.image1,each.rect)
else:
screen.blit(each.image2,each.rect)
else: #毁灭
if not (delay % 3):
enemy3_down_sound.play()
enemy3_fly_sound.stop()
screen.blit(each.destory_images[e3_destory_index],each.rect)
e3_destory_index = (e3_destory_index+1) % 6
if e3_destory_index == 0:
each.reset( )
for each in enemys2: #引入中型敌机
if each.alive:
each.moveEnemy2()
screen.blit(each.image1,each.rect)
else: #毁灭
if not (delay % 3):
enemy2_down_sound.play()
screen.blit(each.destory_images[e2_destory_index],each.rect)
e2_destory_index = (e2_destory_index+1) % 4
if e2_destory_index == 0:
each.reset( )
for each in enemys1: #引入小型敌机
if each.alive:
each.moveEnemy1()
screen.blit(each.image1,each.rect)
else: #毁灭
if not (delay % 3):
enemy1_down_sound.play()
screen.blit(each.destory_images[e1_destory_index],each.rect)
e1_destory_index = (e1_destory_index+1) % 4
if e1_destory_index == 0:
each.reset( )
pg.display.flip()
clock.tick(60)
if __name__ == '__main__':
try:
main( )
except SystemExit:
pass
except :
traceback.print_exc()
pg.quit()
input()`在这里插入代码片`
其中错误的主要备份如下
delay = 10
.......
if collide:
me.alive = False
for each in collide:
each.alive = False
delay -= 1 #我方飞机动态切换
if me.alive:
if me_switch:
screen.blit(me.image1,me.rect)
else:
screen.blit(me.image2,me.rect)
if not delay :
me_switch = not me_switch
delay = 10
else: #毁灭
if not (delay % 3):
me_down_sound.play()
screen.blit(me.destory_images[me_destory_index],me.rect)
me_destory_index = (me_destory_index+1) % 4
if me_destory_index == 0:
me.reset()
其中的delay赋值太小(delay=10),进行碰撞检测后飞机处于me.alive = False的状态,而此时的帧数delay仍然在随着pygame的帧率随时间减少,并且这一块代码中if me.alive:是一直不会运行的,导致其中的if not delay:也失去了他本来具有的检测功能。
碰撞检测的时间较长(我做了测试计算,在后面的飞机爆炸动画中算出大约12帧左右),因此在这段时间内,delay早已被减小的小过了0,因此在碰撞后,if not delay:
已经不再具有检测作用,从而导致在其中的飞机动态开关不再会打开或关闭,导致了飞机与敌机碰撞后不再有图片动态切换效果。
既然原因已经分析出来,那么解决方案就显而易见了。
解决方案1:
直接把if not delay: 改成 if (delay <= 0): 即可,这个方法的好处是不需去改变其他对象或者参数的值。
解决方案2:
把代码中的delay = 10 改为更大的数,多大自己具体决定,但值得注意的是,下面的if not delay:也需要修改,否则飞机动态切换一次的帧数就随之变大了(以及其他涉及delay变量的对象也可能会随之改变),可以改成常用的if not (delay%10): 方法来解决。
从这个解决方案可以反思到程序员应该具备的一个特点就是 “ 不是哪里出错,就像打补丁一样补上去,而是认真分析代码,把根本性的原因找出来”。否则很可能像解决方案2一样只记得了把delay改成更大就好,却忘记了去考虑受其影响的对象,因此程序员很重要的应该就是这种全局观。
如有其它问题欢迎评论讨论