听起来你正在开发一款很酷的游戏。 Microsoft Azure Table Storage(一个 NoSQL 数据库)非常快,非常适合您的游戏。您可以使用 Slazure(我编写了 Slazure BTW),它包含一个查询语言(一个自定义 LINQ 提供程序),它还将数据存储在 Azure 表存储中。如果我为您的游戏使用 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 毫秒) 到 10,000 毫秒进入游戏的所有位置,如下所示:
// 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;
}