PONG - 100行程式碼寫一個彈球遊戲

Crossin先生發表於2022-03-28

大家好,歡迎來到 Crossin的程式設計教室 !

今天跟大家講一講:如何做遊戲

https://www.bilibili.com/vide...

遊戲的主題是彈球遊戲《PONG》,它是史上第一款街機遊戲。因此選它作為我這個遊戲開發系列的第一期主題。

遊戲引擎用的是 Python 的一個遊戲庫:pgzero。它是對 pygame 的一個封裝,讓你不需要寫多餘的套路程式碼,只要配置遊戲的內容邏輯即可。

我們這個遊戲用它來寫,一共只需要100行程式碼。

首先需要安裝 python 環境。這一步沒搞定的同學,可以參考我們 python 入門教程:http://python666.cn,上面有詳細圖文介紹。

然後需要安裝 pgzero 庫,可以命令列下通過 pip 命令安裝:

pip install pgzero

安裝完,執行一句

pgzrun.go()

我們的遊戲世界之門就已經開啟了。

現在上面還是混沌初開,一片漆黑。

image.png

設定一個矩形的左上角座標和長寬,在遊戲的繪製函式 draw 中用指定顏色填充,我們就得到了一個矩形。

pad_1 = Rect((20, 20), (10, 100))

def draw():
    screen.clear()
    screen.draw.filled_rect(pad_1, 'white')

適當調整一下,就得到了一塊遊戲中用來擋球的板。

image.png

在遊戲的更新函式中增加判斷,當鍵盤上的“上”、“下”按鍵被按下時,修改擋板的y座標,就可以在遊戲中控制擋板的移動了。

PAD_SPEED = 10

def update(dt):
    if keyboard.up:
        pad_1.y -= PAD_SPEED
    elif keyboard.down:
        pad_1.y += PAD_SPEED

這樣就已經完成 PONG 遊戲中的玩家操控角色:一塊可上下移動的擋板。而現在我們用到的程式碼僅僅10行。

有的小夥伴可能注意到了,這裡有兩個函式,一個叫 draw,它是負責遊戲中的畫面繪製,另一個叫 update,它負責遊戲中的邏輯更新。

我們經常聽到說遊戲執行時速度是每秒30幀、60幀之類,或者叫做 FPS(Frames Per Second)。draw 和 update 就是在遊戲的“一幀”畫面中所要做的事情。你的計算機或者遊戲主機的效能越高,每一幀所花費的計算時間就越少,遊戲幀數就可以更高,遊戲體驗也就更流暢。

建立一個叫做 Ball 的型別,屬性值包括位置和速度。然後,在繪圖函式中以小球的位置為圓心畫一個圓,在更新函式中按照勻速直線運動位移公式,也就是 位移=速度x時間,計算出小球下一幀的位置。如此就實現了一個會運動的小球。

class Ball():
    def __init__(self):
        self.pos = [300, 200]
        self.speed = [1, 1]        
    def update(self, dt):
        for i in range(2):
            self.pos[i] += self.speed[i] * dt

ball = Ball()

def draw():
    screen.clear()
    screen.draw.filled_rect(pad_1, 'white')
    screen.draw.filled_circle(ball.pos, BALL_RADIUS, 'white')

再設定一下邊界條件,讓小球到達螢幕邊緣時可以改變對應的速度方向,碰到上下邊緣就將y速度分量乘以-1,超出左右邊緣則位置重新設定回螢幕中心。

class Ball():
    ...      

    def update(self, dt):
        for i in range(2):
            self.pos[i] += self.speed[i]

        if self.pos[1] < 0 or self.pos[1] > HEIGHT:
            self.speed[1] *= -1
        if self.pos[0] < 0 or self.pos[0] > WIDTH:
            self.reset()

有了板,有了球,接下來就是讓他們之間產生關聯。

在更新函式中做一個碰撞檢測:如果板子的矩形與球的圓心產生了交集,就讓球反彈回去。

def update(dt):
    ...
    
    ball.update(dt)

    if pad_1.collidepoint(ball.pos) and ball.speed[0] < 0:
        ball.speed[0] *= -1

到這一步,遊戲的核心物理規則就已經定義完畢。

按照同樣的方法,在螢幕的右側建立第二塊板,通過另外的按鍵進行控制。然後,當小球超出左右邊界時,分別給對面一方得分。

class Ball():
    ...      

    def dead(self, side):
        scores[side] += 1
        self.reset()

這樣,一個最最簡單的,雙人版彈球遊戲就完成了。

當然,如果你找不到另一個人陪你一起玩,也可以讓自己的左手跟右手玩。

或者,給一側板增加一點自動追蹤的程式碼:讓板的位置隨著球的位置移動。這也算是一個遊戲AI了。

def auto_move_pad(dt):
    if ball.pos[0] > WIDTH / 2 and ball.speed[0] > 0:
        if pad_2.y + pad_2.height * 0.25 > ball.pos[1]:
            pad_2.y -= PAD_SPEED * dt
            if pad_2.top < 0:
                pad_2.top = 0
        elif pad_2.y + pad_2.height * 0.75 < ball.pos[1]:
            pad_2.y += PAD_SPEED * dt
            if pad_2.bottom > HEIGHT:
                pad_2.bottom = HEIGHT

至此,一個具備完整核心玩法的彈球遊戲 PONG 已經完成了。加上空格也不到100行程式碼。特別適合程式設計新手剛剛接觸遊戲開發的小夥伴進行練習。

不過,我還給遊戲增加了一點點細節,感興趣的小夥伴可點選文章開頭的視訊進行觀看。喜歡的話歡迎點贊和轉發!

之後我還會來嘗試更多的遊戲型別,更多的玩法。爭取完成最初立下的FLAG:實現100個遊戲。如果你想看某類遊戲或者某個遊戲的實現,或者對某個實現細節有疑問,也可以留言中告訴我,我會優先考慮。

程式碼已經開源,可通過“Crossin的程式設計教室”獲取

https://github.com/crossin/ga...


獲取更多教程和案例,

歡迎搜尋及關注:Crossin的程式設計教室

每天5分鐘,輕鬆學程式設計。

相關文章