pygame開發滑雪者游戲


pygame開發滑雪者游戲

一、實驗說明

下述介紹為實驗樓默認環境,如果您使用的是定制環境,請修改成您自己的環境介紹。

1. 環境登錄

無需密碼自動登錄,系統用戶名 shiyanlou,該用戶具備 sudo 的權限,可以執行安裝軟件等管理員操作。

2. 環境介紹

本實驗環境采用帶桌面的Ubuntu Linux環境,實驗中會用到桌面上的程序:

  1. LX終端(LXTerminal): Linux命令行終端,打開后會進入Bash環境,可以使用Linux命令
  2. Firefox:瀏覽器,可以用在需要前端界面的課程里,只需要打開環境里寫的HTML/JS頁面即可
  3. GVim:非常好用的編輯器,最簡單的用法可以參考課程Vim編輯器

3. 環境使用

使用編輯器輸入實驗所需的代碼及文件,使用命令行終端運行所需命令進行操作。

“實驗記錄”頁面可以在“我的主頁”中查看,每次實驗的截圖及筆記,以及有效學習時間(指的是在實驗桌面內操作的時間,如果沒有操作,系統會記錄為發呆時間)。這些都是您在實驗樓學習的真實性證明。

本課程中的所有源碼可以在 Xfce 終端中執行下列命令獲取:

wget http://labfile.oss.aliyuncs.com/courses/826/skierGames.py

二、課程介紹

1. 知識點:

本實驗中將介紹在 Linux 桌面環境下使用 Python 及 pygame 快速開發小游戲的方式。

2. 參考文檔:

http://www.pygame.org/docs/

3. 安裝依賴包

$ sudo apt-get update
$ sudo apt-get install python-pygame

4. 依賴文件

因為我們的游戲包含一些圖片和背景音樂,所以請下載背景音樂和圖片:

wget http://labfile.oss.aliyuncs.com/courses/826/bg_music.tar.gz
wget http://labfile.oss.aliyuncs.com/courses/826/bg_img.tar.gz

然后對其進行解壓

tar zcvf bg_music.tar.gz
tar bg_img.tar.gz

運行方式:將源代碼文件和圖像聲音文件放到一起然后在終端中運行

python skierGames.py

5. 游戲介紹:

主人公就是滑雪者,在滑雪的時候可能會撞上樹,當撞上樹的時候會扣分,地圖中也有小旗子當撞上小旗子的時候會加分 ---很傳統的游戲。

6. 注意事項:

因為實驗樓不提供音頻播放功能,所以在源代碼中將音頻部分注釋了,當您在本機運行的時候可以將代碼中的注釋去掉,從而播放音頻。此處輸入圖片的描述
此處輸入圖片的描述

三、技術設計

重要的事情說三遍:

當您在學習Pygame模塊的時候有不懂的要參考 Pygame的文檔

http://www.pygame.org/docs/

×3

1. 角色設計

class SkierClass(pygame.sprite.Sprite):  # 創建滑雪者

    def __init__(self):
        pygame.sprite.Sprite.__init__(self) # 基類的init方法
        self.image = pygame.image.load("./bg_img/skier_down.png") # 這個是滑雪者的美照。
        self.rect = self.image.get_rect() # 用於獲得Image的矩形大小
        self.rect.center = [320, 100]  # 指定矩形的中心位置
        self.angle = 0

    def turn(self, direction):				# 滑雪者 轉向函數 其中的direction參數是指定滑雪者移動的方向和程度(點擊兩次右鍵比一次右鍵滑動的幅度要大,一會自己試着運行一下試試)
        self.angle = self.angle + direction		#滑雪者當前的移動速度
        if self.angle < -2:  self.angle = -2   # 用於將滑雪者的移動方式固定到這五個方式當中
        if self.angle >  2:  self.angle =  2
        center = self.rect.center
        self.image = pygame.image.load(skier_images[self.angle])	#這個時候滑雪者應該有的姿態圖片。
        self.rect = self.image.get_rect()
        self.rect.center = center
        speed = [self.angle, 6 - abs(self.angle) * 2]	#滑雪者的速度。
        return speed

    def move(self, speed): 			#滑雪者左右移動
    
        self.rect.centerx = self.rect.centerx + speed[0]	#滑雪者所在位置
        if self.rect.centerx < 20:  self.rect.centerx = 20	# 滑雪者所在位置不應該超過的最大最小值。
        if self.rect.centerx > 620: self.rect.centerx = 620

該類創建出來滑雪者的形象和其行為(左右滑動和跌倒時候的形態),計算滑雪者不同的運動速度,和左右移動時候的界限(不應該超過界面的范圍)。

2. 創建樹和小旗子

class ObstacleClass(pygame.sprite.Sprite):	#創建書和小旗
    def __init__(self, image_file, location, type):
        pygame.sprite.Sprite.__init__(self)
        self.image_file = image_file	#image_file可能是樹或者小旗
        self.image = pygame.image.load(image_file)	#載入當前的圖片
        self.location = location
        self.rect = self.image.get_rect()
        self.rect.center = location
        self.type = type
        self.passed = False

    def scroll(self, terrainPos):	#場景上滾,造成下滑假象。
        self.rect.centery = self.location[1] - terrainPos

該類創建出來 樹或者小旗子並且造成場景運動的鏡像。

3. 樹和小旗的隨機位置

def create_map(start, end): 	# 創建一個窗口,包含隨機的樹和小旗
    obstacles = pygame.sprite.Group() # 創建獨立運動的組織
    locations = []
    gates = pygame.sprite.Group()
    for i in range(10):
        row = random.randint(start, end) #獲得隨機數在 start-end之間
        col = random.randint(0, 9)
        location  = [col * 64 + 20, row * 64 + 20] # 確定所在位置
        if not (location in locations): # 如果上面定義的物體不在已經確定屬性(位置等參數)的物體里面。
            locations.append(location)
            type = random.choice(["tree", "flag"])#隨機選擇是樹還是小旗
            if type == "tree": img = "./bg_img/skier_tree.png"	#選擇相應的圖片
            elif type == "flag":  img = "./bg_img/skier_flag.png"
            obstacle = ObstacleClass(img, location, type)		#將上面的形成的物體添加到游戲
            obstacles.add(obstacle)		
    return obstacles

用於創建窗口,並且隨機生成樹和小旗子在隨機位置。並且將相應圖片放到隨機的位置。

4. 繪制屏幕背景並進行圖像的更新

代碼很簡單,見下方:

def animate(): 	# 如果發生移動就重新繪制屏幕
    screen.fill([255, 255, 255])	#指定背景顏色 (RGB)
    pygame.display.update(obstacles.draw(screen))#這個函數就pygame.display.flip的優化版本。它只允許屏幕的一部分更新,而不是整個區域。如果沒有參數傳遞它更新整個表面積就像pygame.display.flip()一樣。
    screen.blit(skier.image, skier.rect)# 用於繪制位圖 在屏幕的skier.rect位置繪制skier.image
    screen.blit(score_text, [10, 10])
    pygame.display.flip()

四、程序邏輯:

首先我們應該初始化Pygame模塊和聲音播放模塊(因為實驗樓不提供音頻支持,所以將音頻部分代碼注釋掉了,在本機運行的時候請去掉注釋。)。
然后我們初始化游戲窗口,載入時間監聽模塊。隨機生成樹和小旗子
然后開始運行游戲進行無限循環,設置游戲的更新幀率,使用鍵盤監控左右按鍵,設置滑雪者的運動軌跡。隨機生成樹和小旗子然后檢測 是否撞到樹和小旗子然后進行相應的操作

pygame.init()        #初始化pygame的所有模塊
#pygame.mixer.init()  # 初始化混音部分 進行聲音的加載和播放---播放音頻之用
#pygame.mixer.music.load("./bg_music/bg_music.mp3")  # 將會加載這一個音樂的文件名並且准備播放!
#pygame.mixer.music.set_volume(0.3)#設置音樂 的音量參數之在 0-1之間
#pygame.mixer.music.play(-1) #這將播放載入的音樂流。如果音樂已經播放,它就會重新啟動。其中的參數時控制音樂播放的次數。如果是-1的話就是無限重復播放。
screen = pygame.display.set_mode([640,640])# 用於初始化窗口,其中的參數就是分辨率
clock = pygame.time.Clock()# 載入監聽時間的模塊 clock在下面還可以看到 clock.tick等方法
skier = SkierClass() # 初始化SkierClass對象
speed = [0, 6]
map_position = 0
points = 0
map0 = create_map(20, 29)
map1 = create_map(10, 19)
activeMap = 0

obstacles = updateObstacleGroup(map0, map1)

font = pygame.font.Font(None, 50)

while True:
    clock.tick(30)		# 每秒更新30次圖形 ---這就是幀率。
    for event in pygame.event.get():    # 檢查按鍵或者窗口是否關閉
        if event.type == pygame.QUIT: sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed = skier.turn(-1)
            elif event.key == pygame.K_RIGHT:
                speed = skier.turn(1)
    skier.move(speed)			# 移動滑雪者
    map_position += speed[1]		# 滾動場景

    if map_position >=640 and activeMap == 0: 		# 從場景的一個窗口切換到下一個窗口
        activeMap = 1
        map0 = create_map(20, 29)
        obstacles = updateObstacleGroup(map0, map1)
    if map_position >=1280 and activeMap == 1:
        activeMap = 0
        for ob in map0:
            ob.location[1] = ob.location[1] - 1280
        map_position = map_position - 1280
        map1 = create_map(10, 19)
        obstacles = updateObstacleGroup(map0, map1)

    for obstacle in obstacles:
        obstacle.scroll(map_position)

    hit =  pygame.sprite.spritecollide(skier, obstacles, False)		# 檢查是否碰到樹或者小旗。
    if hit:
        if hit[0].type == "tree" and not hit[0].passed:# 如果撞到的是樹的話
            points = points - 100
            skier.image = pygame.image.load("./bg_img/skier_crash.png")
            animate()
            pygame.time.delay(1000) # 游戲暫停 1秒。
            skier.image = pygame.image.load("./bg_img/skier_down.png")
            skier.angle = 0
            speed = [0, 6]
            hit[0].passed = True
        elif hit[0].type == "flag" and not hit[0].passed:
            points += 10
            obstacles.remove(hit[0])
	#顯示得分
    score_text = font.render("Score: " +str(points), 1, (0, 0, 0))
    animate()

五、完整代碼參考

import pygame, sys, random

skier_images = ["./bg_img/skier_down.png", "./bg_img/skier_right1.png", "./bg_img/skier_right2.png",
                 "./bg_img/skier_left2.png", "./bg_img/skier_left1.png"]     # 將可能用到的圖片列表化

class SkierClass(pygame.sprite.Sprite):  # 創建滑雪者
    def __init__(self):
        pygame.sprite.Sprite.__init__(self) # 基類的init方法
        self.image = pygame.image.load("./bg_img/skier_down.png") # 這個是滑雪者的美照。
        self.rect = self.image.get_rect() # 用於獲得Image的矩形大小
        self.rect.center = [320, 100]  # 指定矩形的中心位置
        self.angle = 0

    def turn(self, direction):				# 滑雪者 轉向函數 其中的direction參數是指定滑雪者移動的方向和程度(點擊兩次右鍵比一次右鍵滑動的幅度要大,一會自己試着運行一下試試。)
        self.angle = self.angle + direction		#滑雪者當前的移動速度
        if self.angle < -2:  self.angle = -2   # 用於將滑雪者的移動方式固定到這五個方式當中
        if self.angle >  2:  self.angle =  2
        center = self.rect.center
        self.image = pygame.image.load(skier_images[self.angle])	#這個時候滑雪者應該有的姿態圖片。
        self.rect = self.image.get_rect()
        self.rect.center = center
        speed = [self.angle, 6 - abs(self.angle) * 2]	#滑雪者的速度。
        return speed

    def move(self, speed): 			#滑雪者左右移動
        self.rect.centerx = self.rect.centerx + speed[0]	#滑雪者所在位置
        if self.rect.centerx < 20:  self.rect.centerx = 20	# 滑雪者所在位置不應該超過的最大最小值。
        if self.rect.centerx > 620: self.rect.centerx = 620

class ObstacleClass(pygame.sprite.Sprite):	#創建書和小旗
    def __init__(self, image_file, location, type):
        pygame.sprite.Sprite.__init__(self)
        self.image_file = image_file	#image_file可能是樹或者小旗
        self.image = pygame.image.load(image_file)	#載入當前的圖片
        self.location = location
        self.rect = self.image.get_rect()
        self.rect.center = location
        self.type = type
        self.passed = False

    def scroll(self, terrainPos):	#場景上滾,造成下滑假象。
        self.rect.centery = self.location[1] - terrainPos

def create_map(start, end): 	# 創建一個窗口,包含隨機的樹和小旗
    obstacles = pygame.sprite.Group() # 創建獨立運動的組織
    locations = []
    gates = pygame.sprite.Group()
    for i in range(10):
        row = random.randint(start, end) #獲得隨機數在 start-end之間
        col = random.randint(0, 9)
        location  = [col * 64 + 20, row * 64 + 20] # 確定所在位置
        if not (location in locations): # 如果上面定義的物體不在已經確定屬性(位置等參數)的物體里面。
            locations.append(location)
            type = random.choice(["tree", "flag"])#隨機選擇是樹還是小旗
            if type == "tree": img = "./bg_img/skier_tree.png"	#選擇相應的圖片
            elif type == "flag":  img = "./bg_img/skier_flag.png"
            obstacle = ObstacleClass(img, location, type)		#將上面的形成的物體添加到游戲
            obstacles.add(obstacle)		
    return obstacles

def animate(): 	# 如果發生移動就重新繪制屏幕
    screen.fill([255, 255, 255])	#指定背景顏色 (RGB)
    pygame.display.update(obstacles.draw(screen))#這個函數就pygame.display.flip的優化版本。它只允許屏幕的一部分更新,而不是整個區域。如果沒有參數傳遞它更新整個表面積就像pygame.display.flip()一樣。
    screen.blit(skier.image, skier.rect)# 用於繪制位圖 在屏幕的skier.rect位置繪制skier.image
    screen.blit(score_text, [10, 10])
    pygame.display.flip()

def updateObstacleGroup(map0, map1):  # 切換到場景的下一屏
    obstacles = pygame.sprite.Group()
    for ob in map0:  obstacles.add(ob)
    for ob in map1:  obstacles.add(ob)
    return obstacles

pygame.init()        #初始化pygame的所有模塊
#pygame.mixer.init()  # 初始化混音部分 進行聲音的加載和播放---播放音頻之用
#pygame.mixer.music.load("./bg_music/bg_music.mp3")  # 將會加載這一個音樂的文件名並且准備播放!
#pygame.mixer.music.set_volume(0.3)#設置音樂 的音量參數之在 0-1之間
#pygame.mixer.music.play(-1) #這將播放載入的音樂流。如果音樂已經播放,它就會重新啟動。其中的參數時控制音樂播放的次數。如果是-1的話就是無限重復播放。
screen = pygame.display.set_mode([640,640])# 用於初始化窗口,其中的參數就是分辨率
clock = pygame.time.Clock()# 載入監聽時間的模塊 clock在下面還可以看到 clock.tick等方法
skier = SkierClass() # 初始化SkierClass對象
speed = [0, 6]
map_position = 0
points = 0
map0 = create_map(20, 29)
map1 = create_map(10, 19)
activeMap = 0

obstacles = updateObstacleGroup(map0, map1)

font = pygame.font.Font(None, 50)

while True:
    clock.tick(30)		# 每秒更新30次圖形 ---這就是幀率。
    for event in pygame.event.get():    # 檢查按鍵或者窗口是否關閉
        if event.type == pygame.QUIT: sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                speed = skier.turn(-1)
            elif event.key == pygame.K_RIGHT:
                speed = skier.turn(1)
    skier.move(speed)			# 移動滑雪者
    map_position += speed[1]		# 滾動場景

    if map_position >=640 and activeMap == 0: 		# 從場景的一個窗口切換到下一個窗口
        activeMap = 1
        map0 = create_map(20, 29)
        obstacles = updateObstacleGroup(map0, map1)
    if map_position >=1280 and activeMap == 1:
        activeMap = 0
        for ob in map0:
            ob.location[1] = ob.location[1] - 1280
        map_position = map_position - 1280
        map1 = create_map(10, 19)
        obstacles = updateObstacleGroup(map0, map1)

    for obstacle in obstacles:
        obstacle.scroll(map_position)

    hit =  pygame.sprite.spritecollide(skier, obstacles, False)		# 檢查是否碰到樹或者小旗。
    if hit:
        if hit[0].type == "tree" and not hit[0].passed:
            points = points - 100
            skier.image = pygame.image.load("./bg_img/skier_crash.png")
            animate()
            pygame.time.delay(1000)
            skier.image = pygame.image.load("./bg_img/skier_down.png")
            skier.angle = 0
            speed = [0, 6]
            hit[0].passed = True
        elif hit[0].type == "flag" and not hit[0].passed:
            points += 10
            obstacles.remove(hit[0])
	#顯示得分
    score_text = font.render("Score: " +str(points), 1, (0, 0, 0))
    animate()

完整代碼可以從這里獲得:

wget http://labfile.oss.aliyuncs.com/courses/826/skierGames.py


免責聲明!

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



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