前言
本文的文字及圖片來源于網路,僅供學習、交流使用,不具有任何商業用途,著作權歸原作者所有,如有問題請及時聯系我們以作處理,
安裝pygame并創建能左右移動的飛船
安裝pygame
本人電腦是windows 10、python3.6,pygame下載地址:https://pypi.python.org/pypi/Pygame/1.9.3請自行下載對應python版本的pygame運行以下命令
$ pip install wheel $ pip install pygame?1.9.3?cp36?cp36m?win_amd64.whl
創建Pygame視窗及回應用戶輸入
新建一個檔案夾alien_invasion,并在檔案夾中新建alien_invasion.py檔案,輸入如下代碼,
import sys
import pygame
def run_game():
#initialize game and create a dispaly object
pygame.init()
screen = pygame.display.set_mode((1200,800))
pygame.display.set_caption("Alien Invasion")
# set backgroud color
bg_color = (230,230,230)
# game loop
while True:
# supervise keyboard and mouse item
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# fill color
screen.fill(bg_color)
# visualiaze the window
pygame.display.flip()
run_game()
運行上述代碼,我們可以得到一個灰色界面的視窗:
$ python alien_invasion.py
創建設定類
為了在寫游戲的程序中能便捷地創建一些新功能,下面額外撰寫一個settings模塊,其中包含一個Settings類,用于將所有設定存盤在一個地方,這樣在以后專案增大時修改游戲的外觀就更加容易,我們首先將alien_invasion.py中的顯示屏大小及顯示屏顏色進行修改,首先在alien_invasion檔案夾下新建python檔案settings.py,并向其中添加如下代碼:
class Settings(object): """docstring for Settings""" def __init__(self): # initialize setting of game # screen setting self.screen_width = 1200 self.screen_height = 800 self.bg_color = (230,230,230)
然后在alien_invasion.py中匯入Settings類,并使用相關設定,修改如下:
import sys
import pygame
from settings import Settings
def run_game():
#initialize game and create a dispaly object
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
pygame.display.set_caption("Alien Invasion")
# set backgroud color
bg_color = (230,230,230)
# game loop
while True:
# supervise keyboard and mouse item
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# fill color
screen.fill(ai_settings.bg_color)
# visualiaze the window
pygame.display.flip()
run_game()
添加飛船影像
接下來,我們需要將飛船加入游戲中,為了在螢屏上繪制玩家的飛船,我們將加載一幅影像,再使用Pygame()方法blit()繪制它,在游戲中幾乎可以使用各種型別的影像檔案,但是使用位圖(.bmp)檔案最為簡單,這是因為Pygame默認加載位圖,雖然其他型別的影像也能加載,但是需要安裝額外的庫,我們推薦去免費的圖片素材網站上去找影像:https://pixabay.com/我們在主專案檔案夾(alien_invasion)中新建一個檔案夾叫images,將如下bmp圖片放入其中,
接下來,我們創建飛船類ship.py:
import pygame
class Ship():
def __init__(self,screen):
#initialize spaceship and its location
self.screen = screen
# load bmp image and get rectangle
self.image = pygame.image.load('image/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
#put spaceship on the bottom of window
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
def blitme(self):
#buld the spaceship at the specific location
self.screen.blit(self.image,self.rect)
最后我們在螢屏上繪制飛船,即在alien_invasion.py檔案中呼叫blitme方法:
import sys
import pygame
from settings import Settings
from ship import Settings
def run_game():
#initialize game and create a dispaly object
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
ship = Ship(screen)
pygame.display.set_caption("Alien Invasion")
# set backgroud color
bg_color = (230,230,230)
# game loop
while True:
# supervise keyboard and mouse item
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# fill color
screen.fill(ai_settings.bg_color)
ship.blitme()
# visualiaze the window
pygame.display.flip()
run_game()
重構:模塊game_functions
在大型專案中,經常需要在添加新代碼前重構既有代碼,重構的目的是為了簡化代碼的結構,使其更加容易擴展,我們將實作一個game_functions模塊,它將存盤大量讓游戲Alien invasion運行的函式,通過創建模塊game_functions,可避免alien_invasion.py太長,使其邏輯更容易理解,
函式check_events()
首先我們將管理事件的代碼移到一個名為check_events()的函式中,目的是為了隔離事件回圈
import sys import pygame def check_events(): #respond to keyboard and mouse item for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit()
然后我們修改alien_invasion.py代碼,匯入game_functions模塊,并將事件回圈替換成對函式check_events()的呼叫:
import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
def run_game():
#initialize game and create a dispaly object
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
ship = Ship(screen)
pygame.display.set_caption("Alien Invasion")
# set backgroud color
bg_color = (230,230,230)
# game loop
while True:
# supervise keyboard and mouse item
gf.check_events()
# fill color
screen.fill(ai_settings.bg_color)
ship.blitme()
# visualiaze the window
pygame.display.flip()
run_game()
函式update_screen()
將更新螢屏的代碼移到一個名為update_screen()函式中,并將這個函式放在模塊game_functions中:
def update_screen(ai_settings,screen,ship): # fill color screen.fill(ai_settings.bg_color) ship.blitme() # visualiaze the window pygame.display.flip()
其中alien_invasion修改如下:
import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
def run_game():
#initialize game and create a dispaly object
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
ship = Ship(screen)
pygame.display.set_caption("Alien Invasion")
# set backgroud color
bg_color = (230,230,230)
# game loop
while True:
# supervise keyboard and mouse item
gf.check_events()
gf.update_screen(ai_settings,screen,ship)
run_game()
從上面一套流程走下來,我們發現:在實際的開發程序中,我們一開始將代碼撰寫得盡可能的簡單,并在專案越來越復雜時進行重構,接下來我們開始處理游戲的動態方面,
駕駛飛船
這里我們要實作的就是使玩家通過左右箭頭鍵來控制飛船的左移與右移,
回應按鍵
因為在pygame中,每次按鍵都被注冊為KEYDOWN事件,在check_events()中,我們通過event.type檢測到KEYDOWN事件后還需進一步判斷是哪個按鍵,代碼如下:
def check_events(ship): #respond to keyboard and mouse item for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_RIGHT: #move right ship.rect.centerx +=1
允許不斷移動
玩家按住右箭頭不動時,我們希望飛船能不斷地移動,直到玩家松開為止,這里我們通過KETUO事件來判斷,因此我們設定一個標志位moving_right來實作持續移動,原理如下:
飛船不動時,標志moving_right將為false,玩家按下右箭頭時,我們將這個標志設定為True;玩家松開時,我們將標志重新設定成False,這個移動屬性是飛船屬性的一種,我們用ship類來控制,因此我們給這個類增加一個屬性名稱叫,moving_right以及一個update()方法來檢測標志moving_right的狀態,ship
self.moving_right = False def update(self): if self.moving_right: self.rect.centerx +=1
game_functions
elif event.type == pygame.KEYDOWN: if event.key == pygame.K_RIGHT: #move right ship.moving_right = True elif event.type == pygame.KEYUP: if event.key = pygame.K_RIGHT: ship.moving_right = False
最后在alien_invasion中呼叫update()方法
while True: # supervise keyboard and mouse item gf.check_events(ship) ship.update()
左右移動
前面我們實作了向右移動,接下來實作向左移動,邏輯類似,代碼就不貼了,
調整飛船的速度
當前,每次執行while回圈時,飛船最多移動一個像素,我們可以在Settings中添加ship_speed_factor,用于控制飛船的速度,我們將根據這個屬性決定飛船每次回圈時最多移動多少距離,Settings:
class Settings(object): """docstring for Settings""" def __init__(self): # initialize setting of game # screen setting self.screen_width = 1200 self.screen_height = 800 self.bg_color = (230,230,230) self.ship_speed_factor = 1.5
Ship:
class Ship(): def __init__(self,ai_settings,screen): #initialize spaceship and its location self.screen = screen self.ai_settings = ai_settings
限制飛船的活動范圍
如果玩家按住箭頭的時間過長,飛船就會消失,那么如何使飛船抵達螢屏邊緣時停止移動?這里我們只需要修改Ship類中的update方法,增加一個邏輯判斷,
重構
這里我們主要將check_events()函式進行重構,將其中部分代碼分成兩部分,一部分處理KEYDOWN事件,一部分處理KEYUP事件,game_functions:
def check_keydown_events(event,ship): if event.key == pygame.K_RIGHT: #move right ship.moving_right = True elif event.key == pygame.K_LEFT: #move right ship.moving_left = True def check_keyup_events(event,ship): if event.key == pygame.K_RIGHT: ship.moving_right = False elif event.key == pygame.K_LEFT: #move right ship.moving_left = False def check_events(ship): #respond to keyboard and mouse item for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() elif event.type == pygame.KEYDOWN: check_keydown_events(event,ship) elif event.type == pygame.KEYUP: check_keyup_events(event,ship)
射擊
接下來添加射擊功能,使玩家按空格鍵時發射子彈,子彈將在螢屏中向上穿行,抵達螢屏后消失,
添加子彈設定
在Settings類中增加一些子彈的屬性,這里我們創建一個寬3像素,高15像素的深灰色子彈,子彈的速度比飛船稍低,
創建Bullet類
import pygame from pygame.sprite import Sprite class Bullet(Sprite): """A class to manage bullets fired from the ship.""" def __init__(self, ai_settings, screen, ship): """Create a bullet object, at the ship's current position.""" super().__init__() self.screen = screen # Create bullet rect at (0, 0), then set correct position. self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height) self.rect.centerx = ship.rect.centerx self.rect.top = ship.rect.top # Store a decimal value for the bullet's position. self.y = float(self.rect.y) self.color = ai_settings.bullet_color self.speed_factor = ai_settings.bullet_speed_factor def update(self): """Move the bullet up the screen.""" # Update the decimal position of the bullet. self.y -= self.speed_factor # Update the rect position. self.rect.y = self.y def draw_bullet(self): """Draw the bullet to the screen.""" pygame.draw.rect(self.screen, self.color, self.rect)
將子彈存盤到group中
前面定義了Bullet類和必要的設定后,就可以撰寫代碼了,在玩家每次按空格鍵時都會發射一發子彈,首先,我們在alien_invasion中創建一個group,用于存盤所有的有效子彈,
def run_game():
#initialize game and create a dispaly object
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
ship = Ship(ai_settings,screen)
bullets = Group()
pygame.display.set_caption("Alien Invasion")
# set backgroud color
bg_color = (230,230,230)
# game loop
while True:
# supervise keyboard and mouse item
gf.check_events(ai_settings, screen, ship,bullets)
ship.update()
bullets.update()
gf.update_screen(ai_settings, screen, ship,bullets)
開火
這里我們修改check_keydown_events()函式,來監聽玩家按下空格鍵的事件,這里還需要修改update_screen()函式,確保螢屏每次更新時,都能重繪每一個子彈,我們來看下效果:
洗掉消失的子彈
在alien_invasion中洗掉消失的子彈,
import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
def run_game():
#initialize game and create a dispaly object
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height))
ship = Ship(ai_settings,screen)
bullets = Group()
pygame.display.set_caption("Alien Invasion")
# set backgroud color
bg_color = (230,230,230)
# game loop
while True:
# supervise keyboard and mouse item
gf.check_events(ai_settings, screen, ship,bullets)
ship.update()
bullets.update()
for bullet in bullets.copy():
if bullet.rect.bottom <=0:
bullets.remove(bullet)
gf.update_screen(ai_settings, screen,ship,bullets)
run_game()
限制子彈數量
為了鼓勵玩家有目標的射擊,我們規定螢屏上只能同時存在3顆子彈,我們只需要在每次創建子彈前檢查未消失的子彈數目是否小于3即可,
創建update_bullets()函式
為了使alien_invasion中代碼更加簡單,我們將檢查子彈管理的代碼,移到game_functions模塊中:
def update_bullets(bullets): bullets.update() for bullet in bullets.copy(): if bullet.rect.bottom<=0: bullets.remove(bullet)
創建fire_bullet()函式
這里我們將發射子彈的代碼移到一個獨立的函式中:
def fire_bullet(ai_settings,screen,ship,bullets): if len(bullets) < ai_settings.bullets_allowed: new_bullet = Bullet(ai_settings,screen,ship) bullets.add(new_bullet)
添加外星人,并檢測碰撞
在我們完成新的任務之前,我們先給游戲添加一個結束游戲的快捷鍵Q:
創建第一個外星人
這里和創建飛船的方法一樣
class Alien(Sprite):
"""A class to represent a single alien in the fleet."""
def __init__(self, ai_settings, screen):
"""Initialize the alien, and set its starting position."""
super().__init__()
self.screen = screen
self.ai_settings = ai_settings
# Load the alien image, and set its rect attribute.
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()
# Start each new alien near the top left of the screen.
self.rect.x = self.rect.width
self.rect.y = self.rect.height
# Store the alien's exact position.
self.x = float(self.rect.x)
def blitme(self):
"""Draw the alien at its current location."""
self.screen.blit(self.image, self.rect)
創建一群外星人
這里我們首先確定一行能容納多少個外星人以及要繪制幾行,這里改動代碼較多,直接看效果:
移動外星人
前面我們創建的是靜態的外星人,現在我們需要讓外星人動起來,這里我們在Settings類中設定外星人移動的速度,然后通過Alien類中的update的方法來實作移動
射殺外星人
要想射殺外星人,就必須先檢測兩個編組成員之間是否發生碰撞,在游戲中,碰撞就是游戲元素重疊在一起,這里我們使用sprite.groupcollide()來檢測兩個編組的成員之間的碰撞,子彈擊中外星人時,需要立馬知道,并同時使被碰撞的外星人立即消失,因此我們需要在更新子彈的位置后立即檢測碰撞,
結束游戲
這里我們還需要知道何時該結束游戲,有以下幾種情況:
飛船全部被摧毀外星人到達螢屏底部實際效果:
計分
最后我們將給游戲添加一個Play按鈕,用于根據需要啟動游戲以及在游戲結束后重啟游戲,我們還將實作一個計分系統,能夠在玩家等級提高時加快節奏,
添加Play按鈕
這里可以先將游戲初始化為非活動狀態,當我們點擊了按鈕,就開始游戲,由于Pygame中沒有內置的創建按鈕的方法,因此我們可以通過創建一個Button類來創建一個自帶標簽的實心矩形,我們通過檢測滑鼠發生點擊后的坐標是否與我們繪制的按鈕發生碰撞與否來判斷是否發生了點擊事件,
提高等級
為了使玩家將敵人消滅干凈后能夠提高游戲難度,增加趣味性,這里我們可以在Settings類中進行修改,增加靜態初始值,和動態初始值,
記分、等級、剩余飛船
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/105973.html
標籤:Python
上一篇:后臺開發經驗總結
