Python隨身聽-源碼分析-經典小遊戲-flappy bird


又是週六了,讓我們一起讀點代碼放鬆一下吧!

今天要給大家看的代碼仍然是一段遊戲的代碼,上一週是貪吃蛇,這次換個口味:Flappy Bird。

遊戲動圖:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ViFi3Pg9-1577713472634)(http://www.grantjenks.com/docs/freegames/_static/flappy.gif)]

源碼

建議先仔細閱讀一下,然後再往後看 DE8UG 對源碼的分析。

from random import *
from turtle import *
from freegames import vector

bird = vector(0, 0)
balls = []
score = 0

def tap(x, y):
    "Move bird up in response to screen tap."
    up = vector(0, 30)
    bird.move(up) 

def inside(point):
    "Return True if point on screen."
    return -200 < point.x < 200 and -200 < point.y < 200

def draw(alive):
    "Draw screen objects."
    clear()
    goto(bird.x, bird.y)

    if alive:
        dot(10, 'green')
    else:
        dot(10, 'red')

    for ball in balls:
        goto(ball.x, ball.y)
        dot(20, 'black')

    update()

def move():
    "Update object positions."
    global score
    bird.y -= 5

    for ball in balls:
        ball.x -= 3

    if randrange(10) == 0:
        y = randrange(-199, 199)
        ball = vector(199, y)
        balls.append(ball)

    while len(balls) > 0 and not inside(balls[0]):
        balls.pop(0)
        score += 1
        print(f'get {score} scores')

    if not inside(bird):
        draw(False)
        return

    for ball in balls:
        if abs(ball - bird) < 15:
            draw(False)
            return

    draw(True)

    # 在鳥的位置,繪製分數
    goto(bird.x, bird.y)
    write(score, font=('Arial', 30, 'normal'))

    ontimer(move, 50)

setup(420, 420, 370, 0)
hideturtle()
up()
tracer(False)
onscreenclick(tap)
move()
done()

運行

複製上述代碼到一個 py 爲後綴的文件,命名 flappy.py.

在文件所在目錄打開控制檯:運行pip install freegames,然後運行python flappy.py

分析

查看一個py文件中的源碼,最開始可以對他們進行區域劃分。一般有這麼幾個區域:

  • 導入
  • 全局變量
  • 函數
  • 調用流程

我們可以先大致看幾個區域的變量和函數定義,然後從調用流程入手,一步步的分析代碼。

這個遊戲代碼是一個第三方庫 freegames 的一部分。從最上面導入依賴部分可以看出,主要是依賴於 turtle 這個庫。

from turtle import *的最後是個*,表示導入了 turtle 裏面所有東西,一般是不建議導入太多內容的,一是可能加載太多沒用的代碼,二是可能出現同名的類或函數。目前這只是個小遊戲,後面也用到不少 turtle 裏面的函數,所以這麼寫勉強可以接受。

往下看,整個代碼用到很多函數,只要是 import 沒有明確導入的,以及非本 python 文件寫的函數,其實都是這個*帶來的 turtle 內部函數了。如果你不知道神馬意思,記得我我課程裏介紹過超全的在線文檔嗎?https://devdocs.io,你只需要搜一下turtle就可以看到相關解釋了。

導入依賴部分還導入了 freegames 庫裏面一些工具類和函數:from freegames import vector,看單詞就可以知道是個向量,用來表示座標。

接下來是幾個函數:tap,inside,draw,move。

Flappy Bird, 是一個幾年前一位越南開發者做的遊戲,風靡一時,容易上癮,褒貶不一。DE8UG認爲這是一個不錯的遊戲,目前我們看到的這個python代碼,雖然沒有把小鳥和障礙物完全描述出來,但是從學習和娛樂角度來看,已經足夠了。

故事很簡單:一個小鳥,需要不斷拍動翅膀往前飛,同時躲避障礙物。

針對小鳥和障礙物的行爲,就不難理解這幾個函數了。

tap表示扇動翅膀,我們用點擊屏幕來模擬飛行。

inside判斷障礙物是否在屏幕內。

draw用來繪製小鳥和障礙物,這裏其實都是點,不同的是小鳥爲綠色表示正常,紅色表示失敗。障礙物都用黑色表示。這裏有個傳入的參數alive,用來根據小鳥的死活來繪製不同的顏色。同時,繪製障礙物時,注意用goto調整不同的位置,以繪製出不同位置的障礙物小球。

move函數的功能就比較多了,首先要有小鳥的自動降落,表示如果不扇動翅膀就會掉到地上死翹翹了。然後需要繪製黑色小球表示障礙物。這裏障礙物相對小鳥是往左移動的,所以x設置爲-3(函數最後有ontimer(move, 50)表示定時移動)。接下來是隨機模擬不同位置的障礙物,這裏主要是縱座標y在屏幕內的變化。接下來判斷如果障礙物已經不再屏幕內,就從列表裏面移除。我這裏添加了一個score變量,在順利躲避了障礙之後,用來累計分數。之後判斷bird的位置如果不在屏幕內,就給上面的draw函數添加參數False,然後return退出。一切正常的話,就循環判斷所有的障礙物,判斷小鳥和障礙物的位置是否小與一個閾值,這裏寫的15。當小於這個值,表示相撞,小鳥就死翹翹了。最後在鳥的位置,繪製分數,這會是一個動態刷新的過程。

接下來就是啓動遊戲,開始玩了 😊

ok,這就是本週六的源碼分析了,祝你閱讀愉快。

目前在 Python 隨身聽的微信欄目裏,已經從週一到週日安排了:技術精選,基礎學習,Python 練習,項目連載,難點問答,源碼分析,DE8UG 雜談這些欄目,歡迎圍觀。

有任何想法建議疑問歡迎留言,明天見~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章