Pygame飛機大戰爲什麼一按空格鍵所有炸彈都用光了?

關於這個問題,我最先想到的就是炸彈的使用方式是鍵盤按壓式,還是敲擊鍵盤式,(即key_pressed 或 KEYDOWN)。那麼現在你可以想想這裏有沒有弄錯了。
後來我發現確實是用了KEYDOWN的方法,還是出現這種狀況,那我就開始思考問題究竟出現在哪?

if not pause:        
	if event.type == pg.KEYDOWN:  #全屏炸彈
    	if event.key== pg.K_SPACE and bomb_count > 0:
    		bomb_count  -= 1
        	bomb_sound.play()
        	print('go on')
        	for each in groups:
            	if each.rect.bottom > 0:
            		each.alive = False

在這裏我就想到一個簡單方便檢測bug的方法,我在我要檢測錯誤的地方加上一條print語句,其中的內容並不重要,重要的是看print語句有沒有被執行,或者執行了幾次。(也可以寫成print(bomb_count),這樣可以直觀的看到炸彈數量的減少,而且是由這段代碼引起的)

結果卻如圖所示,go on 被打印了多次???
這時我就要思考了,爲什麼一個KEYDOWN的事件會背執行這麼多次??

這裏我就想到, 有沒有可能是因爲敵機爆炸的動畫延時了大概12幀左右導致的?但是我隨機就發現,我的if判斷語句好像沒有聯繫到敵機是否爆炸(即enemy.alive == False或者True),所以這個猜想是不太可能成立的。

於是我只能重新讀自己寫的又臭又長的代碼,自我感覺好像沒問題,這時我實在沒辦法,我就思考會不會是語句之間順序的問題???

我把前面那段代碼提到最前面,就像這樣:

while running:
        for event in pg.event.get(): 
        	if event.type == pg.KEYDOWN:
                    if event.key== pg.K_SPACE:  #全屏炸彈
                        bomb_count  -= 1
                        bomb_sound.play()
                    	for each in groups:
                       		if each.rect.bottom > 0:
                            	each.alive = False

然後我震驚的發現,再次按空格鍵,炸彈居然沒有再減少到 0 。這麼說就是語句順序出現了問題,於是我重新讀自己的代碼,原來未修改的錯誤代碼如下:

while running:
        for event in pg.event.get():                                                                                        
            if me.life == 0:
                running = False
            elif event.type == pg.QUIT:
                pg.quit()                    #這個必須在sys.quit前面,否則程序衝突
                sys.exit()
            elif event.type == SUPPLY:      #補給發放
                supply_sound.play()
                if random.choice([True,False]):                    
                    bo_supply.reset()
                else:
                    bu_supply.reset()
                
            elif event.type == pg.MOUSEBUTTONDOWN:          #鼠標點擊切換暫停
                if event.button == 1 and pause_rect.collidepoint(event.pos):
                    pause = not pause

            elif event.type == pg.MOUSEMOTION:
                if pause_rect.collidepoint(event.pos):
                    if pause:
                        pause_image = resume_pressed_image
                    else:
                        pause_image = pause_pressed_image
                else:
                    if pause:
                        pause_image = resume_nor_image
                    else:
                        pause_image = pause_nor_image
                        
        screen.blit(bg,(0,0))              #把屏幕重新繪製,防止暫停偷看屏幕
        if not pause:                                                                                           #遊戲暫停
        	if event.type == pg.KEYDOWN:
            	if event.key== pg.K_SPACE:                     #全屏炸彈
                	bomb_count  -= 1
                    bomb_sound.play()
                    for each in groups:
                        if each.rect.bottom > 0:
                            each.alive = False       
            key_pressed = pg.key.get_pressed()      #獲得哪些按鍵被長按
            
            if key_pressed[pg.K_w] or key_pressed[pg.K_UP]:    #遊戲操作
                me.moveUp()
            if key_pressed[pg.K_s] or key_pressed[pg.K_DOWN]:
                me.moveDown()
            if key_pressed[pg.K_a] or key_pressed[pg.K_LEFT]:
                me.moveLeft()
            if key_pressed[pg.K_d] or key_pressed[pg.K_RIGHT]:
                me.moveRight()

仔細地讀一讀,不難發現screen.blit(if not pause這句也是)這一語句居然和for event這一語句的遞進關係處於同一級!這就表明當程序執行到這時前面的for event in pg.event.get()語句中的event已經結束了,那麼我的空格鍵事件當然不會再正常執行。

於是解決方法就出來了,我們只需要把空格的那段語句提前到screen.blit語句前面就好了,但是要注意的是我們這裏有暫停功能的,那麼暫停後,你總不能按爆炸吧。因此還要在前面加上一句if not pause:即可。

部分正確代碼:

elif not pause:        
            if event.type == pg.KEYDOWN:
                if event.key== pg.K_SPACE:          #全屏炸彈
                    bomb_count  -= 1
                    bomb_sound.play()
                	for each in groups:
                    	if each.rect.bottom > 0:
                        	each.alive = False
                    
    screen.blit(bg,(0,0))       #把屏幕重新繪製,防止暫停偷看屏幕
    if not pause:                                                                                           #遊戲暫停       
        key_pressed = pg.key.get_pressed()      #獲得哪些按鍵被長按
        
        if key_pressed[pg.K_w] or key_pressed[pg.K_UP]:   #遊戲操作
            me.moveUp()
        if key_pressed[pg.K_s] or key_pressed[pg.K_DOWN]:
            me.moveDown()
        if key_pressed[pg.K_a] or key_pressed[pg.K_LEFT]:
            me.moveLeft()
        if key_pressed[pg.K_d] or key_pressed[pg.K_RIGHT]:
            me.moveRight()

總結:寫代碼的經驗還是太少,相對於這種複製大型一點的代碼,語句的邏輯混亂就出現了,看來我還是要再多加練習。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章