飛機大戰(zhàn)

首先要下載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)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容