C#比Console.Write()更快?

时间:2015-04-28 12:52:02

标签: c#

我正在制作游戏并重新绘制游戏区并不是很好用Console.Write()有什么方法可以更快地重写整个字段而不会让它看起来“滞后”? Playfield中的所有内容都在移动,但是只有不同于0的元素才有对象..(你可以在这里查看完整的代码http://pastebin.com/TkPd37xD,如果我的描述不够,可以看看我在说什么)

for (int Y = 0; Y < playfield.GetLength(0); Y++)
{
    for (int X = 0; X < playfield.GetLength(1); X++)
    {
        //destroying the row when it reaches the top
        if (playfield[0, X] != 0)
        {
            for (int i = 0; i < playfield.GetLength(1); i++)
            {
                playfield[0, X] = 0;
                Console.SetCursorPosition(X, 0);
                Console.Write(" ");
            }
        }
        if (playfield[Y, X] == 3)
        {
            playfield[Y - 1, X] = 3;
            playfield[Y, X] = 0;
        }
        else if (playfield[Y, X] == 1)
        {
            Console.SetCursorPosition(X, Y - 1);
            Console.Write("=");
            playfield[Y - 1, X] = 1;
            Console.SetCursorPosition(X, Y);
            Console.Write(" ");
            playfield[Y, X] = 0;
        }
        else if (playfield[Y, X] == 0)
        {
            Console.SetCursorPosition(X, Y);
            Console.Write(" ");
        }
    }
}

3 个答案:

答案 0 :(得分:13)

基本上有两种方法:渲染更少,渲染更快。

渲染较少通常更棘手,但也往往不那么密集。经典的例子是Carmack的Keen游戏 - PC没有勇气立刻重新渲染整个屏幕,所以Carmack确保只有屏幕上真正改变的部分才能重新绘制。在您的情况下,这可以像在旧屏幕上检查新屏幕一样简单(当然,不使用Console方法) - 根据您正在编写的游戏类型,这可以为您节省大量资金工作量。

渲染速度更快通常更容易。过去通常采用的方法是直接访问输出缓冲区 - 而不是将播放区放在单独的内存中,而是将其直接放在显卡中 - 这样可以根据需要快速重绘整个屏幕,当然,因为否则你在CRT屏幕上看不到多少。此选项仍然可以作为向后兼容性访问,因此如果您在Turbo Pascal中编写应用程序代码,仍然可以使用它,但在C#中实际上并不是那么容易访问。可以选择首先在StringBuilder呈现整个屏幕,然后在Console.Write呈现所有屏幕。它会快得多,但它并不完全是恒星。 char[]会为您提供额外的效果 - 您可以直接将您的游戏区域表示为char[][],然后每次更改内容时都不必重新创建StringBuilder - 您只需要每个游戏区一行Console.Write一次。

当然,你可以在发生变化后立即写出变化;根据你正在写的游戏,这可以从“琐碎的结果”到“非常努力而不是好看”。并且由于控制台的缓冲区域可能比窗口大小大,您甚至可以将其绘制到缓冲区的隐藏部分,然后使用Console.MoveBufferArea一次绘制整个更改 - 通常称为“backbuffering”。我不确定它是否会看起来很好 - 现在控制台窗口允许你在缓冲区中滚动,这可能会对你的用例造成伤害。

仍然有办法更快地访问控制台缓冲区,但是在完全使用.NET时则不能 - 你需要使用P / Invokes。关于这个主题的一个很好的答案就在这里 - How can I write fast colored output to Console?。在现代系统中,这几乎等同于使用后备缓冲区并同时“绘制”它 - 它的速度非常快。再一次,你可以直接使用后台缓冲区为你的游戏数据 - 它在20 - 30年前工作,它今天仍然有效;用有限的资源进行游戏是一种很好的做法。你能编写一款真正使用控制台文本缓冲区的游戏,或者至少几乎所有东西吗?玩这样的东西很有趣;你可以写出这么多的游戏,包括俄罗斯方块或Lode Runner等游戏。当然,这只适用于Windows,所以如果你想支持其他系统,那就太麻烦了。

最后,您可以编写自己的控制台(或者更好,使用已经编写并测试过的人)。如果您希望随着时间的推移继续迎接更大的挑战,这将是一个很好的做法,它将允许您随着时间的推移使用更强大的技术。典型的例子是像Dwarf Fortress这样的游戏 - 仍然基于文本,仍然像控制台一样,但实际上是使用SDL等技术以图形方式绘制的。这不仅在现代系统上快得多(因为你没有直接访问文本缓冲区的简单方法),它还可以轻松地切换到图形平铺游戏。它是楼梯上的另一个踩踏石头来冷却东西:))

答案 1 :(得分:0)

另一种方法是使用链接https://msdn.microsoft.com/en-gb/library/windows/desktop/aa363362%28v=vs.85%29.aspx

中指定的API调用
[DllImport("kernel32.dll")]
static extern void OutputDebugString(string lpOutputString);

您还可以通过将for循环中的输出缓冲到 StringBuilder 并在每个for循环后输出来获得轻微的性能。根据您希望通过程序实现的目标,这可能不是必需的。

答案 2 :(得分:0)

如果您隐藏输出cmd窗口,则窗口不会重绘它,并且您的应用程序运行速度比在屏幕上打开时更快。

如果这只是一个调试问题,您可以简单地最小化窗口并看到性能略有提升。