我正在为我的C#学校项目编写一个俄罗斯方块克隆。我正在使用Microsoft Visual Studio 2012.游戏本身实现为块的二维数组(块列表),每个块都有自己的纹理(bmp图像)。我将整个数组绘制到PictureBox控件上,这就是问题开始的地方。当更新PictureBox上的图像(移动/旋转活动形状)时,游戏稍微滞后。我尝试在Panel控件上绘图,但结果是一样的。我粗略地了解可能导致滞后的原因,但我不确切知道如何摆脱它。
这是游戏“网格”的绘制方法:
public void Draw(Graphics g)
{
Brush brush;
Font font = new System.Drawing.Font( "Arial", 5);
for (int i = 0; i < Width; i++)
for (int j = 0; j < Height; j++)
{
brush = new TextureBrush(Blocks[i][j].Texture);
if (Blocks[i][j].Occupied==true)
g.FillRectangle(brush, i * 20, j * 20, i * 20 + Blocks[i][j].Texture.Width, j * 20 + Blocks[i][j].Texture.Height);
}
}
这是活跃的tetromino的绘制方法:
public void Draw(Graphics g)
{
Brush brush = new TextureBrush(Blocks[0].Texture);
foreach (FullBlock b in Blocks)
g.FillRectangle(brush, b.x * 20, b.y * 20,b.Texture.Width, b.Texture.Height);
}
然后游戏本身使用它们(双缓冲尝试):
public void GameDraw(PictureBox p)
{
Graphics g = Graphics.FromImage(gb);
gameGrid.Draw(g);
PlayingShape.Draw(g);
p.Image = gb;
p.Refresh();
}
其中"gb"
是一个私有Bitmap
变量,我在类构造函数中只创建一次(以减少(不成功)滞后)。
只要游戏状态发生变化,就会调用GameDraw
方法(例如移动/旋转活动的tetromino和每个“重力”滴答声)
答案 0 :(得分:4)
你需要双缓冲,你没有设置。引用MSDN:
双缓冲使用内存缓冲区来解决闪烁问题 与多个油漆操作相关联。当双缓冲是 启用后,所有绘制操作首先渲染到内存缓冲区 而不是屏幕上的绘图表面
您可以使用Control.DoubleBuffered属性
启用它答案 1 :(得分:0)
此外,开箱即用...不是进行全网格扫描,而是可以将每个形状都作为链接列表的一部分,并根据它们在网格中的位置重新绘制它们...直到你的网格完全填满,你会少做扫描。
或者,只考虑重绘你需要重绘的内容,即一个块在顶部附近掉落,不需要完全重绘整个网格。
优化是我们与动物的区别。除了鸭嘴兽,谁是最佳生物。
答案 2 :(得分:0)
不需要图片框,添加自己的控件:
using System.Drawing;
using System.Windows.Forms;
namespace TetrisGame
{
public sealed class TetrisControl : Control
{
private TheBlockType[][] blocks = ...;
protected override void OnPaint(PaintEventArgs e)
{
//draw your stuff here direct to the control, no buffers in the middle
//if that causes flickering, turn on double buffering, but don't bother doing it yourself
//this is your existing draw method:
Draw(e.Graphics);
}
}
}
然后在每次打勾或移动时,执行不调用paint,只是使控件无效:
tetris.Invalidate();