2015-09-04 42 views
1

我目前有一個遊戲重放文件,我正在分析並想知道存儲數據的最佳方式,以便我可以創建快速的複雜查詢。例如,每隔50毫秒,分析儀就會返回一個數據結構,在該數據結構中,您可以訪問當前圓形細節和遊戲中當前玩家狀態的快照,例如他持有什麼武器,他有多健康,他目前拍攝哪些玩家等等。我希望能夠說:從重播文件的開始到10000毫秒,玩家「邁克爾」的位置是什麼。玩家「凱爾」對其他玩家造成的傷害從10000毫秒到20000毫秒有多大。我希望能夠存儲所有數據,然後使用API​​在前端進行分析並重播,以便您可以在視覺上重放它。 (Round 1,StartTime:10000,EndTime:30000),(Round 2,StartTime:31000,EndTime:37000)。我可以將有關重播的元數據存儲到數據庫中。我還可以存儲關於一名玩家何時被殺的元數據(Kyle,DeathTime:31000,KilledBy:Micheal)或者一名玩家受傷(Kyle,HurtBy:Micheal,Damage:10,Weapon:x)。存儲重放數據的最佳方式

爲了完成我想要爲不同情況創建複雜查詢所要做的事情,我是否需要兩者的組合?比如像毫秒數據庫/文件那樣以毫秒數據存儲毫秒數據,然後解析總文件並將第二段中提到的元數據存儲到另一個數據庫中。僅以毫秒數據存儲毫秒數據,然後是否有能力創建快速查詢來解析我想要的數據?

回答

0

聽起來像一個很酷的遊戲,你正在努力。 Microsoft Azure Table Storage(NoSQL數據庫)速度非常快,對你的遊戲來說非常完美。您可以使用包含查詢語言(自定義LINQ提供程序)並且還將數據存儲在Azure表存儲中的Slazure(我編碼的Slazure BTW)。如果我爲你的遊戲使用Slazure和Microsoft Azure Table Storage NoSQL數據庫,我會這樣做。我建議你將在PlayersTable表中存儲一行,其中PartitionKey是玩家名稱,而RowKey是遊戲回合的多少毫秒 - 因爲每個表都在PartitionKey列上索引並且按排序RowKey列使用這些列的所有查詢確實非常快。還有爲使用的武器創建的列,屏幕上的位置,健康狀況,圓號以及哪個玩家被誰殺死。你可以創建一個表使用下同提出的方法來保存數據的破壞:

using SysSurge.Slazure; 
using SysSurge.Slazure.Linq; 
using SysSurge.Slazure.Linq.QueryParser; 

namespace TableOperations 
{ 
    public class PlayerInfo 
    { 
     // List of weapons 
     public enum WeaponList { 
      Axe, Arrow, Knife, Sling 
     }; 

     // Update a player with some new data 
     public void UpdatePlayerData(dynamic playersTable, DateTime gameStartedTime, int round, string playerName, WeaponList weapon, int healthPoints, int xPos, int yPos) 
     { 
      // Create an entity in the Players table using the player name as the PartitionKey, the entity is created if it doesn't already exist 
      var player = playersTable.Entity(playerName); 

      // Store the time the event was recorded for later as milliseconds since the game started. 
      // This means there is one row for each stored player event 
      player.Rowkey = ((DateTime.UtcNow.Ticks - gameStartedTime.Ticks)/10000).ToString("d19"); 

      player.Round = round; // Round number 
      player.Weapon = (int)weapon; // Weapon carried by player. Example Axe 

      // Store player X and Y position coordinates on the screen 
      player.X = xPos; 
      player.Y = yPos; 

      // Number of health points, zero means player is dead 
      player.HealthPoints = healthPoints; 

      // Save the entity to the Azure Table Service storage 
      player.Save() 
     } 

     // Update a player with some new data 
     public void PlayerKilled(dynamic playersTable, DateTime gameStartedTime, int round, string playerName, string killedByPlayerName) 
     { 
      // Create an entity in the Players table using the player name as the PartitionKey, the entity is created if it doesn't already exist 
      var player = playersTable.Entity(playerName); 

      // Store the time the event was recorded for later as milliseconds since the game started. 
      // This means there is one row for each stored player event 
      player.Rowkey = ((DateTime.UtcNow.Ticks - gameStartedTime.Ticks)/10000).ToString("d19"); 

      player.Round = round; // Round number 

      // Number of health points, zero means player is dead 
      player.HealthPoints = 0;  

      player.KilledByPlayerName = killedByPlayerName; // Killed by this player, example "Kyle" 

      // Save the entity to the Azure Table Service storage 
      player.Save() 
     } 

     // Get all the player positions between two time intervals 
     public System.Linq.IQueriable GetPlayerPositions(dynamic playersTable, string playerName, int fromMilliseconds, int toMilliseconds, int round) 
     { 
      return playersTable.Where("PrimaryKey == @0 && RowKey >= @1 && RowKey <= @2 && Round == @3", 
       playerName, fromMilliseconds.ToString("d19"), toMilliseconds.ToString("d19"), round).Select("new(X, Y)"); 
     }  

    } 
} 

首先,你需要記錄當比賽開始和回合數:

var gameStartedTime = DateTime.UtcNow; 
var round = 1; // Round #1 

,並創建一個表在NoQL數據庫:現在

// Get a reference to the Table Service storage 
dynamic storage = new DynStorage("UseDevelopmentStorage=true"); 

// Get reference to the Players table, it's created if it doesn't already exist 
dynamic playersTable = storage.Players; 

,在遊戲過程中,你可以不斷地像這樣更新播放器的信息:

UpdatePlayerData(playersTable, gameStartedTime, round, "Micheal", WeaponList.Axe, 45, 12313, 2332); 
UpdatePlayerData(playersTable, gameStartedTime, round, "Kyle", WeaponList.Knife, 100, 13343, 2323); 

如果你需要等待50毫秒,你可以這樣做的每個存儲事件之間:

System.Threading.Thread.Sleep(50); 

,然後存儲一些玩家事件數據:

UpdatePlayerData(playersTable, gameStartedTime, round, "Micheal", WeaponList.Axe, 12, 14555, 1990); 
UpdatePlayerData(playersTable, gameStartedTime, round, "Kyle", WeaponList.Sling, 89, 13998, 2001); 

當的一個玩家已經死了,你可以用同樣的方法調用零點生命值和殺死他/她的玩家的名字:

PlayerKilled(playersTable, gameStartedTime, round, "Micheal", "Kyle"); 

現在,在你隨後的比賽分析,你可以查詢所有從遊戲開始(0毫秒)的位置到10000毫秒進入遊戲如下:

// Get a reference to the table storage and the table 
dynamic queryableStorage = new QueryableStorage<DynEntity>("UseDevelopmentStorage=true"); 
QueryableTable<DynEntity> queryablePlayersTable = queryableStorage.PlayersTable; 

var playerPositionsQuery = GetPlayerPositions(queryablePlayersTable, "Micheal", 0, 10000, round); 

// Cast the query result to a dynamic so that we can get access its dynamic properties 
foreach (dynamic player in playerPositionsQuery) 
{ 
    // Show player positions in the console 
    Console.WriteLine("Player position: Name=" + player.PrimaryKey + ", Game time MS " + player.RowKey + ", X-position=" + player.X + ", Y-position=" + player.Y; 
} 
+0

比方說,有大約30000位玩家如移動。 (X,Y,Z,LookLocation,Velocity)。抓住這些職位的表現如何?我們還要說,有100人試圖做同樣的事情。 Azure的表格存儲沒有限制嗎?除此之外,我將試驗這個看看它對我有多好。 –

+0

@MohamadBataineh Azure存儲可以處理20,000次IOPS(每秒讀/寫操作),這對大多數應用程序來說應該足夠了,請參閱https://azure.microsoft.com/en-us/documentation/articles/storage-scalability-targets/更多細節。您可以一次性獲取所有30,000個職位,也可以在Slazure查詢中使用分頁,一次只檢索部分查詢結果。 – 2015-09-04 20:30:33

+0

@MohamadBataineh您可以一次獲得所有30,000個職位,或者在Slazure查詢中使用分頁來一次只檢索部分查詢結果,例如'.Take(1000).Skip(10000)'將檢索1,000行,跳過前10,000行,從而僅檢索10,000到11,000行。有關詳細信息,請參閱示例https://www.syssurge.com/Help/Slazure/html/M_SysSurge_Slazure_Linq_QueryParser_DynamicQueryable_Skip.htm和https://www.syssurge.com/Help/Slazure/html/M_SysSurge_Slazure_Linq_QueryParser_DynamicQueryable_Take.htm。 – 2015-09-04 20:36:24