0

我第一次在这里问一个问题,如果我做错了,请纠正我。

我的国际象棋图片:

每次我移动一块它都会滞后大约 1 秒钟。每一块和瓷砖都有一个图像,并且正好有 96 个图像。每次我移动一块时,它都会用黑色清除所有内容,然后更新图形。

在国际象棋的早期阶段,我没有任何图像,而是使用了不同的颜色,只有少数棋子没有明显的滞后,棋子瞬间移动。

        public void updateGraphics(PaintEventArgs e, Graphics g, Bitmap frame)
    {
        g = Graphics.FromImage(frame);
        g.Clear(Color.Black);


        colorMap(g);

        g.Dispose();
        e.Graphics.DrawImageUnscaled(frame, 0, 0);
    }

函数 colorMap(g) 如下所示:

        private void colorMap(Graphics g)
    {
        for (int y = 0; y < SomeInts.amount; y++)
        {
            for (int x = 0; x < SomeInts.amount; x++)
            {
                //Tiles
                Bundle.tile[x, y].colorBody(g, x, y);

                //Pieces
                player1.colorAll(g);
                player2.colorAll(g);
            }
        }
    }

colorAll 函数执行每件 colorBody(g) 函数,如下所示:

        public void colorBody(Graphics g)
    {
        //base.colorBody() does the following: body = new Rectangle(x * SomeInts.size + SomeInts.size / 4, y * SomeInts.size + SomeInts.size / 4, size, size);
        base.colorBody();

        if (team == 1)
        {
            //If its a white queen
            image = Image.FromFile("textures/piece/white/queen.png");
        }
        if (team == 2)
        {
            //If its a black queen
            image = Image.FromFile("textures/piece/black/queen.png");
        }
        g.DrawImage(image, body);
    }

最后是移动作品的功能:

        public void movePiece(MouseEventArgs e)
    {
        for (int y = 0; y < SomeInts.amount; y++)
        {
            for (int x = 0; x < SomeInts.amount; x++)
            {
                if (Bundle.tile[x, y].body.Contains(e.Location))
                {
                    //Ignore this
                    for (int i = 0; i < queens.Count; i++)
                    {
                        Queen temp = queens.ElementAt<Queen>(i);
                        temp.move(x, y);
                    }
                    //Relevant
                    player1.move(x, y);
                    player2.move(x, y);
                }
            }
        }
    }

感谢您阅读这一切!如果我的编码示例还不够,我可以链接到整个程序。

4

4 回答 4

7

Image.FromFile在每次刷新时调用每个图像 - 每次都从磁盘有效地重新加载每个图像文件。

您是否考虑过加载图像一次,并将生成Image的 s 存储在有用的地方?(比如说,一个数组Image[2,6]就足够了)

于 2012-07-05T14:36:52.357 回答
3

为什么每次都重绘棋盘?您不能将板留在原处并在其上显示具有透明背景的图像吗?这样你就有一个图像作为背景(棋盘),再加上 64 个较小的图像以网格的形式放置在棋盘上,并且每次移动时只需更改显示的图像。

这样,您可以让窗口处理绘图...

此外,在应用程序开始时加载碎片的图像。

于 2012-07-05T14:36:57.427 回答
1

除了不在Image.FromFile()内部调用updateGraphics() (这绝对是您最大的问题),您不应该在每次调用时都尝试重新绘制整个电路板updateGraphics()- 大多数情况下,只有一小部分电路板将无效。

PaintEventArgs包含一个参数 ,它指定板的ClipRectangle哪个部分需要重绘。看看您是否无法确定哪些图块与该矩形相交,并且只重绘这些图块:)

提示:编写一个函数,该函数Point ScreenToTileCoords(Point)接受屏幕坐标并返回哪个棋盘图块位于该坐标处。然后,您需要重绘的唯一瓷砖是

Point upperLeftTileToBeDrawn = ScreenToTileCoords(e.ClipRectangle.Left, e.ClipRectangle.Top);
Point lowerRightTileToBeDrawn = ScreenToTileCoords(e.ClipRectangle.Right - 1, e.ClipRectangle.Bottom- 1);

此外,请确保您的控件是双缓冲的,以避免撕裂。这比上述评论中@Steve B 的链接简单得多;假设这是一个UserControl,简单地设置

this.DoubleBuffered = true;
于 2012-07-05T15:32:52.293 回答
0

那么,这个呢:

不要清除整个电路板,而只清除需要清除的部分。

选择:

更新到 WPF - 它将绘图移动到图形卡 - 并且只是以一种智能的方式移动各个部分(即,每个部分都有一个控件/对象)。

于 2012-07-05T14:37:05.550 回答