2015/11/5用Python寫游戲,pygame入門(5):面向對象的游戲設計


昨天的內容里有了運動的子彈,雖然我們只添加了一個子彈,但你可以看到我們需要記錄子彈的x,y坐標,每次要更新它的坐標。如果我們想要有多顆子彈,就需要存儲多個坐標。那時候處理起來就不顯得那么簡單,也許我們可以使用兩個list,一個專門存儲各個子彈的x坐標,另一個專門存儲子彈的y坐標,問題似乎變得沒那么復雜,寫起來會簡單一些。但是我們到現在還沒有加入過敵機,如果加入了敵機,加入別的東西的設計,我們將需要很多不同的數據的存儲。雖然一個思路清晰的程序員可以記住所有的坐標存儲在哪個list里,但是這畢竟比較麻煩。那有什么方法呢?

這就需要提到程序語言的數據抽象方法了,也就是面向對象的抽象方法,可以讓我們更好地處理數據。


面向對象的關鍵在於封裝,我們來看看應該怎樣封裝一個子彈。

描述一個子彈,最主要要用的就是它的圖片,坐標的位置。它需要的就這么多,還有是一段處理子彈顯示的代碼。

#定義一個Bullet類,封裝子彈的數據和方法
class Bullet(object):
    def __init__(self):
        self.x = 0
        self.y = -100
        self.speed = 600
        self.image = pygame.image.load(bullet_image_filename).convert_alpha()

    def move(self,passed_time_second):
        if self.y < 0:
            mouseX, mouseY = pygame.mouse.get_pos()
            self.x = mouseX - self.image.get_width()/2
            self.y = mouseY - self.image.get_width()/2
        else:
            self.y -= self.speed*passed_time_seconds

這段代碼的寫法和昨天寫的完全一樣,但是用了面向對象的寫法。然后我們將昨天的代碼更改一下:

# -*- coding: utf8 -*-

background_image_filename = 'background.png'
mouse_image_filename = 'hero.png'
bullet_image_filename = 'bullet.png'
#指定圖像文件名稱
 
import pygame #導入pygame庫
from sys import exit #向sys模塊借一個exit函數用來退出程序

#定義一個Bullet類,封裝子彈的數據和方法
class Bullet(object):
    def __init__(self):
        self.x = 0
        self.y = -100
        self.speed = 600
        self.image = pygame.image.load(bullet_image_filename).convert_alpha()

    def move(self, passed_time_second):
        if self.y < 0:
            mouseX, mouseY = pygame.mouse.get_pos()
            self.x = mouseX - self.image.get_width()/2
            self.y = mouseY - self.image.get_width()/2
        else:
            self.y -= self.speed*passed_time_second

pygame.init() #初始化pygame,為使用硬件做准備
screen = pygame.display.set_mode((480, 650), 0, 32)
#創建了一個窗口
pygame.display.set_caption("PlaneFight!")
#設置窗口標題
pygame.mouse.set_visible(False)
 
background = pygame.image.load(background_image_filename).convert()
mouse_cursor = pygame.image.load(mouse_image_filename).convert_alpha()
#加載並轉換圖像

bullet = Bullet()
clock = pygame.time.Clock()
while True:
#游戲主循環
 
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            #接收到退出事件后退出程序
            pygame.quit()
            exit()
    time_passed = clock.tick(100)
    time_passed_second = time_passed/1000.0
    screen.blit(background, (0,0))
    #將背景圖畫上去
    x, y = pygame.mouse.get_pos()
    #獲得鼠標位置
    bullet.move(time_passed_second)#移動子彈
        
    
    x-= mouse_cursor.get_width() / 2
    y-= mouse_cursor.get_height() / 2
    #計算光標的左上角位置
    
    screen.blit(bullet.image, (bullet.x, bullet.y))
    screen.blit(mouse_cursor, (x, y))
    #把元素畫上去
 
    pygame.display.update()
    #刷新一下畫面

這樣,我們就掌握了子彈的創建方法。


我們用同樣的思路去考慮敵機應該怎樣創建。

敵機需要封裝的數據,主要也是圖片,坐標。以及封裝一個處理它坐標變化的方法。

那么我們就可以定義敵機的類:

class Enemy(object):#定義一個Enemy類,封裝敵機的數據和方法
    def __init__(self):
        self.x = 200
        self.y = -50
        self.speed = 200
        self.image = pygame.image.load(enemy_image_filename).convert_alpha()

    def move(self, passed_time_second):
        if self.y < 650:
            self.y += self.speed*passed_time_second
        else:
            self.y = -50

然后用相同的方法給它實例化,顯示,就可以得到這樣的畫面:

敵機和子彈一樣,我們就將它顯示了出來。

但是,這里有個很明顯的問題,那就是敵機每次都從上面的中間飛到下面的中間,和真實游戲相差很多,怎么才能讓它多變呢?

這里我們可以import另外一個常用的庫了,也就是random

from random import randint

在開始加上這一句,引入randint(),這個方法用於生成隨機整數,可以給它兩個參數,分別作為下界和上界,使用時下界不能比上界大。

然后我們把這個Enemy類改寫成這樣:

class Enemy(object):#定義一個Enemy類,封裝敵機的數據和方法
    def restart(self):
        self.x = randint(-30,400)
        self.y = randint(-100, -50)
        self.speed = randint(100,400)
    def __init__(self):
        self.restart()
        self.image = pygame.image.load(enemy_image_filename).convert_alpha()

    def move(self, passed_time_second):
        if self.y < 650:
            self.y += self.speed*passed_time_second
        else:
            self.restart()

這樣,敵機的出現速度,出現位置都會發生變化,就顯得沒有那么呆板了。

整體的代碼如下:

# -*- coding: utf8 -*-

background_image_filename = 'background.png'
mouse_image_filename = 'hero.png'
bullet_image_filename = 'bullet.png'
enemy_image_filename = 'enemy.png'
#指定圖像文件名稱
 
import pygame #導入pygame庫
from sys import exit #向sys模塊借一個exit函數用來退出程序
from random import randint #引入隨機數

#定義一個Bullet類,封裝子彈的數據和方法
class Bullet(object):
    def __init__(self):
        self.x = 0
        self.y = -100
        self.speed = 600
        self.image = pygame.image.load(bullet_image_filename).convert_alpha()

    def move(self, passed_time_second):
        if self.y < 0:
            mouseX, mouseY = pygame.mouse.get_pos()
            self.x = mouseX - self.image.get_width()/2
            self.y = mouseY - self.image.get_width()/2
        else:
            self.y -= self.speed*passed_time_second

class Enemy(object):#定義一個Enemy類,封裝敵機的數據和方法
    def restart(self):
        self.x = randint(-30,400)
        self.y = randint(-100, -50)
        self.speed = randint(100,400)
    def __init__(self):
        self.restart()
        self.image = pygame.image.load(enemy_image_filename).convert_alpha()

    def move(self, passed_time_second):
        if self.y < 650:
            self.y += self.speed*passed_time_second
        else:
            self.restart()

pygame.init() #初始化pygame,為使用硬件做准備
screen = pygame.display.set_mode((480, 650), 0, 32)
#創建了一個窗口
pygame.display.set_caption("PlaneFight!")
#設置窗口標題
pygame.mouse.set_visible(False)
 
background = pygame.image.load(background_image_filename).convert()
mouse_cursor = pygame.image.load(mouse_image_filename).convert_alpha()
#加載並轉換圖像

bullet = Bullet()
enemy = Enemy()
clock = pygame.time.Clock()
while True:
#游戲主循環
 
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            #接收到退出事件后退出程序
            pygame.quit()
            exit()
    time_passed = clock.tick(100)
    time_passed_second = time_passed/1000.0
    screen.blit(background, (0,0))
    #將背景圖畫上去
    x, y = pygame.mouse.get_pos()
    #獲得鼠標位置
    bullet.move(time_passed_second)#移動子彈
    enemy.move(time_passed_second)
        
    
    x-= mouse_cursor.get_width() / 2
    y-= mouse_cursor.get_height() / 2
    #計算光標的左上角位置

    screen.blit(enemy.image, (enemy.x, enemy.y))
    screen.blit(bullet.image, (bullet.x, bullet.y))
    screen.blit(mouse_cursor, (x, y))
    #把各個元素畫上去
 
    pygame.display.update()
    #刷新一下畫面

今天除了將程序方法改成了面向對象以外,基本上也沒有多講什么。

現在,飛機只有一架,子彈只有一發,敵機也只有一架,感覺不出面向對象的威力,但當它數目多起來時,你會覺得面向對象的抽象的確很省事。

明天我就來給出我的多架飛機的方法。


由於我最近事情比較多,這個更新也寫的很拖沓,每天只講了一點點。對於每天在試着做的人來講是太慢了。不過我每天都會堅持更新,直到把這個游戲搭建起來。

覺得我講的慢的朋友,有兩個方法,一是自己試着查一些資料,二是先不管我的更新,一周以后再看,到時候就可以看到比較多的變化。

最近比較忙,沒辦法一氣呵成,不好意思了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM