其實前段時間就寫完這個了,但是沒有什麼時間寫博客,因爲現在正好在複習python的一些東西,可以寫一下博客來複習梳理一下整個遊戲的流程。
1.效果展示
2.實現主窗體
先從最主要的開始入手,做一個遊戲的窗體,因爲導入了pygame,感覺在python中做一個小遊戲比Java中更加容易做。可以直接設置FPS什麼的,很方便。
下面是窗體部分實現代碼
import pygame
from pygame.locals import * # 導入pygame中的常量
SCREENWIDTH = 822
SCREENHEIGHT = 260
FPS = 30 # 更新畫面的時間
def mainGame():
global SCREEN, FPSCLOCK
pygame.init() # 使用pygame前先初始化
# 要使用pygame時鐘,先創建clock對象的實例
# 用於控制每個循環多長時間運行一次
FPSCLOCK = pygame.time.Clock()
# 先創建一個窗體
SCREEN = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
pygame.display.set_caption('恐龍快跑')
while True:
# 判斷是否單擊關閉了窗體
for event in pygame.event.get():
# 單擊關閉窗體就關閉窗體
if event.type == QUIT:
exit() # 關閉窗體
pygame.display.update() # 更新整個窗體
FPSCLOCK.tick(FPS) # 循環多久運行一次
if __name__ == '__main__':
mainGame()
我們可以看下運行效果
3.遊戲背景的滾動
恐龍快跑的遊戲背景滾動其實是恐龍沒有動,背景一直在動,這一點和飛機大戰是一樣的,所以實現原理也是一樣,總共有兩張圖片,第一張圖片放完後就放第二張,第二張圖片放完後繼續放第一張。這個和我以前寫的飛機大戰的繪製背景是一樣的,在飛機大戰裏面有畫圖解釋,鏈接如下:
飛機大戰博客鏈接
先創建一個地圖類
class Map():
def __init__(self, x, y):
# 背景圖片加載
self.bg = pygame.image.load("images/bg.png").convert_alpha()
self.x = x
self.y = y
def map_move(self):
if self.x < -790: # 已經移動完畢
self.x = 800 # 再次開始
else:
self.x -= 5 # 一次左移動5個像素點
def map_update(self):
SCREEN.blit(self.bg, (self.x, self.y))
當遊戲開始後,因爲地圖要移動,所以先在mainGame()定義兩張背景圖片的初始位置,然後在mainGame()的while True循環裏面加入地圖的更新
代碼如下:
# 創建地圖對象
bg1 = Map(0, 0)
bg2 = Map(800, 0)
if over == False:
bg1.map_update()
bg1.map_move()
bg2.map_update()
bg2.map_move()
實現效果如下:
3.加入恐龍圖片和加入鍵盤監聽實現恐龍跳躍動作
在實現完背景圖片的移動之後,我們應該考慮把恐龍的圖片加進來了,並且加上鍵盤監聽器,比如當按下空格鍵時實現恐龍的跳躍動作。
我們首先設置一個恐龍類,代碼如下:
class Dragon():
def __init__(self):
self.rect = pygame.Rect(0, 0, 0, 0) # 小恐龍矩形圖片的初始化,Rect(left,top,width,height)
self.jumpHeight = 130
self.jumpState = False # 跳躍狀態,true爲跳躍
self.lowest_y = 140 # 最低座標
self.jumpValue = 0 # 跳躍增變量
# 小恐龍跳躍動作播放圖片,連續放三張圖片,造成一種gif的感覺
self.DragonIndex = 0
self.DragonIndexGen = cycle([0, 1, 2]) # 引入的迭代工具
# 加載恐龍圖片,使用convert_alpha()背景圖片才爲透明,用convert則爲黑色背景
self.dragon_img = (
pygame.image.load("images/dargon1.png").convert_alpha(),
pygame.image.load("images/dargon2.png").convert_alpha(),
pygame.image.load("images/dargon3.png").convert_alpha(),
)
self.rect.size = self.dragon_img[0].get_size()
self.x = 50 # 繪製恐龍x座標
self.y = self.lowest_y # 繪製恐龍y座標
self.rect.topleft = (self.x, self.y)
def jump(self):
self.jumpState = True
print("jump方法正在執行")
def move(self):
if self.jumpState== True: # 起跳的時候
if self.rect.y >= self.lowest_y:
self.jumpValue = -5 # 向上移動五個像素點
if self.rect.y <= self.lowest_y - self.jumpHeight: # 到頂後下降
self.jumpValue = 5
self.rect.y += self.jumpValue
if self.rect.y >= self.lowest_y: # 恐龍落地以後,跳躍狀態改爲False
self.jumpState = False
def draw(self):
# 匹配恐龍動圖
DragonIndex = next(self.DragonIndexGen)
# 繪製小恐龍,blit()第一個爲圖片,第二個參數爲位置
SCREEN.blit(self.dragon_img[DragonIndex], (self.x, self.rect.y))
因爲恐龍一直在原地,所以並沒有x軸上的移動,跳躍也只是在y軸上移動一下。只有背景圖片一直在動
效果如下:
4.障礙物的實現
遊戲的規則是恐龍越過障礙物就加一分,如果碰到障礙物則死亡,可以選擇重開遊戲,所以我們接下來要做的是障礙物的隨機出現。
和恐龍一樣,我們先建一個Obstacle障礙物類,然後實現Obstacle的move,draw方法。
代碼如下:
class Obstacle():
def __init__(self):
# 初始化障礙物矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加載障礙物圖片
self.stone = pygame.image.load("images/stone.png").convert_alpha()
self.cacti = pygame.image.load("images/cacti.png").convert_alpha()
# 生成0到1的隨機數
r = random.randint(0, 1)
if r == 0: # 隨機數爲0則爲石頭,1爲仙人掌
self.image = self.stone
else:
self.image = self.cacti
# 根據障礙物位圖的寬和高來顯示仙人掌
self.rect.size = self.image.get_size()
# 獲取圖片寬高
self.width, self.height = self.rect.size
# 繪製障礙物的座標
self.x = 800
self.y = 200 - (self.height / 2)
# self.y = 200
self.rect.center = (self.x, self.y)
def move(self):
self.rect.x -= 5
def draw(self):
SCREEN.blit(self.image, (self.rect.x, self.rect.y))
然後我們在mainGame()的whileTrue裏面加入障礙物出現的時間和概率的判斷,並在whileTrue裏面調用Obstacle的move和draw方法
if addObstacleTimer >= 1000:
r = random.randint(0, 100)
if r > 40:
# 創建障礙物對象
obstacle = Obstacle()
# 添加到列表
list.append(obstacle)
# 重置時間,到下一次出現障礙物
addObstacleTimer = 0
# 循環遍歷障礙物
for i in range(len(list)):
# 障礙物移動與繪製
list[i].move()
list[i].draw()
addObstacleTimer += 20
實現效果如下:
5.碰撞判斷
在上面的效果展示我們可以發現,恐龍碰到障礙物以後並沒有發生預料中的遊戲結束,因爲我們還沒有加入對碰撞的判斷,所以我們現在可以加入對碰撞的判斷過程。
我們可以直接在whileTrue裏面加入對碰撞的判斷
# 判斷與障礙物是否碰撞
if pygame.sprite.collide_rect(dragon, list[i]):
over = True
game_over()
可以發現如果碰撞發生,則遊戲結束,但是我們這裏調用的game_over()方法還沒有開始寫,所以還需要寫一個game_over()方法。
def game_over():
# 獲取窗體寬度和高
screen_w = pygame.display.Info().current_w
screen_h = pygame.display.Info().current_h
# 加載遊戲結束的圖片
over_img = pygame.image.load("images/gameover.png").convert_alpha()
# 遊戲結束的圖片控制在窗體的中間位置
SCREEN.blit(over_img, ((screen_w - over_img.get_width()) / 2,
(screen_h - over_img.get_height()) / 2))
這下就大功告成了,大家可以看下效果圖
6.分數的顯示
遊戲做到這裏基本已經結束了,但是我們可以再增加一個分數顯示的功能,當恐龍躍過一個障礙時就加一分。所以我們先實現一個獲取分數getScore()和顯示分數showScore()的方法
def getScore(self):
tmp = self.score
self.score = 0
return tmp
def showScore(self, score):
# 在窗體頂部中間的位置顯示分數
self.scoreDigits = [int(x) for x in list(str(score))]
totalWidth = 0 # 要顯示所有數字的總寬度
for digit in self.scoreDigits:
# 獲取積分圖片的寬度
totalWidth += self.numbers[digit].get_width()
# 分數橫向位置
Xoffset = (SCREENWIDTH - totalWidth) / 2
for digit in self.scoreDigits:
# 繪製分數
SCREEN.blit(self.numbers[digit], (Xoffset, SCREENHEIGHT * 0.1))
# 數字增加也改變位置
Xoffset += self.numbers[digit].get_width()
並且需要在是否碰撞的判斷加上一個else,如果沒有碰到的話,則加分
# 判斷與障礙物是否碰撞
if pygame.sprite.collide_rect(dragon, list[i]):
over = True
game_over()
else:
if(list[i].rect.x + list[i].rect.width) < dragon.rect.x:
score += list[i].getScore()
# 顯示分數
list[i].showScore(score)
遊戲到這裏就整體就完成啦,下面是效果圖
有需要整份代碼的可以留郵箱。