使用python實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲
本文實(shí)例為大家分享了Python飛機(jī)大戰(zhàn)項(xiàng)目,供大家參考,具體內(nèi)容如下
import gc
import random
import pygame
# 玩家飛機(jī)精靈類
import Constants
class HeroPlane(pygame.sprite.Sprite):
def __init__(self, screen):
# 調(diào)用父類初始化方法
# pygame.sprite.Sprite.__init__(self)
super().__init__()
# 窗口
self.screen = screen
# 一個(gè)玩家飛機(jī)圖片
self.image = pygame.image.load('./feiji/feiji.png')
# 飛機(jī)矩形區(qū)域?qū)ο?
self.rect = self.image.get_rect()
# 左上角坐標(biāo)
self.rect.topleft = [512 / 2 - 116 / 2, 600]
# 飛機(jī)的速度
self.speed = 15
# 一個(gè)精靈組 存放所有的子彈精靈
self.bullets = pygame.sprite.Group()
# 血量 初始100
self.blood_value = 100
# 標(biāo)記玩家飛機(jī)是否over
self.is_remove = False
# 顯示爆炸圖片的 索引 從0開始
self.mIndex = 0
# 存放爆炸圖片 的列表
self.bomb_mImages = []
for v in range(1, 15):
# 把所有圖片 存到列表里 每個(gè)圖片 存2次
self.bomb_mImages.append(pygame.image.load('./feiji/image ' + str(v) + '.png'))
self.bomb_mImages.append(pygame.image.load('./feiji/image ' + str(v) + '.png'))
def kill_blood(self, kill_value=10):
"""血量減少"""
self.blood_value -= kill_value
print('被打中了,血量還剩%s' % self.blood_value)
if self.blood_value <= 0:
# 避免血量負(fù)值
self.blood_value = 0
# 血量<=0 設(shè)置is_remove 為True
self.is_remove = True
def key_control(self):
"""按鍵監(jiān)聽 操作飛機(jī)上下左右和發(fā)子彈"""
# 監(jiān)聽鍵盤事件
key_pressed = pygame.key.get_pressed() # 注意這種方式是能夠檢測(cè)到一直按下不松開的鍵盤
if key_pressed[pygame.K_w] or key_pressed[pygame.K_UP]:
# top值如果小于0 就到了最頂部 不要再移動(dòng)了
if self.rect.top > 3:
self.rect.top -= self.speed
if key_pressed[pygame.K_s] or key_pressed[pygame.K_DOWN]:
if self.rect.bottom <= 768:
self.rect.bottom += self.speed
if key_pressed[pygame.K_a] or key_pressed[pygame.K_LEFT]:
if self.rect.left > 0:
self.rect.left -= self.speed
if key_pressed[pygame.K_d] or key_pressed[pygame.K_RIGHT]:
if self.rect.right < 520:
self.rect.right += self.speed
if key_pressed[pygame.K_SPACE]:
# print("space")
# 創(chuàng)建3個(gè)子彈
bullet1 = Bullet(self.screen, self.rect.left, self.rect.top, 1)
bullet2 = Bullet(self.screen, self.rect.left, self.rect.top, 2)
bullet3 = Bullet(self.screen, self.rect.left, self.rect.top, 3)
# 添加到精靈組
self.bullets.add(bullet1, bullet2, bullet3)
def bomb(self):
print('玩家飛機(jī)爆炸中')
"""顯示爆炸圖片"""
self.screen.blit(self.bomb_mImages[self.mIndex], self.rect)
self.mIndex += 1
print('mIndex', self.mIndex)
if self.mIndex >= len(self.bomb_mImages):
# 播放到了最后 爆炸結(jié)束 返回True
return True
def update(self):
if self.is_remove:
print('玩家飛機(jī)掛掉')
# 如果玩家飛機(jī)掛掉
if self.bomb():
# 爆炸結(jié)束
print('爆炸結(jié)束')
self.rect.topleft = [-200, -200]
# 開啟倒計(jì)時(shí)
pygame.time.set_timer(Constants.game_over_id, 1000)
# 把玩家飛機(jī)指向None 停止update
manager.hero = None
else:
self.key_control()
self.display()
def display(self):
# if self.blood_value <= 0:
# # 如果血量小于0 移出窗口
# self.rect.topleft = [-200, -200]
# 把飛機(jī)顯示到窗口上 飛機(jī) 116*100
self.screen.blit(self.image, self.rect)
# 更新精靈組里的子彈位置
self.bullets.update()
# 精靈組所有子彈顯示到窗口
self.bullets.draw(self.screen)
class Bullet(pygame.sprite.Sprite):
# path_num表示散彈中 子彈是哪一個(gè)
def __init__(self, screen, planex, planey, path_num):
# 調(diào)用父類初始化方法
# pygame.sprite.Sprite.__init__(self)
super().__init__()
# 窗口
self.screen = screen
# 一個(gè)子彈圖片
self.image = pygame.image.load('./feiji/bullet_12.png')
# 子彈矩形區(qū)域?qū)ο?
self.rect = self.image.get_rect()
# 子彈左上角坐標(biāo)
self.rect.topleft = [planex + 48, planey - 20]
# 子彈的速度
self.speed = 15
# path_num表示散彈中 子彈是哪一個(gè)
self.path_num = path_num
def update(self):
"""修改子彈坐標(biāo)"""
self.rect.top -= self.speed
if self.rect.bottom < 0:
# 子彈已經(jīng)移出了屏幕上方 這時(shí)把子彈從精靈組刪除
self.kill()
if self.path_num == 1:
pass
elif self.path_num == 2:
# 如果等于2 就是左側(cè)的散彈
self.rect.left -= 10
elif self.path_num == 3:
# 如果等于3 就是右側(cè)的散彈
self.rect.right += 10
# 敵機(jī)精靈類
class EnemyPlane(pygame.sprite.Sprite):
# 創(chuàng)建類屬性 存放所有飛機(jī)的所有的子彈
all_bullets = pygame.sprite.Group()
def __init__(self, screen):
# 調(diào)用父類初始化方法
# pygame.sprite.Sprite.__init__(self)
super().__init__()
# 窗口
self.screen = screen
# 一個(gè)玩家飛機(jī)圖片
self.image = pygame.image.load('./feiji/img-plane_5.png')
# 飛機(jī)矩形區(qū)域?qū)ο?
self.rect = self.image.get_rect()
# 左上角坐標(biāo) x坐標(biāo)隨機(jī)
self.rect.topleft = [random.randint(0, 412), 0]
# 飛機(jī)的速度
self.speed = 3
# 一個(gè)精靈組 存放所有的子彈精靈
self.bullets = pygame.sprite.Group()
# 敵機(jī)的左右方向 默認(rèn)一開始向右
self.direction = 'right'
# 子彈的精靈組
self.bullets = pygame.sprite.Group()
# 標(biāo)記敵機(jī)是否被擊中 是否要?jiǎng)h除
self.is_remove = False
# 顯示爆炸圖片的 索引 從0開始
self.mIndex = 0
# 存放爆炸圖片 的列表
self.bomb_mImages = []
for v in range(1, 14):
# 把所有圖片 存到列表里 每個(gè)圖片 存2次
self.bomb_mImages.append(pygame.image.load('./feiji/image ' + str(v) + '.png'))
self.bomb_mImages.append(pygame.image.load('./feiji/image ' + str(v) + '.png'))
# 記錄爆炸位置
self.x = 0
self.y = 0
def auto_move(self):
"""自動(dòng)移動(dòng)"""
# 向下移動(dòng)
self.rect.bottom += self.speed
# 如果飛機(jī)向下移出邊界 刪除它
if self.rect.top > Manager.height:
self.kill()
# 按不同方向左右移動(dòng)
if self.direction == 'right':
self.rect.right += 6
elif self.direction == 'left':
self.rect.right -= 6
# 超出左右邊界 更改移動(dòng)方向
if self.rect.right >= Manager.width:
self.direction = 'left'
if self.rect.left <= 0:
self.direction = 'right'
def auto_fire(self):
# 用一個(gè)隨機(jī)數(shù)
num = random.randint(1, 40)
# 判斷如果等于1就發(fā)射一個(gè)子彈 ,降低了概率
if num == 5:
# 生成敵機(jī)子彈
bullet = EnemyBullet(self.screen, self.rect.left, self.rect.top)
# 添加到精靈組
self.bullets.add(bullet)
# 把子彈添加到類的all_bullets里 用來(lái)碰撞檢測(cè)
EnemyPlane.all_bullets.add(bullet)
def bomb(self):
"""顯示爆炸圖片"""
if self.mIndex >= len(self.bomb_mImages):
# 播放到了最后 爆炸結(jié)束 返回True
return True
self.screen.blit(self.bomb_mImages[self.mIndex], (self.x, self.y))
self.mIndex += 1
def update(self):
if self.is_remove:
if self.rect.left != -200:
# 記錄爆炸時(shí)的位置
self.x = self.rect.left
self.y = self.rect.top
# 如果已經(jīng)被擊中 把飛機(jī)移除窗口 防止繼續(xù)碰撞檢測(cè)
self.rect.left = -200
self.rect.top = -200
# 顯示爆炸效果
if self.bomb() and not self.bullets:
# 如果爆炸結(jié)束 把自己從精靈組刪除
self.kill()
else:
# 移動(dòng)
self.auto_move()
# 開火
self.auto_fire()
# 顯示
self.display()
self.bullet_show()
def display(self):
# 把飛機(jī)顯示到窗口上 飛機(jī) 116*100
self.screen.blit(self.image, self.rect)
def bullet_show(self):
if self.bullets:
# 敵機(jī)子彈更新
self.bullets.update()
# 敵機(jī)子彈顯示
self.bullets.draw(self.screen)
class EnemyBullet(pygame.sprite.Sprite):
# path_num表示散彈中 子彈是哪一個(gè)
def __init__(self, screen, x, y):
# 調(diào)用父類初始化方法
# pygame.sprite.Sprite.__init__(self)
super().__init__()
# 窗口
self.screen = screen
# 一個(gè)子彈圖片
self.image = pygame.image.load('./feiji/bullet_6.png')
# 子彈矩形區(qū)域?qū)ο?
self.rect = self.image.get_rect()
# 子彈左上角坐標(biāo)
self.rect.topleft = [x + 40, y + 60]
# 子彈的速度
self.speed = 10
def update(self):
"""修改子彈坐標(biāo)"""
self.rect.bottom += self.speed
# 如果子彈向下移出邊界 刪除它
if self.rect.top > Manager.height:
self.kill()
# 游戲音樂(lè)
class GameSound(object):
def __init__(self):
pygame.mixer.init() # 音樂(lè)模塊初始化
pygame.mixer.music.load("./feiji/Jamesketed.mp3")
pygame.mixer.music.set_volume(0.5) # 聲音大小 一半
self.__bomb = pygame.mixer.Sound("./feiji/bomb.wav")
def playBackgroundMusic(self):
# 開始播放背景音樂(lè) -1表示一直重復(fù)播放
pygame.mixer.music.play(-1)
def playBombSound(self):
pygame.mixer.Sound.play(self.__bomb) # 爆炸音樂(lè)
class GameBackground(object):
# 初始化地圖
def __init__(self, screen):
self.mImage1 = pygame.image.load("./feiji/img_bg_level_4.jpg")
self.mImage2 = pygame.image.load("./feiji/img_bg_level_4.jpg")
# 窗口
self.screen = screen
# 輔助移動(dòng)地圖
self.y1 = 0
self.y2 = -Manager.height # -768
def update(self):
self.move()
self.draw()
# 移動(dòng)地圖
def move(self):
self.y1 += 2
self.y2 += 2
if self.y1 >= Manager.height:
self.y1 = 0
if self.y2 >= 0:
self.y2 = -Manager.height
# 繪制地圖
def draw(self):
self.screen.blit(self.mImage1, (0, self.y1))
self.screen.blit(self.mImage2, (0, self.y2))
class Manager:
hero: HeroPlane
# 創(chuàng)建寬高
width = 512
height = 768
def __init__(self):
# pygame初始化 否則找不到字體文件
pygame.init()
# 1 創(chuàng)建一個(gè)窗口 參數(shù)1是寬高,參數(shù)2 附加參數(shù) 參3是顏色深度
self.screen = pygame.display.set_mode((self.width, self.height), 0, 32)
# 2創(chuàng)建背景圖的對(duì)象
# self.background = pygame.image.load('./feiji/img_bg_level_5.jpg')
self.background = GameBackground(self.screen)
# 創(chuàng)建飛機(jī)對(duì)象
self.hero = HeroPlane(self.screen)
# 創(chuàng)建時(shí)鐘對(duì)象
self.clock = pygame.time.Clock()
# 敵機(jī)的精靈組
self.enemys = pygame.sprite.Group()
# 初始化音效對(duì)象
self.sound = GameSound()
# 定義分?jǐn)?shù)屬性
self.score = 0
# 倒計(jì)時(shí)時(shí)間
self.over_time = 3
def exit(self):
# 執(zhí)行退出代碼
pygame.quit()
# 程序的退出
exit()
def new_enemy(self):
# 創(chuàng)建敵機(jī)對(duì)象
enemy = EnemyPlane(self.screen)
# 添加到精靈組
self.enemys.add(enemy)
def drawText(self, text, x, y, textHeight=30, fontColor=(255, 255, 255), backgroudColor=None):
# 通過(guò)字體文件獲得字體對(duì)象 參數(shù)1 字體文件 參數(shù)2 字體大小
font_obj = pygame.font.Font('./feiji/baddf.ttf', textHeight)
# 1文字 2是否抗鋸齒 3文字顏色 4背景顏色
text_obj = font_obj.render(text, True, fontColor, backgroudColor) # 配置要顯示的文字
# 獲得要顯示的對(duì)象的rect
text_rect = text_obj.get_rect()
# 設(shè)置顯示對(duì)象的坐標(biāo)
text_rect.topleft = (x, y)
# 繪制字 到指定區(qū)域 參1是文字對(duì)象 參2 矩形對(duì)象
self.screen.blit(text_obj, text_rect)
def game_over_timer(self):
"""執(zhí)行倒計(jì)時(shí)"""
self.over_time -= 1
if self.over_time == 0:
# 停止倒計(jì)時(shí)
pygame.time.set_timer(Constants.game_over_id, 0)
# 重新開始游戲
self.start_game()
def show_over_text(self):
print('self.over_time', self.over_time)
# 游戲結(jié)束 顯示倒計(jì)時(shí)時(shí)間
self.drawText('gameover %d' % self.over_time, 0, Manager.height / 2, textHeight=50,
fontColor=[0, 0, 0])
def start_game(self):
global manager
# 情況敵機(jī)子彈的精靈組
EnemyPlane.all_bullets.empty()
manager = Manager()
# 垃圾回收 提示python解釋器 要回收了
gc.collect()
manager.main()
def main(self):
# 播放背景音樂(lè)
self.sound.playBackgroundMusic()
# 參1eventid是事件id,自己定義(0 - 32之間)不要和已用的pygame的其它事件id沖突,
# 參2是定時(shí)事件的間隔時(shí)間,單位是毫秒
pygame.time.set_timer(Constants.new_enemy, 500)
while True:
# 控制每s執(zhí)行的次數(shù)
self.clock.tick(60)
# 獲取事件 并且處理
for event in pygame.event.get():
# 判斷事件的類型是否是退出
if event.type == pygame.QUIT:
# 退出
self.exit()
elif event.type == Constants.new_enemy:
# 等于20 說(shuō)明定時(shí)器生效 添加一個(gè)敵機(jī)
# print('添加一個(gè)敵機(jī)')
self.new_enemy()
elif event.type == Constants.game_over_id:
print('倒計(jì)時(shí) 33333')
# 顯示倒計(jì)時(shí)時(shí)間
self.game_over_timer()
# 3把背景圖顯示到窗口上
# self.screen.blit(self.background, (0, 0))
self.background.update()
self.drawText('分?jǐn)?shù):%s' % self.score, 0, 0)
if self.hero:
self.drawText('血量:%s' % self.hero.blood_value, 0, 30)
# 更新飛機(jī)
self.hero.update()
# if self.hero.blood_value <= 0 and not self.hero.bullets.sprites():
# # 把玩家飛機(jī)引用指向None 盡快釋放
# self.hero = None
else:
self.drawText('血量:0', 0, 30)
# 更新 敵機(jī)
self.enemys.update()
# 如果飛機(jī)已經(jīng)掛掉 就一直顯示倒計(jì)時(shí)
if not self.hero:
# 顯示倒計(jì)時(shí)
self.show_over_text()
# 判斷 玩家飛機(jī) 和敵機(jī)是否都存在 self.enemys.sprites()返回精靈組對(duì)應(yīng)的精靈列表
if self.hero and self.enemys.sprites():
# 碰撞檢測(cè) 返回的碰撞到的 敵機(jī)列表
collide_enemys = pygame.sprite.spritecollide(self.hero, self.enemys, False, pygame.sprite.collide_mask)
if collide_enemys:
# 如果列表不為空 說(shuō)明碰到了敵機(jī)
print('碰到了敵機(jī)')
# 爆炸聲音
self.sound.playBombSound()
self.hero.kill_blood(100)
for enemy_item in collide_enemys:
# 標(biāo)記敵機(jī)已經(jīng)被撞到
enemy_item.is_remove = True
# 判斷 玩家飛機(jī) 和 玩家飛機(jī)的子彈 和 敵機(jī)是否都存在
if self.hero and self.hero.bullets and self.enemys:
# 檢測(cè)玩家飛機(jī)的子彈 和敵機(jī)的碰撞
# 返回是個(gè)字典 格式{<Bullet sprite(in 0 groups)>: [<EnemyPlane sprite(in 0 groups)>]}
# {碰撞的子彈1:[打中的敵機(jī)1,打中的敵機(jī)2],碰撞的子彈2:[打中的敵機(jī)1,打中的敵機(jī)5]}
collode_dict = pygame.sprite.groupcollide(self.hero.bullets, self.enemys, True, False,
pygame.sprite.collide_mask)
# 1多個(gè)子彈打中同一個(gè)飛機(jī) # 2不同子彈 打中不同飛機(jī) # 所有加分值時(shí) 要去除重復(fù)的敵機(jī)
# print(collode_dict)
if collode_dict:
# 爆炸聲音
self.sound.playBombSound()
print(self.score)
# 用一個(gè)集合 添加敵機(jī) 去除重復(fù)的
enemyset = set()
# 獲取所有打中的敵機(jī)列表,然后遍歷
for v_enemys in collode_dict.values():
# 遍歷敵機(jī)列表
for enemy_item in v_enemys:
# print(id(enemy_item))
enemyset.add(enemy_item)
# 標(biāo)記敵機(jī)已經(jīng)被擊中
enemy_item.is_remove = True
# 碰撞后 +10分*集合里敵機(jī)的數(shù)量
self.score += 10 * len(enemyset)
# 判斷 玩家飛機(jī) 和 和 敵機(jī)子彈
if self.hero and EnemyPlane.all_bullets:
# 檢測(cè)玩家 和敵機(jī)子彈的碰撞
collide_bullets = pygame.sprite.spritecollide(self.hero, EnemyPlane.all_bullets, True,
pygame.sprite.collide_mask)
if collide_bullets:
# 如果碰到了 就減少10*子彈數(shù)量的血量
self.hero.kill_blood(10 * len(collide_bullets))
# 2 顯示窗口
pygame.display.update()
if __name__ == '__main__':
manager = Manager()
manager.main()





以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- python版飛機(jī)大戰(zhàn)代碼分享
- python實(shí)現(xiàn)飛機(jī)大戰(zhàn)
- python實(shí)現(xiàn)飛機(jī)大戰(zhàn)小游戲
- 用Python寫飛機(jī)大戰(zhàn)游戲之pygame入門(4):獲取鼠標(biāo)的位置及運(yùn)動(dòng)
- python實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲(pygame版)
- python pygame模塊編寫飛機(jī)大戰(zhàn)
- python飛機(jī)大戰(zhàn)pygame碰撞檢測(cè)實(shí)現(xiàn)方法分析
- python實(shí)現(xiàn)飛機(jī)大戰(zhàn)游戲
- python實(shí)現(xiàn)飛機(jī)大戰(zhàn)項(xiàng)目
- python實(shí)現(xiàn)簡(jiǎn)單飛機(jī)大戰(zhàn)小游戲
相關(guān)文章
淺談Python小波分析庫(kù)Pywavelets的一點(diǎn)使用心得
這篇文章主要介紹了淺談Python小波分析庫(kù)Pywavelets的一點(diǎn)使用心得,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
Python統(tǒng)計(jì)單詞出現(xiàn)的次數(shù)
最近經(jīng)理交給我一項(xiàng)任務(wù),統(tǒng)計(jì)一個(gè)文件中每個(gè)單詞出現(xiàn)的次數(shù),列出出現(xiàn)頻率最多的5個(gè)單詞。本文給大家?guī)?lái)了python 統(tǒng)計(jì)單詞次數(shù)的思路解析,需要的朋友參考下吧2018-04-04
基于Python和Scikit-Learn的機(jī)器學(xué)習(xí)探索
這篇文章主要介紹了基于Python和Scikit-Learn的機(jī)器學(xué)習(xí)探索的相關(guān)內(nèi)容,小編覺(jué)得還是挺不錯(cuò)的,這里分享給大家,供需要的朋友學(xué)習(xí)和參考。2017-10-10
由Python運(yùn)算π的值深入Python中科學(xué)計(jì)算的實(shí)現(xiàn)
這篇文章主要介紹了由Python運(yùn)算π的值深入Python中科學(xué)計(jì)算的實(shí)現(xiàn),由簡(jiǎn)單的計(jì)算發(fā)散出各種算法的講解,需要的朋友可以參考下2015-04-04
python實(shí)現(xiàn)while循環(huán)打印星星的四種形狀
今天小編就為大家分享一篇python實(shí)現(xiàn)while循環(huán)打印星星的四種形狀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11
利用Python連接Oracle數(shù)據(jù)庫(kù)的基本操作指南
由于之前的在職的公司沒(méi)有機(jī)會(huì)接觸到Oralce數(shù)據(jù)庫(kù),所以就沒(méi)有用python連接過(guò)Oralce,之前大多集中在連接mysql和sql server,最近在做一下web自動(dòng)化的工作,所以簡(jiǎn)單的記錄一下,下面這篇文章主要給大家介紹了關(guān)于利用Python連接Oracle數(shù)據(jù)庫(kù)的基本操作,需要的朋友可以參考下2022-06-06
Python+Pygame實(shí)現(xiàn)海洋之神大冒險(xiǎn)游戲
這篇文章主要介紹了如何利用Python+Pygame自制一個(gè)海洋之神大冒險(xiǎn)游戲。規(guī)則是在海里收集魚骨頭,有些魚骨頭可以轉(zhuǎn)化為武器,用來(lái)攻擊敵人,感興趣的可以了解一下2022-08-08
python中以函數(shù)作為參數(shù)(回調(diào)函數(shù))的實(shí)現(xiàn)方法
這篇文章主要介紹了python中以函數(shù)作為參數(shù)(回調(diào)函數(shù))的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的最短路徑(Dijkstra算法)完整實(shí)例
這篇文章主要介紹了Python數(shù)據(jù)結(jié)構(gòu)與算法之圖的最短路徑(Dijkstra算法),結(jié)合完整實(shí)例形式分析了Python圖的最短路徑算法相關(guān)原理與實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-12-12

