在學python之餘,根據書上的程式碼寫一個小遊戲,一方面是透過這個小遊戲來讓自己對面向物件的理解更深入一些,另一方面也為之後寫其他小遊戲打好基礎

編譯環境:pycharm+python3。7。6

標準庫:pygame,sys(pygame得安裝,sys是python自帶的,不用安裝)

pygame透過命令列安裝:

pip

install

pygame

-

i

https

//

pypi

mirrors

ustc

edu

cn

/

simple

/

不能訪問外網的話建議使用映象

豆瓣

http://

pypi。douban。com/simple/

清華大學

https://

pypi。tuna。tsinghua。edu。cn

/simple/

中國科學技術大學

http://

pypi。mirrors。ustc。edu。cn

/simple/

阿里雲

http://

mirrors。aliyun。com/pypi

/simple/

中國科技大學

https://

pypi。mirrors。ustc。edu。cn

/simple/

import pygame # 設計遊戲

import sys #退出遊戲

用python寫小遊戲——外星人入侵(基於pygame)

以上就是我使用的檔案,包含9個py檔案、一個image檔案、一個data檔案

其中image檔案是用來儲存外星人以及飛船影象的,在使用的時候儲存為ship。bmp檔案和alien。bmp檔案,這兩個檔案是點陣圖檔案,讀取時相對於jpg影象而言會比較快

用python寫小遊戲——外星人入侵(基於pygame)

用python寫小遊戲——外星人入侵(基於pygame)

而data檔案中有一個data。txt,裡面只有一個數據就是用來儲存最高分的

用python寫小遊戲——外星人入侵(基於pygame)

下面就給出具體程式碼

alien_invasion。py檔案,主要作用就是使用其他檔案所編寫的函式運行遊戲,起到main。py的作用

import

sys

import

pygame

from

settings

import

Settings

from

game_states

import

GameStats

from

ship

import

Ship

import

game_functions

as

gf

from

pygame。sprite

import

Group

from

button

import

Button

from

scoreboard

import

Scoreboard

def

run_game

():

# 初始化遊戲並建立一個螢幕物件

pygame

init

()

ai_settings

=

Settings

()

screen

=

pygame

display

set_mode

((

ai_settings

screen_width

ai_settings

screen_height

))

pygame

display

set_caption

‘Alien Invasion’

play_button

=

Button

ai_settings

screen

‘Play’

#建立play按鈕

stats

=

GameStats

ai_settings

# 建立一個用於儲存遊戲統計資訊的例項

sb

=

Scoreboard

ai_settings

screen

stats

ship

=

Ship

ai_settings

screen

# 建立一艘飛船

bullets

=

Group

()

# 建立一個用於儲存子彈的偏組

aliens

=

Group

()

# 建立外星人群

gf

creat_fleet

ai_settings

screen

ship

aliens

# 開始遊戲的主迴圈

while

True

# 監視鍵盤和滑鼠事件

gf

check_events

ai_settings

screen

stats

sb

play_button

ship

aliens

bullets

if

stats

game_active

ship

updata

()

gf

updata_bullets

ai_settings

screen

stats

sb

ship

aliens

bullets

gf

updata_aliens

ai_settings

screen

stats

sb

ship

aliens

bullets

gf

updata_screen

ai_settings

screen

stats

sb

ship

aliens

bullets

play_button

run_game

()

ship。py檔案,其作用就是編寫ship類

import pygame

from pygame。sprite import Sprite

class Ship(Sprite):

def __init__(self,ai_settings,screen):

‘’‘初始化飛船位置’‘’

super()。__init__()

self。screen=screen

self。ai_setting=ai_settings

# 載入飛船影象並獲取其外接矩形

self。image=pygame。image。load(‘images\ship。bmp’)

self。rect=self。image。get_rect()

self。screen_rect=screen。get_rect()

# 將每艘新飛船放在螢幕底部中央

self。rect。centerx=self。screen_rect。centerx

self。rect。bottom=self。screen_rect。bottom

# 在飛船的屬性center中儲存小數值

self。center=float(self。rect。centerx)

self。moving_right=False # 向右移動標誌

self。moving_left=False #向左移動標誌

def updata(self): # 根據移動位置調整飛船位置

# 更新飛船的center值而不是rect

if self。moving_right and self。rect。right

self。center+=self。ai_setting。ship_speed_factor

if self。moving_left and self。rect。left>0:

self。center-=self。ai_setting。ship_speed_factor

self。rect。centerx=self。center # 根據self。center更新rect物件

def blitme(self):

‘’‘在指定位置繪製飛船’‘’

self。screen。blit(self。image,self。rect)

def center_ship(self):

self。center=self。screen_rect。centerx # 讓飛船在螢幕上居中

alien。py檔案,用來編寫alien類

import pygame

from pygame。sprite import Sprite

class Alien(Sprite): # 表示單個外星人的類

def __init__(self,ai_settings,screen): # 初始化外星人

super()。__init__()

self。screen=screen

self。ai_settings=ai_settings

# 載入外星人影象,並設定其rect屬性

self。image=pygame。image。load(‘images/alien。bmp’)

self。rect=self。image。get_rect()

# 每個外星人最初都在螢幕左上角附近

self。rect。x=self。rect。width

self。rect。y=self。rect。height

# 儲存外星人的準確位置

self。x=float(self。rect。x)

def check_edges(self):

# 如果外星人位於螢幕邊緣,就返回True

screen_rect=self。screen。get_rect()

if self。rect。right>=screen_rect。right:

return True

elif self。rect。left<=0:

return True

def updata(self): # 向左或右移動外星人

self。x+=(self。ai_settings。alien_speed_factor*self。ai_settings。fleet_direction)

self。rect。x=self。x

def blitem(self): # 在指定位置繪製外星人

self。screen。blit(self。image,self。rect)

bullet。py檔案,用來編寫射擊類

import pygame

from pygame。sprite import Sprite

class Bullet(Sprite): # 對飛船發射子彈的類

def __init__(self,ai_settings,screen,ship):

super(Bullet,self)。__init__()

self。screen=screen

# 在(0,0)處建立一個表示子彈的矩形,再設定正確的位置

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

# 儲存用小數表示的子彈的位置

self。y=float(self。rect。y)

self。color=ai_settings。bullet_color

self。speed_factor=ai_settings。bullet_speed_factor

def updata(self): # 向上移動子彈

self。y -=self。speed_factor # 更新表示子彈位置的小數值

self。rect。y=self。y # 更新表示子彈的rect的位置

def draw_bullet(self): # 在螢幕上繪製子彈

pygame。draw。rect(self。screen,self。color,self。rect)

settings。py檔案,儲存外星人入侵的所有設定的類

class Settings(): #儲存外星人入侵的所有設定的類

def __init__(self):

‘’‘初始化遊戲的靜態設定’‘’

# 螢幕設定

self。screen_width=1200

self。screen_height=650

self。bg_color=(230,230,230)

# 飛船的設定

#self。ship_speed_factor=1。5 # 設定飛船的速度

self。ship_limit=3

# 子彈設定

#self。bullet_speed_factor=2

self。bullet_width=3

self。bullet_height=15

self。bullet_color=60,60,60

self。bullets_allowed=3 # 限制子彈數目

# 外星人設定

self。fleet_drop_speed = 10

# 以什麼樣的速度加快遊戲節奏

self。speedup_scale=1。1 # 外星人移動速度

self。score_scale=1。5 # 外星人分數的提高

self。initialize_dynamic_settings()

def initialize_dynamic_settings(self):

self。ship_speed_factor=1。5

self。bullet_speed_factor=3

self。alien_speed_factor=1

self。fleet_direction=1 # 1表示向右移動,-1表示向左移動

self。alien_points=10

def increase_speed(self): #提高速度

self。ship_speed_factor*=self。speedup_scale

self。bullet_speed_factor*=self。speedup_scale

self。alien_speed_factor*=self。speedup_scale

self。alien_points=int(self。alien_points*self。score_scale)

#print(self。alien_points)

button。py檔案,設定play按鈕

import pygame。font

class Button():

def __init__(self,ai_settings,screen,msg):

self。screen=screen

self。screen_rect=screen。get_rect()

# 設定按鈕的尺寸和其他屬性

self。width,self。height=200,50

self。button_color=(0,255,0)

self。text_color=(255,255,255)

self。font=pygame。font。SysFont(None,48)

# 建立按鈕的rect物件,並使其居中

self。rect=pygame。Rect(0,0,self。width,self。height)

self。rect。center=self。screen_rect。center

# 按鈕的標籤只需要建立一次

self。prep_msg(msg)

def prep_msg(self,msg):

# 將msg渲染為影象,並使其在按鈕上居中

self。msg_image=self。font。render(msg,True,self。text_color,self。button_color)

self。msg_image_rect=self。msg_image。get_rect()

self。msg_image_rect。center=self。rect。center

def draw_button(self):

# 繪製一個用顏色填充的按鈕,再繪製文字

self。screen。fill(self。button_color,self。rect)

self。screen。blit(self。msg_image,self。msg_image_rect)

game_states。py檔案,跟蹤遊戲的統計資訊,比如遊戲狀態,等級,分數等

class GameStats():

# 跟蹤遊戲的統計資訊

def __init__(self,ai_settings):

self。ai_settings=ai_settings

self。reset_stats()

self。game_active=True

self。game_active=False # 讓遊戲一開始處於非活動狀態

#self。high_score=0 #最高分

# 檔案操作讀取最高分

with open(‘data\data。txt’) as f:

self。high_score=int(f。read())

def reset_stats(self):

# 初始化

self。ships_left=self。ai_settings。ship_limit

self。score=0

self。level=1

scoreboard。py檔案,顯示遊戲的最高分、等級、得分、飛船數量等資訊

import pygame。font

from pygame。sprite import Group

from ship import Ship

class Scoreboard(): # 顯示得分資訊

def __init__(self,ai_settings,screen,stats):

self。screen=screen

self。screen_rect=screen。get_rect()

self。ai_settings=ai_settings

self。stats=stats

# 顯示得分資訊時使用的字型設定

self。text_color=(150,100,50)

self。font=pygame。font。SysFont(None,48)

# 準備初始化得分影象

self。prep_score() #當前得分影象

self。prep_high_score() # 最高得分影象

self。prep_level() # 顯示等級

self。prep_ships() # 顯示飛船數量

def prep_score(self): #將得分轉化為一幅渲染的影象

round_score=int(round(self。stats。score,-1))

score_str=‘{}{:,}’。format(‘Score:’,round_score)

self。score_image=self。font。render(score_str,True,self。text_color,

self。ai_settings。bg_color)

# 將得分放在螢幕右上角

self。score_rect=self。score_image。get_rect()

self。score_rect。right=self。screen_rect。right-20

self。score_rect。top=20

def prep_high_score(self):

high_score=int(round(self。stats。high_score,-1))

high_score_str=“{}{:,}”。format(‘High_score:’,high_score)

self。high_score_image=self。font。render(high_score_str,True,self。text_color,

self。ai_settings。bg_color)

# 將最高得分放在螢幕頂部中央

self。high_score_rect=self。high_score_image。get_rect()

self。high_score_rect。centerx=self。screen_rect。centerx

self。high_score_rect。top=self。score_rect。top

def show_score(self): #顯示得分

self。screen。blit(self。high_score_image, self。high_score_rect) # 顯示得分

self。screen。blit(self。score_image,self。score_rect) # 顯示最高分

self。screen。blit(self。level_image,self。level_rect) # 顯示等級

self。ships。draw(self。screen)

def prep_level(self):

# 將等級轉換為渲染的影象

level_str=“{}{:,}”。format(‘Level:’,self。stats。level)

self。level_image=self。font。render(level_str,True,self。text_color,

self。ai_settings。bg_color)

# 將等級放在得分下方

self。level_rect=self。level_image。get_rect()

self。level_rect。right=self。score_rect。right

self。level_rect。top=self。score_rect。bottom+10

def prep_ships(self): # 顯示飛船數量

self。ships=Group()

for ship_number in range(self。stats。ships_left):

ship=Ship(self。ai_settings,self。screen)

ship。rect。x=10+ship_number*ship。rect。width

ship。rect。y=10

self。ships。add(ship)

game_functions。py檔案,例項物件,實現遊戲的具體功能,例如:移動、復活、射擊等

import sys

import pygame

from bullet import Bullet

from alien import Alien

from time import sleep

def check_keydown_events(event,ai_settings,screen,ship,bullets): # 響應按鍵

if event。key==pygame。K_RIGHT:

ship。moving_right=True

elif event。key==pygame。K_LEFT:

ship。moving_left=True

elif event。key==pygame。K_SPACE:

fire_bullet(ai_settings,screen,ship,bullets)

elif event。key==pygame。K_q: # 按q結束遊戲

sys。exit()

def check_keyup_events(event,ship): # 響應鬆開

if event。key==pygame。K_RIGHT:

ship。moving_right=False

elif event。key==pygame。K_LEFT:

ship。moving_left=False

def check_events(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets):

‘’‘響應按鍵和滑鼠事件’‘’

for event in pygame。event。get():

if event。type==pygame。QUIT:

sys。exit()

elif event。type==pygame。KEYDOWN:

check_keydown_events(event,ai_settings,screen,ship,bullets)

elif event。type==pygame。KEYUP:

check_keyup_events(event,ship)

elif event。type==pygame。MOUSEBUTTONDOWN:

mouse_x,mouse_y=pygame。mouse。get_pos()

check_play_button(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets,mouse_x,mouse_y)

def updata_screen(ai_settings,screen,stats,sb,ship,aliens,bullets,play_button):

‘’‘更新螢幕上的影象,並切換到新螢幕’‘’

# 每次迴圈時都會重新繪製螢幕

screen。fill(ai_settings。bg_color)

# 在飛船和外星人後面重繪所有子彈

for bullet in bullets。sprites():

bullet。draw_bullet()

ship。blitme()

aliens。draw(screen) #顯示外星人

sb。show_score() #顯示得分

if not stats。game_active: #如果遊戲處於非活動狀態,就顯示play按鈕

play_button。draw_button()

pygame。display。flip() # 讓最近繪製的螢幕可見

def updata_bullets(ai_settings,screen,stats,sb,ship,aliens,bullets): #更新子彈位置並刪除消失的子彈

for bullet in bullets。sprites():

bullet。updata()

for bullet in bullets。copy(): # 刪除已經消失的子彈

if bullet。rect。bottom <= 0:

bullets。remove(bullet)

#print(len(bullets))

check_bullet_alien_collisions(ai_settings, screen, stats,sb,ship,aliens, bullets)

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)

def get_number_aliens_x(ai_settings,alien_width): #計算每行可以容納多少個外星人

available_space_x = ai_settings。screen_width - 2 * alien_width

number_aliens_x = int(available_space_x / (2 * alien_width))

return number_aliens_x

def get_number_rows(ai_aettings,ship_height,alien_height):

# 計算螢幕可容納多少行外星人

available_space_y=(ai_aettings。screen_height-(3*alien_height)-ship_height)

number_rows=int(available_space_y/(2*alien_height))

return number_rows

def creat_alien(ai_settings,screen,aliens,alien_number,row_number):

# 建立一個外星人行並將其放在當前行

alien = Alien(ai_settings, screen)

alien_width=alien。rect。width

alien。x=alien_width+2 *alien_width*alien_number

alien。rect。x=alien。x

alien。rect。y=alien。rect。height+2*alien。rect。height*row_number

aliens。add(alien)

def creat_fleet(ai_settings,screen,ship,aliens): # 建立外星人群

# 建立一個外星人,並計算一行可以容納多少個外星人

alien = Alien(ai_settings, screen)

number_aliens_x=get_number_aliens_x(ai_settings,alien。rect。width)

number_rows=get_number_rows(ai_settings,ship。rect。height,alien。rect。height)

for row_number in range(number_rows): # 建立外星人群

for alien_number in range(number_aliens_x):

creat_alien(ai_settings,screen,aliens,alien_number,row_number)

def check_fleet_edges(ai_settings,aliens):

# 有外星人到達邊緣時採取相應的措施

for alien in aliens。sprites():

if alien。check_edges():

change_fleet_direction(ai_settings,aliens)

break

def change_fleet_direction(ai_settings,aliens):

# 將外星人下移,並改變他們的方向

for alien in aliens。sprites():

alien。rect。y+=ai_settings。fleet_drop_speed

ai_settings。fleet_direction*=-1

def ship_hit(ai_settings, screen,stats,sb, ship, aliens, bullets):

# 響應被外星人撞到的飛船

if stats。ships_left>0:

stats。ships_left -= 1

sb。prep_ships() # 更新記分牌

# 清空外星人列表和子彈列表

aliens。empty()

bullets。empty()

# 建立一群新的外星人,並將飛船放到螢幕底端中央

creat_fleet(ai_settings, screen, ship, aliens)

ship。center_ship()

sleep(0。5) # 暫停0。5秒

else:

stats。game_active=False

pygame。mouse。set_visible(True) # 顯示游標

def check_aliens_bottom(ai_settings,screen,stats,sb,ship,aliens,bullets):

# 檢查是否有外星人到達了螢幕底端

screen_rect=screen。get_rect()

for alien in aliens。sprites():

if alien。rect。bottom>=screen_rect。bottom:

# 像飛船被撞到一樣進行處理

ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets)

break

def updata_aliens(ai_settings,screen,stats,sb,ship,aliens,bullets): # 檢查外星人是否在邊緣,更新所有外星人位置

check_fleet_edges(ai_settings,aliens)

for alien in aliens。sprites():

alien。updata()

# 檢測外星人和飛船之間的碰撞

if pygame。sprite。spritecollideany(ship,aliens):

# print(‘Ship hit!!!’)

ship_hit(ai_settings,screen,stats,sb,ship,aliens,bullets)

check_aliens_bottom(ai_settings,screen,stats,sb,ship,aliens,bullets)

def check_bullet_alien_collisions(ai_settings,screen,stats,sb,ship,aliens,bullets):

# 檢查是否有子彈擊中外星人,擊中就消失

collisions = pygame。sprite。groupcollide(bullets, aliens, True, True)

if collisions: #射中一個外星人就加分

for aliens in collisions。values():

stats。score+=ai_settings。alien_points*len(aliens) #一顆子彈射死多個的情況

sb。prep_score()

check_high_score(stats, sb) # 更新最高分

if len(aliens) == 0:

# 如果外星人被全部消滅,加快遊戲節奏,刪除現有子彈並新建一群外星人

bullets。empty()

ai_settings。increase_speed()

# 提高等級

stats。level+=1

sb。prep_level()

creat_fleet(ai_settings, screen, ship, aliens)

def check_play_button(ai_settings,screen,stats,sb,play_button,ship,aliens,bullets,mouse_x,mouse_y):

# 在玩家單擊play按鈕時開始遊戲

button_clicked=play_button。rect。collidepoint(mouse_x,mouse_y)

if button_clicked and not stats。game_active:

ai_settings。initialize_dynamic_settings() #重置遊戲設定

pygame。mouse。set_visible(False) # 隱藏游標

# 重置遊戲統計資訊

stats。reset_stats()

stats。game_active=True

# 重置記分牌影象

sb。prep_score()

sb。prep_high_score()

sb。prep_level()

sb。prep_ships()

# 清空外星人列表以及子彈

aliens。empty()

bullets。empty()

# 建立一群新的外星人,並讓飛船居中

creat_fleet(ai_settings,screen,ship,aliens)

ship。center_ship()

def check_high_score(stats,sb): #檢查是否誕生最高分

if stats。score>stats。high_score:

stats。high_score = stats。score

sb。prep_high_score()

with open(‘data\data。txt’,‘w’) as f:

data=str(stats。high_score)

f。write(data)

在所有程式碼編寫完畢之後就可以進行遊戲了

移動功能:鍵盤上的左右箭頭起到移動功能

射擊功能:鍵盤上的空格鍵起到射擊功能,為增加難度,遊戲框最多隻允許存在3顆子彈(子彈的多少可以自己調節)

用python寫小遊戲——外星人入侵(基於pygame)