45歲碼農用不到2年時間擼出100款撲克遊戲

崔鵬發表於2020-08-25
前言

撲克的玩法非常多,常見的就有鬥地主、跑得快、五十K、鋤大地、梭哈、十點半、二十一點、打千分、升級、拖拉機、雙扣、保皇、鬥牛、挖坑等等。在國內的不同地方,同類遊戲的玩法也有不同講究。粗略估計,國內的撲克玩法,超過上百種。

要短期內開發出這麼多款撲克遊戲,需要先對大多數撲克遊戲進行系統的分析,歸納總結,然後打造一條流水線,每一款遊戲都使用相同的框架,使用通用的零元件,等等。

本文主要內容就是講述這個設計過程。

1、演算法庫

撲克遊戲的歷史很悠久,能夠廣為流行的一個原因就是上手比較容易。就算在今天,如果說一個人沒讀過書就學不會打撲克,這沒人會相信。所以我估計撲克遊戲的演算法,都是比較簡單的。歸納一下,一般包括:

  • 牌的大小(包括數字、花色等);牌的數目和分數;判斷幾張牌相同或連續;
  • 還需要一些對一組牌進行操作的演算法,比如取出、合併等等。

基於以上的分析,我們估計可以完成一套通用的撲克的演算法庫,能滿足所有撲克遊戲。最後實踐證明,撲克演算法庫比預期稍微複雜一點,但仍在可接受範圍內。

此外,我們很容易發現,很多流行的手遊的玩法、功能層出不窮,開發團隊頻繁升級迭代。相反,撲克遊戲的玩法相對固定,演化相對較慢。所以,在系統設計上,我們假定撲克遊戲的數量有限,玩法有限,發展慢。這樣的好處是流水線設計好之後,以後改動很小,維護工作量也比較小。

2、互動UI庫

撲克遊戲可以歸納出3個核心要素:牌、規則、人(玩家)。對撲克遊戲的一種高度抽象的描述是:按照一定的流程和規則,每個人通過選擇選項、選擇牌、選擇數值,來爭取獲勝的一種遊戲。

歸納了一下,玩家的行為包括以下3種:

  • 對遊戲流程中的選項,做出選擇
  • 按照遊戲規則,對牌進行選擇。
  • 對數值(分數)進行選擇。

比如鬥地主中的叫地主、不搶,都是玩家自己要做的一種選擇。出牌的時候選擇不出,也是一種選擇。後續會將“選項”稱之為“命令”。

比如選擇要出的牌,分組擺牌等。

比如下注。

以上三種玩家的行為,決定了遊戲客戶端需要提供哪些業務級UI庫,對應下面幾種:

  • 一組按鈕
  • 選牌或牌分組的UI
  • 選擇數值的UI

由玩家選擇其中一個按鈕;在業務層,稱為命令選擇器。

允許玩家在一組牌中選出符合要求的牌。牌分組UI則允許玩家將牌放入不同分組或按不同順序排布。這2種在業務層都稱為牌選擇器。

可以用滑動條,也有用按鈕的。在業務層稱為值選擇器。

以上我們抽象出了撲克遊戲的3個核心要素,以及玩家使用的3類UI。現在我們思考一下撲克遊戲還需要哪些UI。

除了牌、規則、人,實際上我們還需要房間(桌子)、椅子(座位)。

一款撲克遊戲有很多介面、子介面;我們大體將其分為:房間內,房間外。房間內就是一個桌面,UI都顯示到桌面上。房間外包括一些撲克遊戲的常用介面和功能:註冊、登入、使用者資訊;房間列表;查詢(分數記錄、排名等);其他比如:公告、幫助、設定。這些都可以做成通用的幾套,不同遊戲選擇其中的一套即可。房間內除了3類選擇器,還需要下面一些介面UI:座位、牌(比如公共牌、出牌)、定時器、圖片(比如籌碼)、文字(用於顯示數值或文字)。這裡除了一些業務級別的UI物件,也包含一些基礎的UI物件。

3、管理員與通訊庫

現實中,幾個朋友坐一桌打撲克的時候,每個人都按照流程和規則來,大家共同監督。而對於線上的撲克遊戲,其實有一個規則執行者,不妨稱之為管理員(我們前面將選項稱之為“命令”,可以理解為:管理員下達出牌的命令,由玩家選擇出牌還是不出。所以,“選項”是站在玩家角度,“命令”是站在管理員角度)。那麼前文的說法,可以進一步升級為:撲克遊戲就是由管理員控制一套流程規則,特定的時候交由玩家來選擇選項、選擇牌、選擇值,這樣一種競賽遊戲。這裡我們引入了管理員的概念。

下面說通訊庫:

幾個朋友坐一桌打撲克的時候,比如發牌,每個人收到的牌,其他人不能看到;再比如一個人出牌,是要給其他人看到。現實中打牌,我們是靠視覺來看,相當於靠光線傳播資料(影像),而對於網路遊戲,則需要的是一個通訊庫通過網路傳輸資料。我們不能僅僅提供一個簡單的基於socket、websocket、http封裝(比如常見的封裝介面有 read_cmd,read_version,read_int,read_string....),這太底層了,我們需要的是一個業務級別的通訊庫。

比如你跟你老婆說:晚上加班要11點回去,你老婆說“好的”。通訊庫應該是這樣的:

建立一問一答的非同步請求,發給老婆;

請求分類是告假(晚上晚回);引數是11點;

答覆選項是3種:好的;不行;超時;(如果你老婆不是話癆的話)

再比如人事部給每個員工發簡訊,內容是本月工資明細。通訊庫就是群發簡訊,格式相同,但內容不同。

通過分析一些撲克遊戲,我們從這樣幾個層面進行設計抽象:通訊方向、是否應答、傳送目標、單發還是群發。其中:不需要答覆的,我們叫通知;需要答覆的,我們叫“命令”或“請求”。從客戶端發向管理員,稱之為“客戶端請求”;從管理員向客戶端傳送,稱之為“服務端命令”;最終,我們把通訊歸納成5種模板:客戶端請求;服務端命令;服務端廣播;服務端私有通知;服務端公開通知;

有了通訊庫,我們需要往裡面塞資料,資料包括:通訊型別名稱、命令選項、數值、牌。實際上資料內容也正是對應了選擇選項、選擇牌、選擇數值。

舉個例子:比如輪到一個玩家出牌了,我們使用服務端命令定義了一個出牌命令,這是一問一答的通訊,管理員傳送時,不攜帶資料。客戶端答覆時,選項包括:出、不出;如果出牌,則需要攜帶出的牌。

再舉一個例子:遊戲結束時需要通知輸贏,這時可以使用服務端公開通知,就是服務端給每一個玩家傳送通知,通知內容是這一局輸了還是贏了,贏了多少金幣。那麼,這個通訊中,攜帶的就是贏的金幣(如果為負值,則表明是輸)

總結一下:套用這5種模板,通過定義名稱、攜帶的資料,來定義遊戲中特定的通訊過程。比如拖拉機遊戲中有以下幾種通訊的定義:發牌公開通知、亮主請求、亮主結果廣播、扣底牌命令、扣底牌通知、出牌命令、出牌結果廣播、結算通知。此外所有遊戲都會用到一些公共的通訊定義:坐下請求、站起請求、一局開始廣播、一局結束廣播、聊天等。

在通訊中,還涉及到資料對不同客戶端的可見性的問題,這裡就不再深入介紹了。

4、流程

通過分析數十款不同特點的撲克遊戲,整理了下面一種思路:

所有撲克遊戲,在概念上,可以這樣劃分:

  • 一局
  • 階段
  • 一輪

比如鬥地主,從發牌,到出牌,到結束,這是一局。一局結束後,開始下一局。

一局遊戲可以劃分成幾個階段,比如發牌階段,出牌階段,結算階段;

大多數撲克遊戲都是每個人輪著來的。還有一些遊戲(或者遊戲中的某個環節)是允許搶先的(比如拖拉機的亮主)。在技術上,一輪就是一個非同步迴圈,提供很多引數和控制。

以上是為了方便而從概念上劃分的,並不絕對,使用這樣一種套路,開發不同撲克遊戲時,可以更加統一了。

5、組裝

到目前為止,我們已經完成了下面的成品模組、框架、零元件。

  • 一套撲克演算法庫
  • 房間內的UI庫
  • 房間外的幾套成品模組
  • 5種通訊類别範本
  • 流程庫

命令選擇器;牌選擇器;值選擇器;頭像、牌、圖片、文字;

註冊、登入、使用者資訊;房間列表;查詢(分數記錄、排名等);其他比如:公告、幫助、設定。

客戶端請求;服務端命令;服務端廣播;服務端私有通知;服務端公開通知;

提供一局、階段、一輪等控制;

對於不同撲克遊戲,我們首先要把遊戲玩法弄清楚,然後用這些成品模組、框架、零元件,通過配置,通過編寫一些程式碼來進行粘合,從而實現一個完整的遊戲。

在實際的開發過程中我們驗證了:對於簡單的遊戲,三五天就可以完成,對於極其複雜的遊戲,一般在1~2周(比如拖拉機這類遊戲)。這裡說的是一個人,同時也包含自測時間。

為了提升粘合的效率,開發一個圖形化程式設計工具,這裡附上一些截圖供參考:

  • 主介面
  • 函式庫
  • 牌型演算法的例子
  • 流程控制
  • 除錯

45歲碼農用不到2年時間擼出100款撲克遊戲

45歲碼農用不到2年時間擼出100款撲克遊戲

除了演算法庫、UI庫以外,還包含了程式語言級別的函式、流程控制函式等。

45歲碼農用不到2年時間擼出100款撲克遊戲

有了這個工具,寫牌型演算法就快多了。

45歲碼農用不到2年時間擼出100款撲克遊戲

這個圖中的例子,包括了對一副牌進行洗牌,每次取出17張牌,在一個迴圈中,給每一個玩家發牌。下面是用英文顯示函式的樣子:

45歲碼農用不到2年時間擼出100款撲克遊戲

實際使用過程中,還是習慣英文程式設計。切換到中文相當於看看文件。

45歲碼農用不到2年時間擼出100款撲克遊戲

除錯的時候,可以隨時看一組牌是什麼牌,這樣很方便,對開發效率的提升很明顯。

以上介紹的圖形化開發工具,已經具備的工程管理、圖形化程式設計(編輯)、除錯、釋出、以及介面設定等輔助功能為一體的整合化開發環境。是圖形化程式設計的一次有益的嘗試。

6、測試

技術人員自己可以搞定的測試是:單元測試;功能測試;效能測試(壓力測試);

我們還請了專業的測試團隊進行了遊戲內測。

簡單的公測:找老家親戚朋友拉微信群,有些朋友人脈廣,可以拉很多人。然後每天集中半小時搞一次測試,玩5局發10元紅包,連續測試一週就差不多了。這種測試還挺有效,而且投入不大。

7、進展

目前,專案已經基本達成了技術目標,所有撲克遊戲使用了同一套演算法庫(C++程式碼使用emscripten 轉為 javascript)、同一套UI庫(html5/pixi.js)、兩套標準的大廳,同一個伺服器程式(C++),同一套通訊庫(javascript)。另外還有:管理和監控後臺;伺服器更新;客戶端更新;html5錯誤上報;C++錯誤上報等等。

除C++程式碼未開源,其他程式碼都開源了,文件齊全,放在 gitee上了,歡迎大家下載使用,歡迎提意見和交流。

(在html5瀏覽器相容性方面有一些問題,比如UC瀏覽器、搜狗瀏覽器,特別需要熟悉這塊的同學能給與一些支援!)

gitee.com/szcuipeng/public

後記

作者是9年前誤入遊戲行業,也有幸在一家上市遊戲公司擔任技術副總監,並承擔過遊戲引擎主程的工作。其實我不是很喜歡棋牌遊戲開發,如果有機會,我更想去加入古劍或河洛的團隊中去學習。我大學出來後大部分時間裡,從事的是GIS(地圖編輯、空間分析、圖形)開發,也有一部分跟AutoCAD有關,都是windows客戶端。一個團隊40多號人,開發企業用大型客戶端,當時在國內也頗為壯觀。現在看到米國禁止我們們大學用MATLAB,我也很想投入到這些領域中。

自己一直喜歡幹技術,雖然早已是大齡,但也一直堅持幹技術,是因為從大學時候起,就想在技術上幹出一點名堂來。那時自己仰望一些技術大牛,就像小蝦米仰望14本天書中的大俠一樣,希望有一天像他們一樣,成為技術界的俠之大者,成為對社會對行業有用的人。

風馬 2020年7月


來源:騰訊遊戲學院
原文:https://gameinstitute.qq.com/community/detail/133491

相關文章