首先要下載pygame
代碼類
(1)游戲初始化

image.png
(2)創(chuàng)建英雄

image.png
(3)創(chuàng)建游戲窗口

image.png
(4)創(chuàng)建圖像

image.png
(5)創(chuàng)建飛機

(6)調(diào)用update方法

image.png
(7)創(chuàng)建時鐘對象

image.png
(8)讓英雄動起來

image.png
(9)監(jiān)聽退出

image.png
(10)飛機循環(huán)飛行

image.png

image.png
總的代碼
import pygame
from gws import *
class PlaneGame(object):
"""飛機大戰(zhàn)主游戲類"""
def __init__(self):
print("游戲初始化")
"""在開始游戲我們做這么幾件事
1 創(chuàng)建游戲窗口
2 創(chuàng)建游戲時鐘
3 調(diào)用創(chuàng)建精靈和精靈組的方法 (私有方法)
"""
self.screen = pygame.display.set_mode(SCREEN_RECT.size)
self.clock = pygame.time.Clock(self.__create_sprites()
pygame.time.set_timer(CREATE_ENEMY_EVENT, 1000)
def start_game(self):
"""在開始游戲這里我們需要做下面幾件事"""
while True:
# 1 設(shè)置幀率
self.clock.tick(60)
# 2 事件監(jiān)聽 主要是要監(jiān)聽我們鼠標(biāo) 鍵盤的一些事件
self.__event_handler()
# 3 碰撞檢測 碰撞檢測的內(nèi)容比較 在這里我還沒有定義 現(xiàn)在需要補上
self.__check_collide()
# 4 更新精靈和精靈組
self.__update_sprites()
# 5 更新顯示
pygame.display.update()
# 在上面 我們調(diào)用類方法 并且關(guān)于幀率的設(shè)置
# 更新精靈組 碰撞檢測 刷新屏幕這些事情 是要實時檢測的
# 所以我寫在游戲循環(huán)里面
# 沒1/60秒 就會調(diào)用一次
# 創(chuàng)建精靈和精靈組
def __create_sprites(self):
bg1 = Background()
# True 就表示是第二張圖片
bg2 = Background(True)
# 首先你要知道 你需要先 創(chuàng)建背景精靈 需要把精靈的修改一下
# bg1 = Background('images/background.png')
# bg2 = Background('images/background.png')
# # 我們發(fā)現(xiàn) 兩張圖片的位置我們需要設(shè)置一下
# bg2.rect.y = -bg2.rect.height
# 我們已經(jīng)創(chuàng)建了背景精靈 我們接下來可以創(chuàng)建一個背景精靈組
# 背景組 把我們的背景扔進(jìn) 背景精靈組
#------------------------------------------
# 英雄
self.hero = Hero(60)
self.hero1 = Hero(-60)
self.back_group = pygame.sprite.Group(bg1, bg2)
# 敵機組
self.enemy_group = pygame.sprite.Group()
# 英雄組
self.hero_group = pygame.sprite.Group(self.hero,self.hero1)
# 事件監(jiān)聽
def __event_handler(self):
# 在這里我先寫 事件監(jiān)聽 為啥呢?在調(diào)試過程中我好關(guān)閉窗口呀
for event in pygame.event.get():
# 另外一個方案 返回按鍵元組 這個我們觀察一下就知道了
# 如果 某個按鍵按下 對應(yīng)的值應(yīng)該會是
key_pressed = pygame.key.get_pressed()
key_pressed1 = pygame.key.get_pressed()
if key_pressed[pygame.K_KP1]:
self.hero.fire()
if key_pressed[pygame.K_RIGHT]:
print("向右邊移動")
# 給英雄一個移動速度
self.hero.speed = 8
elif key_pressed[pygame.K_LEFT]:
self.hero.speed = -8
print("向左邊移動")
elif key_pressed[pygame.K_UP]:
print("向上邊移動")
self.hero.speed1 = -8
elif key_pressed[pygame.K_DOWN]:
print("想下邊移動")
self.hero.speed1 = 8
else:
self.hero.speed = 0
self.hero.speed1 = 0
# pygame.event.get():這是 獲取到我們所有的事件
if event.type == pygame.QUIT:
# 哈哈 我調(diào)用方法 是不是相當(dāng)于可以關(guān)閉我們的窗口啦?。?!
# 在開發(fā)的過程中需要 有這種思想 專門的事情由專門的方法去做
self.__game_over()
# event.type 相當(dāng)于說之前 是通過我們按鍵盤或者
# 移動鼠標(biāo) 產(chǎn)生事件
# 那么現(xiàn)在呢 是我們自己創(chuàng)造一個事件 每秒執(zhí)行一次
# 然后我們?nèi)ケO(jiān)聽我們自己 讓 系統(tǒng)去每秒調(diào)用的事件
# 如果調(diào)到 那就說明監(jiān)聽成功
# 那么既然監(jiān)聽監(jiān)聽成功 我需要在監(jiān)聽成功后
# 去創(chuàng)建敵機 因為我的目的 就是每秒創(chuàng)建一家敵機
elif event.type == CREATE_ENEMY_EVENT:
# 因為我的敵機精靈類還沒有寫
# 我這里就先輸出一下
# 其實這一步 我們完全可以先運行一下
# 看看有沒有出錯 看看是不是每秒調(diào)用一次
print("新的敵機產(chǎn)生")
# 我們添加了敵機 但是但是但是
# 沒有刷新呀!
self.enemy_group.add(Enemy())
#elif event.type == HERO_FIRE_EVENT:
#self.hero.fire()
#self.hero1.fire()
if key_pressed1[pygame.K_SPACE]:
self.hero1.fire()
if key_pressed1[pygame.K_d]:
print("向右邊移動")
# 給英雄一個移動速度
self.hero1.speed = 8
elif key_pressed1[pygame.K_a]:
self.hero1.speed = -8
print("向左邊移動")
elif key_pressed1[pygame.K_w]:
print("向上邊移動")
self.hero1.speed1 = -8
elif key_pressed1[pygame.K_s]:
print("想下邊移動")
self.hero1.speed1 = 8
else:
self.hero1.speed = 0
self.hero1.speed1 = 0
# 更新精靈和精靈組
def __update_sprites(self):
"""更新精靈組"""
# 我們這一步 先更新背景組
# 刷新位置
# self.back_group.update()
# # 繪制到屏幕上 類似blit
# self.back_group.draw(self.screen)
# self.enemy_group.update()
# self.enemy_group.draw(self.screen)
# self.hero_group.update()
# self.enemy_group.draw(self.screen)
# 到這里我們就可以簡寫代碼了 改造 看了比較清爽
for xxx in [self.back_group, self.enemy_group, self.hero_group, self.hero.bullets, self.hero1.bullets]:
xxx.update()
xxx.draw(self.screen)
def __check_collide(self):
"""接下來我們就需要完成碰撞檢測"""
# 1 子彈摧毀飛機
# 子彈炸毀敵機 的情況:
# 地一個參數(shù)和第二個參數(shù)是要參與碰撞檢測的精靈
# 地三個參數(shù)為 Ture的時候 就是當(dāng)碰撞的時候 被碰撞的精靈從精靈組移出
pygame.sprite.groupcollide(
self.enemy_group, self.hero.bullets,True, True)
# 2 敵機撞毀飛機
enemies = pygame.sprite.spritecollide(
self.hero, self.enemy_group, True)
pygame.sprite.groupcollide(
self.enemy_group, self.hero1.bullets, True, True)
enemies1 = pygame.sprite.spritecollide(
self.hero1, self.enemy_group, True)
# 判斷列表時候有內(nèi)容
if len(enemies) == 1:
# 讓英雄犧牲
self.hero.kill()
self.hero.rect.x = -SCREEN_RECT.width
if len(enemies1) == 1:
self.hero1.kill()
self.hero1.rect.x = -SCREEN_RECT.width
if self.hero.rect.x == -SCREEN_RECT.width and self.hero1.rect.x == -SCREEN_RECT.width:
# 結(jié)束游戲
self.__game_over()
def __game_over(self):
"""游戲結(jié)束"""
print("游戲結(jié)束")
# 這是pygame提供的卸載模塊的功能
pygame.quit()
# 這是python本身提供的退出腳本的功能
exit()
# 總結(jié) :我們需要先卸載我們的pygame模塊 然后退出我們的腳本
# 這個方法就是在我當(dāng)前方法內(nèi)生效 在其他模塊調(diào)不到
if __name__ == "__main__":
# 創(chuàng)建游戲?qū)ο?
game = PlaneGame()
# 開始游戲
game.start_game()
"""
來講講類的設(shè)計吧! 這個游戲類 我們主要就是考慮邏輯性 當(dāng)然 你按照之前的學(xué)習(xí)快速入門的內(nèi)容 也能搞出
一個打飛機 但是我們需要把我們的代碼寫的邏輯清晰 并且
分工明確
關(guān)于 planeGame類 我們內(nèi)部是這么設(shè)計的
PlaneGame為我們的主游戲類
包含這些屬性 screen--->游戲屏幕 clock--->游戲時鐘
設(shè)計了幾個方法 分別做不同的事情
1 初始化方法:設(shè)置我們的初始化屬性
2 創(chuàng)建精靈 __create_sprites(self): 這里我設(shè)置成私有方法
3 start_game(self): 是開始游戲的方法
4 事件監(jiān)聽 event_handler
5 碰撞檢測 check_collider
6 更新精靈和精靈組(主要是為了實時去改變和繪制我們精靈
游戲精靈(背景 飛機 敵機 子彈 的位置
7 結(jié)束游戲 game_over
大致我們就分析完了 現(xiàn)在來開始寫我們的代碼
"""
另一個代碼
"""
這是我們剛剛說的 另外一個需要設(shè)計的模塊
在這個模塊 放一些常用工具和 基礎(chǔ)類 和精靈類
在其他模塊調(diào)用
"""
import pygame
import random
# 設(shè)置游戲屏幕小大 這是一個常量
# 常量見名知意 就是不需要猜測的數(shù)字的含義 就是一個固定的數(shù)值
# 通過一處修改 其他地方也能生效 統(tǒng)一控制
SCREEN_RECT = pygame.Rect(0, 0, 480,700)
# 我們的父類需要考慮這幾個問題
# 1 通用性 2 屬性有哪些 方法有哪些 將來誰要用
# 我們自己去定制的精靈類 需要繼承 pygame提供的精靈類
"""
我們需要定義的屬性有:
image-->圖片
rect--->坐標(biāo)
speed -->速度
"""
# 接下來我們就開始寫我們敵機方面的內(nèi)容 (產(chǎn)生敵機)
# 我先定義一個事件常量
CREATE_ENEMY_EVENT = pygame.USEREVENT
# 我們還可以定義一個事件常量 (發(fā)射子彈)
HERO_FIRE_EVENT = pygame.USEREVENT + 1
GameSprite(pygame.sprite.Sprite):
"""游戲精靈的基礎(chǔ)類"""
# 我們其實可以給我們的基礎(chǔ)類的速度 設(shè)置一個默認(rèn)值
def __init__(self,new_image,new_speed=1):
super().__init__()
# 我們需要以下3個屬性
# 考慮到通用性 我們需要改造一下代碼
# pygame.image.load pygame提供的方法 主要是加載圖片
self.image = pygame.image.load(new_image)
# self.image.get_rect() 獲取圖片的寬高 get_rect() 是pygame提供
self.rect = self.image.get_rect()
# 這是將來精靈的移動速度 精靈有:英雄精靈 背景精靈 敵機精靈 子彈精靈
self.speed = new_speed
def update(self):
# 默認(rèn)垂直方向移動 (這個時候我就要有一個概念 坐標(biāo)系的y軸控制垂直
self.rect.y += self.speed
# 那么以上就是我們游戲的基礎(chǔ)類 接下來我們需要設(shè)置我們的 背景類
# 首先我們需要先明確我們的背景類 繼承自我們的游戲精靈類
class Background(GameSprite):
"""背景精靈類"""
def __init__(self,is_alt=False):
"""is_alt 判斷是否為另外一張圖像
False表示第一張圖像
True表示另外一張圖像 我們最開始說了 我們是2張圖像交替
在這里我先設(shè)置一下 vim快捷鍵
"""
# 因為背景圖片是固定的 所以我們可以在背景精靈類直接傳圖片
super().__init__('./images/background.png')
if is_alt:
# 如果是地二張圖片 我們讓他的初始位置為 -self.rect.height
self.rect.y = -self.rect.height
def update(self):
# 1 調(diào)用父類的方法實現(xiàn) 這是實現(xiàn)父類方法
super().update()
# 2 判斷是否移除屏幕 如果移出屏幕 我們就要將圖像設(shè)置到屏幕到上方
# SCREEN_RECT.height 這是我們自己設(shè)置的常量 我們可以往上看
# 其實到這一步 我們就已經(jīng)把我們的背景類設(shè)計完了 接下來我們就去我們的主程序模塊調(diào)用就行了
if self.rect.y >= SCREEN_RECT.height:
self.rect.y = -self.rect.height
# 接下來我們就要設(shè)置我們的敵機類
# 我們的敵機類 同樣也是繼承自我們的精靈基類
class Enemy(GameSprite):
"""敵機精靈類"""
def __init__(self):
# 1 調(diào)用父類方法 創(chuàng)建敵機精靈類 并且指定敵機圖像
super().__init__('./images/enemy1.png')
# 2 設(shè)置敵機初始速度 稍后設(shè)置 (隨機數(shù))
# 我的sublime 沒有花事件去調(diào) 老是跟我發(fā)脾氣
self.speed = random.randint(1, 3)
# 3 設(shè)置敵機的隨機初始位置 稍后設(shè)置
# self.rect.y = self.rect.bottom - self.rect.height
self.rect.bottom = 0
# 敵機x軸最大值 需要用屏幕的寬度-敵機自身的寬度
max_x = SCREEN_RECT.width - self.rect.width
# 隨機一個位置
self.rect.x = random.randint(0, max_x)
# 我們發(fā)現(xiàn)。。。。。敵機出來的位置在 一條線上
# 說明 x軸的位置一直沒有變
def update(self):
# 1 調(diào)用父類方法
super().update()
# 2 判斷是否飛出屏幕 如果是 需要敵機從精靈組刪除
if self.rect.y >= SCREEN_RECT.height:
print("敵機飛出屏幕")
# 移出屏幕 就銷毀
self.kill()
# 接下來我們就設(shè)計英雄類和子彈類
# 英雄精靈類
class Hero(GameSprite):
"""英雄精靈類"""
def __init__(self,a):
# 英雄的初始速度我設(shè)置為0
super().__init__('./images/me1.png',0)
# 設(shè)置初始位置 這是是讓我英雄X軸的中心點等于屏幕X軸中心點
self.rect.centerx = SCREEN_RECT.centerx + a
# 這里是設(shè)置我飛機的y軸
self.rect.bottom = SCREEN_RECT.bottom
# 子彈組
self.bullets = pygame.sprite.Group()
# 這樣 我們的子彈精靈組 就創(chuàng)建完畢了 我們就要去fire里面修改我們的
# 方法
self.speed1 = 0
def update(self):
# 飛機水平移動
self.rect.x += self.speed
self.rect.y += self.speed1
# 控制英雄邊界 屏幕邊界
if self.rect.left < 0:
self.rect.left = 0
if self.rect.right >SCREEN_RECT.right:
self.rect.right = SCREEN_RECT.right
if self.rect.bottom > SCREEN_RECT.height:
self.rect.bottom = SCREEN_RECT.height
if self.rect.top < 0:
self.rect.top = 0
def fire(self):
# 英雄的方法。。。發(fā)射子彈 是一個動作 是一個行為 。。。
print("發(fā)射子彈....")
for i in (1,2,3):
# 子彈精靈 我們在 英雄的這個fire()方法里面去創(chuàng)建
#1 創(chuàng)建 子彈精靈
bullet = Bullet()
gws = Bullet()
sst = Bullet()
#2 設(shè)置精靈位置
bullet.rect.bottom = self.rect.y -20
bullet.rect.centerx = self.rect.centerx
gws.rect.bottom = self.rect.y -20
gws.rect.centerx = self.rect.centerx +15
sst.rect.bottom = self.rect.y -20
sst.rect.centerx = self.rect.centerx -15
#3 將精靈添加到精靈組
self.bullets.add(bullet,gws,sst)
class Bullet(GameSprite):
"""子彈精靈"""
def __init__(self):
super().__init__('./images/bullet1.png',-10)
def update(self):
super().update()
# 判斷是否超出屏幕
if self.rect.bottom < 0:
self.kill()
這就是基本的飛機大戰(zhàn)