1. 程式人生 > 其它 >python編寫飛機大戰小遊戲+原始碼

python編寫飛機大戰小遊戲+原始碼

前言

大家之前用python編寫過飛機大戰的部分程式碼,只能夠展示英雄飛機,背景,敵機和發射子彈,今天把背景音樂,擊毀敵機,爆

炸特效,得分等等相關功能一併加入進來,程式碼有點長,三百多行,你們要的程式碼來了哦?

程式設計思路

主要使用pygame庫,類的建立,函式的呼叫等等來實現,話不多說,上程式。

程式設計實現

Python學習交流Q群:906715085####
import pygame  # 匯入動態模組(.dll .pyd .so) 不需要在包名後邊跟模組名

from pygame.locals import *

import time

import random import sys # 定義常量(定義後,不再改值) WINDOW_HEIGHT = 768 WINDOW_WIDTH = 512 enemy_list = [] score = 0 is_restart = False class Map: def __init__(self, img_path, window): self.x = 0 self.bg_img1 = pygame.image.load(img_path) self.bg_img2 = pygame.image.load(img_path) self.bg1_y
= - WINDOW_HEIGHT self.bg2_y = 0 self.window = window def move(self): # 當地圖1的 y軸移動到0,則重置 if self.bg1_y >= 0: self.bg1_y = - WINDOW_HEIGHT # 當地圖2的 y軸移動到 視窗底部,則重置 if self.bg2_y >= WINDOW_HEIGHT: self.bg2_y = 0 # 每次迴圈都移動1個畫素 self.bg1_y += 3 self.bg2_y += 3 def display(self):
"""貼圖""" self.window.blit(self.bg_img1, (self.x, self.bg1_y)) self.window.blit(self.bg_img2, (self.x, self.bg2_y)) class HeroBullet: """英雄子彈類""" def __init__(self, img_path, x, y, window): self.img = pygame.image.load(img_path) self.x = x self.y = y self.window = window def display(self): self.window.blit(self.img, (self.x, self.y)) def move(self): """子彈向上飛行距離""" self.y -= 6 def is_hit_enemy(self, enemy): if pygame.Rect.colliderect( pygame.Rect(self.x, self.y, 20, 31), pygame.Rect(enemy.x, enemy.y, 100, 68) ): # 判斷是否交叉 return True else: return False class EnemyPlane: """敵人飛機類""" def __init__(self, img_path, x, y, window): self.img = pygame.image.load(img_path) # 圖片物件 self.x = x # 飛機座標 self.y = y self.window = window # 飛機所在的視窗 self.is_hited = False self.anim_index = 0 self.hit_sound = pygame.mixer.Sound("E:/飛機大戰/baozha.ogg") def move(self): self.y += 10 # 到達視窗下邊界,回到頂部 if self.y >= WINDOW_HEIGHT: self.x = random.randint(0, random.randint(0, WINDOW_WIDTH - 100)) self.y = 0 def plane_down_anim(self): """敵機被擊中動畫""" if self.anim_index >= 21: # 動畫執行完 self.anim_index = 0 self.img = pygame.image.load( "E:/飛機大戰/img-plane_%d.png" % random.randint(1, 7)) self.x = random.randint(0, WINDOW_WIDTH - 100) self.y = 0 self.is_hited = False return elif self.anim_index == 0: self.hit_sound.play() self.img = pygame.image.load( "E:/飛機大戰/bomb-%d.png" % (self.anim_index // 3 + 1)) self.anim_index += 1 def display(self): """貼圖""" if self.is_hited: self.plane_down_anim() self.window.blit(self.img, (self.x, self.y)) class HeroPlane: def __init__(self, img_path, x, y, window): self.img = pygame.image.load(img_path) # 圖片物件 self.x = x # 飛機座標 self.y = y self.window = window # 飛機所在的視窗 self.bullets = [] # 記錄該飛機發出的所有子彈 self.is_hited = False self.is_anim_down = False self.anim_index = 0 def is_hit_enemy(self, enemy): if pygame.Rect.colliderect( pygame.Rect(self.x, self.y, 120, 78), pygame.Rect(enemy.x, enemy.y, 100, 68) ): # 判斷是否交叉 return True else: return False def plane_down_anim(self): """敵機被擊中動畫""" if self.anim_index >= 21: # 動畫執行完 self.is_hited = False self.is_anim_down = True return self.img = pygame.image.load( "E:/飛機大戰/bomb-%d.png" % (self.anim_index // 3 + 1)) self.anim_index += 1 def display(self): """貼圖""" for enemy in enemy_list: if self.is_hit_enemy(enemy): enemy.is_hited = True self.is_hited = True self.plane_down_anim() break self.window.blit(self.img, (self.x, self.y)) def display_bullets(self): # 貼子彈圖 deleted_bullets = [] for bullet in self.bullets: # 判斷 子彈是否超出 上邊界 if bullet.y >= -31: # 沒有出邊界 bullet.display() bullet.move() else: # 飛出邊界 deleted_bullets.append(bullet) for enemy in enemy_list: if bullet.is_hit_enemy(enemy): # 判斷是否擊中敵機 enemy.is_hited = True deleted_bullets.append(bullet) global score score += 10 break for out_window_bullet in deleted_bullets: self.bullets.remove(out_window_bullet) def move_left(self): """往左飛""" if self.x >= 0 and not self.is_hited: self.x -= 10 def move_right(self): """往右飛""" if self.x <= WINDOW_WIDTH - 120 and not self.is_hited: self.x += 10 def move_up(self): """往上飛""" if self.y >= 0 and not self.is_hited: self.y -= 5 def move_down(self): """往下飛""" if self.y <= WINDOW_HEIGHT - 78 and not self.is_hited: self.y += 5 def fire(self): """發射子彈""" # 建立子彈物件 子彈x = 飛機x + 飛機寬度的一半 - 子彈寬度的一半 bullet = HeroBullet("E:/飛機大戰/bullet_17.png", self.x + 60 - 10, self.y - 31, self.window) # 顯示子彈(貼子彈圖) bullet.display() self.bullets.append(bullet) # 為了避免子彈物件被釋放(只有區域性變數引用物件,方法一執行完就會釋放) class Game: def __init__(self): pygame.init() # 設定標題 pygame.display.set_caption("飛機大戰 v1.0") # 設定圖示 game_ico = pygame.image.load("E:/飛機大戰/app.ico") pygame.display.set_icon(game_ico) pygame.mixer.music.load("E:/飛機大戰/bg2.ogg") # 遊戲結束的音效(超級瑪麗) self.gameover_sound = pygame.mixer.Sound("E:/飛機大戰/gameover.wav") # 迴圈播放背景音樂 pygame.mixer.music.play(-1) # 建立視窗 set_mode((視窗尺寸)) self.window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) # 建立地圖物件 self.game_map = Map("E:/飛機大戰/img_bg_level_%d.jpg" % random.randint(1, 5), self.window) # 建立物件 self.hero_plane = HeroPlane("E:/飛機大戰/hero2.png", 240, 500, self.window) enemy_plane1 = EnemyPlane("E:/飛機大戰/img-plane_%d.png" % random.randint( 1, 7), random.randint(0, WINDOW_WIDTH - 100), 0, self.window) enemy_plane2 = EnemyPlane("E:/飛機大戰/img-plane_%d.png" % random.randint(1, 7), random.randint(0, WINDOW_WIDTH - 100), random.randint(-150, -68), self.window) enemy_plane3 = EnemyPlane("E:/飛機大戰/img-plane_%d.png" % random.randint(1, 7), random.randint(0, WINDOW_WIDTH - 100), random.randint(-300, -140), self.window) enemy_list.append(enemy_plane1) enemy_list.append(enemy_plane2) enemy_list.append(enemy_plane3) self.enemy_list = enemy_list # 建立文字物件 # self.score_font = pygame.font.SysFont("simhei", 40) self.score_font = pygame.font.Font("E:/飛機大戰/SIMHEI.TTF", 40) def draw_text(self, content, size, x, y): # font_obj = pygame.font.SysFont("simhei", size) font_obj = pygame.font.Font("E:/飛機大戰/SIMHEI.TTF", size) text = font_obj.render(content, 1, (255, 255, 255)) self.window.blit(text, (x, y)) def wait_game_input(self): while True: for event in pygame.event.get(): if event.type == QUIT: sys.exit() pygame.quit() elif event.type == KEYDOWN: if event.key == K_ESCAPE: sys.exit() pygame.quit() elif event.key == K_RETURN: global is_restart, score is_restart = True score = 0 return def game_start(self): # 貼背景圖片 self.game_map.display() self.draw_text("飛機大戰", 40, WINDOW_WIDTH / 2 - 100, WINDOW_HEIGHT / 3) self.draw_text("按Enter開始遊戲, Esc退出遊戲.", 28, WINDOW_WIDTH /3 - 140, WINDOW_HEIGHT /2) pygame.display.update() self.wait_game_input() def game_over(self): # 先停止背景音樂 pygame.mixer.music.stop() # 再播放音效 self.gameover_sound.play() # 貼背景圖片 self.game_map.display() self.draw_text("戰機被擊落,得分為 %d" % score, 28, WINDOW_WIDTH / 3 - 100, WINDOW_HEIGHT / 3) self.draw_text("按Enter重新開始, Esc退出遊戲.", 28, WINDOW_WIDTH / 3 - 140, WINDOW_HEIGHT / 2) pygame.display.update() self.wait_game_input() self.gameover_sound.stop() def key_control(self): # 獲取事件,比如按鍵等 先顯示介面,再根據獲取的事件,修改介面效果 for event in pygame.event.get(): # 判斷是否是點選了退出按鈕 if event.type == QUIT: sys.exit() # 讓程式終止 pygame.quit() # 判斷是否是按下了鍵 elif event.type == KEYDOWN: # 檢測按鍵是否是空格鍵 if event.key == K_SPACE: self.hero_plane.fire() # 獲取連續按下的情況 pressed_keys = pygame.key.get_pressed() if pressed_keys[pygame.K_LEFT]: self.hero_plane.move_left() if pressed_keys[pygame.K_RIGHT]: self.hero_plane.move_right() if pressed_keys[pygame.K_UP]: self.hero_plane.move_up() if pressed_keys[pygame.K_DOWN]: self.hero_plane.move_down() def display(self): # 貼背景圖 self.game_map.display() self.game_map.move() # 貼飛機圖 self.hero_plane.display() self.hero_plane.display_bullets() # 貼敵機圖 for enemy in enemy_list: enemy.display() # 讓敵機移動 if not enemy.is_hited: enemy.move() # 貼得分文字 score_text = self.score_font.render("得分:%d" % score, 1, (255, 255, 255)) self.window.blit(score_text, (10, 10)) # 重新整理介面 不重新整理不會更新顯示的內容 pygame.display.update() def run(self): if is_restart == False: self.game_start() while True: # 顯示介面 self.display() if self.hero_plane.is_anim_down: self.hero_plane.is_anim_down = False global enemy_list enemy_list = [] break # 鍵盤控制 self.key_control() # 每次迴圈,讓程式休眠一會兒 time.sleep(0.01) self.game_over() def main(): """主函式 一般將程式的入口""" # 運行遊戲 while True: # 建立遊戲物件 game = Game() game.run() if __name__ == '__main__': # 判斷是否主動執行該檔案 main() import pygame # 匯入動態模組(.dll .pyd .so) 不需要在包名後邊跟模組名 from pygame.locals import * import time import random import sys # 定義常量(定義後,不再改值) WINDOW_HEIGHT = 768 WINDOW_WIDTH = 512 enemy_list = [] score = 0 is_restart = False class Map: def __init__(self, img_path, window): self.x = 0 self.bg_img1 = pygame.image.load(img_path) self.bg_img2 = pygame.image.load(img_path) self.bg1_y = - WINDOW_HEIGHT self.bg2_y = 0 self.window = window def move(self): # 當地圖1的 y軸移動到0,則重置 if self.bg1_y >= 0: self.bg1_y = - WINDOW_HEIGHT # 當地圖2的 y軸移動到 視窗底部,則重置 if self.bg2_y >= WINDOW_HEIGHT: self.bg2_y = 0 # 每次迴圈都移動1個畫素 self.bg1_y += 3 self.bg2_y += 3 def display(self): """貼圖""" self.window.blit(self.bg_img1, (self.x, self.bg1_y)) self.window.blit(self.bg_img2, (self.x, self.bg2_y)) class HeroBullet: """英雄子彈類""" def __init__(self, img_path, x, y, window): self.img = pygame.image.load(img_path) self.x = x self.y = y self.window = window def display(self): self.window.blit(self.img, (self.x, self.y)) def move(self): """子彈向上飛行距離""" self.y -= 6 def is_hit_enemy(self, enemy): if pygame.Rect.colliderect( pygame.Rect(self.x, self.y, 20, 31), pygame.Rect(enemy.x, enemy.y, 100, 68) ): # 判斷是否交叉 return True else: return False class EnemyPlane: """敵人飛機類""" def __init__(self, img_path, x, y, window): self.img = pygame.image.load(img_path) # 圖片物件 self.x = x # 飛機座標 self.y = y self.window = window # 飛機所在的視窗 self.is_hited = False self.anim_index = 0 self.hit_sound = pygame.mixer.Sound("E:/飛機大戰/baozha.ogg") def move(self): self.y += 10 # 到達視窗下邊界,回到頂部 if self.y >= WINDOW_HEIGHT: self.x = random.randint(0, random.randint(0, WINDOW_WIDTH - 100)) self.y = 0 def plane_down_anim(self): """敵機被擊中動畫""" if self.anim_index >= 21: # 動畫執行完 self.anim_index = 0 self.img = pygame.image.load( "E:/飛機大戰/img-plane_%d.png" % random.randint(1, 7)) self.x = random.randint(0, WINDOW_WIDTH - 100) self.y = 0 self.is_hited = False return elif self.anim_index == 0: self.hit_sound.play() self.img = pygame.image.load( "E:/飛機大戰/bomb-%d.png" % (self.anim_index // 3 + 1)) self.anim_index += 1 def display(self): """貼圖""" if self.is_hited: self.plane_down_anim() self.window.blit(self.img, (self.x, self.y)) class HeroPlane: def __init__(self, img_path, x, y, window): self.img = pygame.image.load(img_path) # 圖片物件 self.x = x # 飛機座標 self.y = y self.window = window # 飛機所在的視窗 self.bullets = [] # 記錄該飛機發出的所有子彈 self.is_hited = False self.is_anim_down = False self.anim_index = 0 def is_hit_enemy(self, enemy): if pygame.Rect.colliderect( pygame.Rect(self.x, self.y, 120, 78), pygame.Rect(enemy.x, enemy.y, 100, 68) ): # 判斷是否交叉 return True else: return False def plane_down_anim(self): """敵機被擊中動畫""" if self.anim_index >= 21: # 動畫執行完 self.is_hited = False self.is_anim_down = True return self.img = pygame.image.load( "E:/飛機大戰/bomb-%d.png" % (self.anim_index // 3 + 1)) self.anim_index += 1 def display(self): """貼圖""" for enemy in enemy_list: if self.is_hit_enemy(enemy): enemy.is_hited = True self.is_hited = True self.plane_down_anim() break self.window.blit(self.img, (self.x, self.y)) def display_bullets(self): # 貼子彈圖 deleted_bullets = [] for bullet in self.bullets: # 判斷 子彈是否超出 上邊界 if bullet.y >= -31: # 沒有出邊界 bullet.display() bullet.move() else: # 飛出邊界 deleted_bullets.append(bullet) for enemy in enemy_list: if bullet.is_hit_enemy(enemy): # 判斷是否擊中敵機 enemy.is_hited = True deleted_bullets.append(bullet) global score score += 10 break for out_window_bullet in deleted_bullets: self.bullets.remove(out_window_bullet) def move_left(self): """往左飛""" if self.x >= 0 and not self.is_hited: self.x -= 10 def move_right(self): """往右飛""" if self.x <= WINDOW_WIDTH - 120 and not self.is_hited: self.x += 10 def move_up(self): """往上飛""" if self.y >= 0 and not self.is_hited: self.y -= 5 def move_down(self): """往下飛""" if self.y <= WINDOW_HEIGHT - 78 and not self.is_hited: self.y += 5 def fire(self): """發射子彈""" # 建立子彈物件 子彈x = 飛機x + 飛機寬度的一半 - 子彈寬度的一半 bullet = HeroBullet("E:/飛機大戰/bullet_17.png", self.x + 60 - 10, self.y - 31, self.window) # 顯示子彈(貼子彈圖) bullet.display() self.bullets.append(bullet) # 為了避免子彈物件被釋放(只有區域性變數引用物件,方法一執行完就會釋放) class Game: def __init__(self): pygame.init() # 設定標題 pygame.display.set_caption("飛機大戰 v1.0") # 設定圖示 game_ico = pygame.image.load("E:/飛機大戰/app.ico") pygame.display.set_icon(game_ico) pygame.mixer.music.load("E:/飛機大戰/bg2.ogg") # 遊戲結束的音效(超級瑪麗) self.gameover_sound = pygame.mixer.Sound("E:/飛機大戰/gameover.wav") # 迴圈播放背景音樂 pygame.mixer.music.play(-1) # 建立視窗 set_mode((視窗尺寸)) self.window = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) # 建立地圖物件 self.game_map = Map("E:/飛機大戰/img_bg_level_%d.jpg" % random.randint(1, 5), self.window) # 建立物件 self.hero_plane = HeroPlane("E:/飛機大戰/hero2.png", 240, 500, self.window) enemy_plane1 = EnemyPlane("E:/飛機大戰/img-plane_%d.png" % random.randint( 1, 7), random.randint(0, WINDOW_WIDTH - 100), 0, self.window) enemy_plane2 = EnemyPlane("E:/飛機大戰/img-plane_%d.png" % random.randint(1, 7), random.randint(0, WINDOW_WIDTH - 100), random.randint(-150, -68), self.window) enemy_plane3 = EnemyPlane("E:/飛機大戰/img-plane_%d.png" % random.randint(1, 7), random.randint(0, WINDOW_WIDTH - 100), random.randint(-300, -140), self.window) enemy_list.append(enemy_plane1) enemy_list.append(enemy_plane2) enemy_list.append(enemy_plane3) self.enemy_list = enemy_list # 建立文字物件 # self.score_font = pygame.font.SysFont("simhei", 40) self.score_font = pygame.font.Font("E:/飛機大戰/SIMHEI.TTF", 40) def draw_text(self, content, size, x, y): # font_obj = pygame.font.SysFont("simhei", size) font_obj = pygame.font.Font("E:/飛機大戰/SIMHEI.TTF", size) text = font_obj.render(content, 1, (255, 255, 255)) self.window.blit(text, (x, y)) def wait_game_input(self): while True: for event in pygame.event.get(): if event.type == QUIT: sys.exit() pygame.quit() elif event.type == KEYDOWN: if event.key == K_ESCAPE: sys.exit() pygame.quit() elif event.key == K_RETURN: global is_restart, score is_restart = True score = 0 return def game_start(self): # 貼背景圖片 self.game_map.display() self.draw_text("飛機大戰", 40, WINDOW_WIDTH / 2 - 100, WINDOW_HEIGHT / 3) self.draw_text("按Enter開始遊戲, Esc退出遊戲.", 28, WINDOW_WIDTH /3 - 140, WINDOW_HEIGHT /2) pygame.display.update() self.wait_game_input() def game_over(self): # 先停止背景音樂 pygame.mixer.music.stop() # 再播放音效 self.gameover_sound.play() # 貼背景圖片 self.game_map.display() self.draw_text("戰機被擊落,得分為 %d" % score, 28, WINDOW_WIDTH / 3 - 100, WINDOW_HEIGHT / 3) self.draw_text("按Enter重新開始, Esc退出遊戲.", 28, WINDOW_WIDTH / 3 - 140, WINDOW_HEIGHT / 2) pygame.display.update() self.wait_game_input() self.gameover_sound.stop() def key_control(self): # 獲取事件,比如按鍵等 先顯示介面,再根據獲取的事件,修改介面效果 for event in pygame.event.get(): # 判斷是否是點選了退出按鈕 if event.type == QUIT: sys.exit() # 讓程式終止 pygame.quit() # 判斷是否是按下了鍵 elif event.type == KEYDOWN: # 檢測按鍵是否是空格鍵 if event.key == K_SPACE: self.hero_plane.fire() # 獲取連續按下的情況 pressed_keys = pygame.key.get_pressed() if pressed_keys[pygame.K_LEFT]: self.hero_plane.move_left() if pressed_keys[pygame.K_RIGHT]: self.hero_plane.move_right() if pressed_keys[pygame.K_UP]: self.hero_plane.move_up() if pressed_keys[pygame.K_DOWN]: self.hero_plane.move_down() def display(self): # 貼背景圖 self.game_map.display() self.game_map.move() # 貼飛機圖 self.hero_plane.display() self.hero_plane.display_bullets() # 貼敵機圖 for enemy in enemy_list: enemy.display() # 讓敵機移動 if not enemy.is_hited: enemy.move() # 貼得分文字 score_text = self.score_font.render("得分:%d" % score, 1, (255, 255, 255)) self.window.blit(score_text, (10, 10)) # 重新整理介面 不重新整理不會更新顯示的內容 pygame.display.update() def run(self): if is_restart == False: self.game_start() while True: # 顯示介面 self.display() if self.hero_plane.is_anim_down: self.hero_plane.is_anim_down = False global enemy_list enemy_list = [] break # 鍵盤控制 self.key_control() # 每次迴圈,讓程式休眠一會兒 time.sleep(0.01) self.game_over() def main(): """主函式 一般將程式的入口""" # 運行遊戲 while True: # 建立遊戲物件 game = Game() game.run() if __name__ == '__main__': # 判斷是否主動執行該檔案 main() #程式碼有點長,得使勁往下拉..

 

效果圖

最後

今天給大家分享的飛機大戰小遊戲到這裡就結束了,程式碼就放在上面吧,喜歡的小夥伴就拿去試試手吧。