《球球大作戰》原始碼解析(7):遊戲迴圈

遊資網發表於2019-03-22
《球球大作戰》原始碼解析(7):遊戲迴圈


服務端程式中有3個定時器函式,前兩篇解析的moveloop方法處理了玩家的移動,另外兩個方法分別是gameloop和sendUpdates。其中gameloop負責排行榜和食物產生等邏輯。gameloop是在定時器中呼叫,相關語句為:setInterval(gameloop, 1000),即每秒執行1次。下圖為遊戲右上角的排行榜。

《球球大作戰》原始碼解析(7):遊戲迴圈

排行榜

gameloop先將user表按照重量大小排序,然後把前10名放到topUsers列表中,程式碼如下所示。

  1. function gameloop() {

  2.     if (users.length > 0) {

  3.         users.sort( function(a, b) { return b.massTotal - a.massTotal; });



  4.         var topUsers = [];



  5.         for (var i = 0; i < Math.min(10, users.length); i++) {

  6.             if(users[i].type == 'player') {

  7.                 topUsers.push({

  8.                     id: users[i].id,

  9.                     name: users[i].name

  10.                 });

  11.             }

  12.         }

  13.         ……

  14. }
複製程式碼

緊接著更新leaderboard列表,如果topUsers較之前有改變的話,就標記leaderboardChanged,這樣可以減少不必要的訊息 同步,只傳送有更改的資料。

  1. if (isNaN(leaderboard) || leaderboard.length !== topUsers.length) {

  2.             leaderboard = topUsers;

  3.             leaderboardChanged = true;

  4.         }

  5.         else {

  6.             for (i = 0; i < leaderboard.length; i++) {

  7.                 if (leaderboard[i].id !== topUsers[i].id) {

  8.                     leaderboard = topUsers;

  9.                     leaderboardChanged = true;

  10.                     break;

  11.                 }

  12.             }

  13.         }
複製程式碼

質量損失

如果小球質量較大,那麼它會定時損耗質量,相關程式碼如下所示。

  1. for (i = 0; i < users.length; i++) {

  2.             for(var z=0; z < users[i].cells.length; z++) {

  3.                 if (users[i].cells[z].mass * (1 - (c.massLossRate / 1000)) > c.defaultPlayerMass && users[i].massTotal > c.minMassLoss) {

  4.                     var massLoss = users[i].cells[z].mass * (1 - (c.massLossRate / 1000));

  5.                     users[i].massTotal -= users[i].cells[z].mass - massLoss;

  6.                     users[i].cells[z].mass = massLoss;

  7.                 }

  8.             }

  9.         }
複製程式碼

食物和病毒

最後gameloop呼叫balanceMass方法,它先計算現在場上所有食物和所有玩家的質量之和,然後看看食物會不會太少,如果太少則呼叫addFood新增食物,多了就減少一些食物。同理,也增加或減少一些病毒。

  1. function balanceMass() {

  2.     var totalMass = food.length * c.foodMass +

  3.         users

  4.             .map(function(u) {return u.massTotal; })

  5.             .reduce(function(pu,cu) { return pu+cu;}, 0);



  6.     var massDiff = c.gameMass - totalMass;

  7.     var maxFoodDiff = c.maxFood - food.length;

  8.     var foodDiff = parseInt(massDiff / c.foodMass) - maxFoodDiff;

  9.     var foodToAdd = Math.min(foodDiff, maxFoodDiff);

  10.     var foodToRemove = -Math.max(foodDiff, maxFoodDiff);



  11.     if (foodToAdd > 0) {

  12. //console.log('[DEBUG] Adding ' + foodToAdd + ' food to level!');

  13.         addFood(foodToAdd);

  14. //console.log('[DEBUG] Mass rebalanced!');

  15.     }

  16.     else if (foodToRemove > 0) {

  17. //console.log('[DEBUG] Removing ' + foodToRemove + ' food from level!');

  18.         removeFood(foodToRemove);

  19. //console.log('[DEBUG] Mass rebalanced!');

  20.     }



  21.     var virusToAdd = c.maxVirus - virus.length;



  22.     if (virusToAdd > 0) {

  23.         addVirus(virusToAdd);

  24.     }

  25. }

複製程式碼

最後依然還是放個廣告吧,筆者出版的一本書《Unity3D網路遊戲實戰》充分的講解怎樣開發一款網路遊戲,特別對網路框架設計、網路協議、資料處理等方面都有詳細的描述,相信會是一本好書的。

《球球大作戰》原始碼解析(7):遊戲迴圈



作者:羅培羽
專欄地址:https://zhuanlan.zhihu.com/p/28488266

相關文章