2015/11/6用Python寫遊戲,pygame入門(6):控制大量的對象

昨天咱們已經實現了這個遊戲的三個基本類。app

可是如今它仍是沒辦法作成一個適合玩的遊戲,畢竟只有一架敵機的遊戲是很乏味的。因此,咱們須要好多子彈,也須要好多敵機。dom

因此,咱們要建立list,這個list存放Bullet或者Enemy的實例。函數

以Bullet爲例:ui

bullet = [] #建立子彈
for i in range(6):
    bullet.append(Bullet())
...
for b in bullet:#移動子彈
        b.move(time_passed_second)
...
for b in bullet:#顯示子彈
        screen.blit(b.image, (b.x, b.y))

咱們能夠用這樣的代碼替換咱們原來建立子彈,移動子彈和顯示子彈的部分。可是實際運行結果卻並無變化。這是爲何?spa

由於一個list的子彈都按照了一樣的方法建立和發射了,全部的子彈在同一時間發射了出去,同時到達了屏幕上方,而後又同時發射。這樣的效果和發射一發子彈是沒有區別的。因此咱們要讓它按照必定的時間間隔,一個個地發射。3d

另外,若是到了屏幕頂端就回頭了,從新發射的子彈和按時發射的子彈混在了一塊兒,打亂了發射節奏,因此子彈回收的方法也要更改。咱們能夠選擇每發子彈只寫它的發射,不寫它的回收,可是這樣每發射一發子彈就會建立一個空間,讀取一次圖片,這樣會消耗內存資源,通常都應該避免。rest

那麼咱們必須解決兩個問題,一個是定時發射,一個是回收子彈。code


 

Python有專門的time模塊,可是,在遊戲中,咱們原本就有幀率固定的循環,只要用一個計數器來計數,每隔多少個循環出發一次,就能夠實現定時效果。blog

好比說,咱們定義一個子彈發射的間隔interval_bullet,讓它遞增或者遞減,到達某個數後,就重置間隔,而且運行特定的程序,就可使子彈定時發射。隊列

若是要重複利用子彈,咱們可讓子彈自己多一個屬性,來代表這個子彈是否應該被激活,只有它是激活狀態,咱們去處理它的運動和顯示。

子彈自己是能夠重複利用的,咱們用一個循環隊列的結構來處理子彈的利用。

依照這樣的方法,咱們能夠修改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()
        self.active = False

    def move(self, passed_time_second):
        if self.y < 0:
            self.active = False
        else:
            self.y -= self.speed*passed_time_second

    def restart(self):
        self.active = True
        mouseX, mouseY = pygame.mouse.get_pos()
        self.x = mouseX - self.image.get_width()/2
        self.y = mouseY - self.image.get_width()/2

添加了一個從新激活該子彈的方法restart(),還添加了一個數據屬性active來標記子彈自己是否被激活。而後,咱們把添加子彈,移動子彈,顯示子彈部分的代碼改爲這樣:

bullet = []
for i in range(6):#子彈總數量
    bullet.append(Bullet())
interval_bullet = 25 #發射子彈的幀數間隔
index_bullet = 0 #初始化子彈座標
...
 interval_bullet -= 1
    if interval_bullet <= 0:
        interval_bullet = 25
        bullet[index_bullet].restart()
        index_bullet = (index_bullet + 1) % 6
        
    for b in bullet:
        if b.active:
            b.move(time_passed_second)#移動子彈
            screen.blit(b.image, (b.x, b.y))#顯示子彈

結果就是這樣了:

子彈完成了之後,飛機還會遠麼?


 

你們能夠本身想想敵機應該怎麼去寫,敵機不一樣的是,先後的間隔應該有更多的隨機性。

我這裏就不給出一步步的指南了,把本身實現的代碼整個貼上來,也許你們有更好的控制方式,能夠一塊兒交流一下:

# -*- 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()
        self.active = False

    def move(self, passed_time_second):
        if self.y < 0:
            self.active = False
        else:
            self.y -= self.speed*passed_time_second

    def restart(self):
        self.active = True
        mouseX, mouseY = pygame.mouse.get_pos()
        self.x = mouseX - self.image.get_width()/2
        self.y = mouseY - self.image.get_width()/2

class Enemy(object):#定義一個Enemy類,封裝敵機的數據和方法
    def restart(self):
        self.x = randint(-30,400)
        self.y = randint(-100, -50)
        self.speed = randint(100,400)
        self.active = True
    def __init__(self):
        self.restart()
        self.active = False
        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.active = False

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 = []
for i in range(6):#子彈總數量
    bullet.append(Bullet())
interval_bullet = 25 #發射子彈的幀數間隔
index_bullet = 0 #初始化子彈座標
enemy = []
for i in range(10):#敵機總數量
    enemy.append(Enemy())
interval_enemy = 100 #敵機出現的間隔
index_enemy = 0 #初始化敵機座標
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()
    #得到鼠標位置

    interval_bullet -= 1
    if interval_bullet <= 0:
        interval_bullet = 25
        bullet[index_bullet].restart()#重置子彈
        index_bullet = (index_bullet + 1) % 6 #循環遞增
        
    for b in bullet:
        if b.active:
            b.move(time_passed_second)#移動子彈
            screen.blit(b.image, (b.x, b.y))#顯示子彈

    interval_enemy -= 1
    if interval_enemy <= 0:
        interval_enemy = randint(30,100)
        enemy[index_enemy].restart() #重置飛機
        index_enemy = (index_enemy + 1) % 10 #循環遞增
    for e in enemy:
        if e.active:
            e.move(time_passed_second) #移動敵機
            screen.blit(e.image, (e.x, e.y)) #顯示敵機
        
    
    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()
    #刷新一下畫面

相關文章
相關標籤/搜索