好吧,首先,这是我在这里的第一篇文章,通常我可以过去并简单地搜索答案,但是,因为这有点具体,我无法找到答案之一。
我在某种程度上是编码的初学者(我基本上了解基础知识并观看了很多视频并阅读了很多关于C#的教程)并且正在尝试编写ASCII控制台"游戏" 。一段时间一切都很顺利,但现在我已经陷入了映射部分。起初,我以为我会手动输入墙壁的所有坐标。但是我在这里发现了一篇文章,解释说更多以对象为导向的方法就是创建一个像这样的Tile类。
public class Tile
{
public int X { get; set; }
public int Y { get; set; }
public bool IsWall { get; set; }
}
然后通过执行此操作填充列表
private static void PopulateTiles()
{
for (int x = 1; x < 159; x++)
for (int y = 3; y < 45; y++)
Tiles.Add(new Tile { X = x, Y = y });
}
奇数启动x和y值的原因是因为我将tile限制为控制台的某个部分,其余部分用于GUI。
在任何情况下,除非有更好的方法(并且必须有一个,我只是不知道它可能是什么),我试图只检索该列表的一部分来改变ISWALL属性将其设置为TRUE然后使用此
static void DrawObstacles()
{
foreach (Tile tile in World.Tiles)
{
if (tile.IsWall)
{
Console.SetCursorPosition(tile.X, tile.Y);
Console.Write("#");
}
}
}
到目前为止,我尝试了几种不同的解决方案,但很明显,我遇到了每个问题的问题(如果可能的话,我也试图避免减慢程序的速度,并且避免使用另外1000次迭代的循环)。
//Tried this
private static void SetWalls()
{
int[] walls = new int[] { };
walls += Tiles.GetRange(0, 7); //Fails because I cannot use tiles in an int[]... of course
}
//This
List<Tile> walls = new List<Tile>();
List<Tile> walls = Tiles.GetRange(0, 7);
List<Tile> walls = Tiles.GetRange(19, 7; //Doesn't work either but I've no idea why here
//And finally
List<Tile> walls = new List<Tile>();
walls.Add(Tiles[Tiles.GetRange(0, 7)]); //Gives me an error saying that System.Collections.Generic.List<Engine.Tile> cannot be converted to int
所以现在,我有点迷失,因为我真的更喜欢迭代列表,而不是在2D数组中手动输入每个坐标......然后迭代到#34 ;建立&#34;墙壁。
我的问题是:是否可以只检索列表的某些部分(如索引0 - 7,19 - 26,29,31,35 - 46),然后遍历主要的切片列表以使用这个新的&#34;索引列表&#34;在那些索引处更改tile的ISWALL属性......如果这是有道理的。
提前致谢,请随时告诉我,如果我在帖子中犯了一些错误。
答案 0 :(得分:0)
有很多不必要的信息,所以这个问题很难理解。但是,看起来你不想遍历每个游戏对象来简单地找到一些。这是你在游戏中遇到的一个问题,主要是碰撞。我假设您正在控制台上构建此游戏,因此任何游戏引擎功能都可能无法使用。
所以,我建议您根据其重要性或功能将对象分解为列表。这样做,您只需要在启动时循环遍历每个游戏对象,然后在运行时避免耗尽处理。
例如,您可以像这样初始化所有内容:
List<GameObject> GameObjects { get; set; }
List<GameObject> Walls { get; set; }
List<GameObject> Items { get; set; }
public Map()
{
PopulateTiles();
StructureCollections();
}
//Small processing loop
private void DrawObstacles()
{
foreach(var wall in Walls)
{
Console.SetCursorPosition(tile.X, tile.Y);
Console.Write("#");
}
}
//Called only on startup
private void PopulateTiles()
{
for (int x = 1; x < 159; x++)
for (int y = 3; y < 45; y++)
GameObjects.Add(new GameObject() { X = x, Y = y });
}
//Called only on starup
private void StructureCollections()
{
foreach(GameObject gameObj in GameObjects)
{
if (gameObj.IsWall)
Walls.Add(gameObj);
if (gameObj.IsItem)
Items.Add(gameObj);
}
}
这不是一个完美的解决方案,而且所有这些都取决于您计划如何运行游戏。但我认为这是一个好主意。
更新:如果你想找到一种更好的方法来协调游戏对象的创建,而不是手动完成它们,你可以将对象分成更多的类。例如:
public class GameObject
{
public int X { get; set; }
public int Y { get; set; }
public bool IsWall { get; set; }
public GameObject(int x, int y)
{
X = x;
Y = y;
}
}
public class Wall : GameObject
{
public Wall(int x, int y) : base(x,y)
{
IsWall = true;
}
}
现在在这种情况下,您只需要调用一个新的new Wall(x, y);
,它将处理作为墙操作所需的一切,而不需要更多参数。
更新:由于这被接受作为答案,我觉得有必要指出这个答案是针对一个小而具体的问题。如果你将要有许多需要自己的类的对象,这不是最好的方法(其中“Wall”是它自己的类)。如果我们要有更多的对象,这种设计可能会导致类爆炸。