我正在开发一款游戏服务器,目前我需要能够在一个区域内吸引观众,不过我担心我使用的是非常丑陋和“慢”,但我还没有遇到任何性能点击我在本地测试它而不是在实时服务器上。
这是我的GetSpectators功能:
public void GetSpectators(ref HashSet<Player> Players, Coordinate_t coordinate, bool MultiFloor = false)
{
for (int x = coordinate.X - 11; x != coordinate.X + 11; x++)
{
for (int y = coordinate.Y - 11; y != coordinate.Y + 11; y++)
{
if (MultiFloor)
{
for (int z = coordinate.Z - 2; z != coordinate.Z + 2; z++)
{
Tile tile = GetTile(x, y, z);
if (tile != null)
{
foreach (Player p in tile.Creatures)
{
Players.Add(p);
}
}
}
}
else
{
Tile tile = GetTile(x, y, coordinate.Z);
if (tile != null)
{
foreach (Player p in tile.Creatures)
{
Players.Add(p);
}
}
}
}
}
}
我有这个类Map,它用Tile类来保存这个其他字典,每个tile用X,Y和Z坐标表示,每个tile都有一个名为Player的类的列表,有些tile有些玩家没有。
我需要一个好方法,而不是丑陋得到例如:
例如,x = 100,y = 100,z = 7,半径为11的所有玩家。
答案 0 :(得分:1)
我认为如果您还没有在Player
课程中引用磁贴,那么将智能化,然后将所有玩家传递给GetSpectators()
方法... < / p>
像...一样的东西。
public class Player
{
// a reference to the tile that the player is currently on.
public Tile CurrentTile { get; set; }
}
这可以让你循环播放玩家而不是那么多牌。如果没有所有的循环嵌套,找到你想要的方式应该更干净,更有效率。例如:
public List<Player> GetSpectators(Hashset<Player> playersInGame, Coordinate coord)
{
var playersInRange = new List<Player>();
// iterate through each player.
foreach (var p in playersInGame)
{
// check if the tile the player is sitting on is in range of radius given.
if ((p.CurrentTile.X < coord.X + 6 || p.CurrentTile.X > coord.X - 6)
&&
(p.CurrentTile.Y < coord.Y + 6 || p.CurrentTile.Y > coord.Y - 6))
{
// Player is within radius.
playersInRange.Add(p);
}
}
return playersInRange;
}
您可以添加Z坐标和任何其他条件语句的附加检查。但正如您所看到的,这将允许您使用一个循环而不是3个嵌套循环。您可能会或可能不会发现它有用。但我希望它有所帮助。
答案 1 :(得分:0)
您可以使用圆圈方程来检查玩家是否位于其他玩家的给定半径内,即
if
x1=100,y1=100,z=7 and r=11
then
(x-x1)^2+(y-y1)^2+(z-z1)^2=r^2.
任何满足这个等式的点都在于该区域。