這是原來的錯誤代碼(只是其中一部分,主模塊(未寫完的)),其中的錯誤是自定義的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改成更大就好,卻忘記了去考慮受其影響的對象,因此程序員很重要的應該就是這種全局觀。
如有其它問題歡迎評論討論