gpt4 book ai didi

c# - 如何使用 Graphics.Draw 高效渲染图 block ?

转载 作者:行者123 更新时间:2023-11-30 17:38:54 26 4
gpt4 key购买 nike

我目前正在用 C# 制作基于图 block 的游戏,但每次我绘制图 block 时它都会使用大量 CPU,并且随着图 block 变大(如果我让游戏全屏显示)它会消耗更多。这是我的 Tile 类:

 public class Tiles
{
//PRIVATE :

//variabiles
private int XPosition, YPosition;
private Image Texture;
private bool Colidable;
private int SizeW = 32;
private int SizeH = 32;
private Resizer resizer = new Resizer();
//methods




//PUBLIC :

//variabiles


//methods

//CONSTRUCTOR
public Tiles(int _x,int _y,Image _i, int _sW = 32, int _sH = 32, bool _c = false)
{
XPosition = _x;//set position X
YPosition = _y;//set position Y
SizeW = _sW;
SizeH = _sH;
Texture = resizer.ResizeImage(_i, SizeW, SizeH) ;// set texture

Colidable = _c;//set if the tile is colidable,default : false
resizer = null;
}

//DRAW METHOD
//gets graphics object to draw on, adn draws at the position of the tile
public void Draw(Graphics _g)
{
_g.DrawImage(this.Texture, this.XPosition, this.YPosition);
}

//GET PRIVATE MEBERS
//returns if the tile is colidable
public bool getColidable()
{

return this.Colidable;

}
}

这就是我绘制方 block 的方式:

private void DrawMap(Graphics _g)
{
//CALLS THE DRAW METHOD OF EACH TILE
for (int i = 0; i < MAP_WIDTH; i++)
{
for (int j = 0; j < MAP_HEIGHT; j++)
{
Tile[i, j].Draw(_g);
}

}

}
bool TilesUpdate = false;


private void _Window_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);

if (isGameRunning)
{

DrawMap(e.Graphics);
}
else
{
FullRezolutionBtn.Draw(e.Graphics);
BigRezolutionBtn.Draw(e.Graphics);
NormalRezolutionBtn.Draw(e.Graphics);
}

}


private void Update_Tick(object sender, EventArgs e)
{
Invalidate();

}

我想提一下, map 是 20 x 20 的图 block ,全屏时它占用了大约 50% 的 CPU。

最佳答案

正如我在评论中提到的,方向应该是少画。一种方法是仅当与该部分相关的内容发生变化时,才使绘图 Canvas 的部分无效并绘制该部分。 Windows 本身对控件/窗口进行了这样的优化。

这是一个例子。看看 Gadget 类如何在某些属性更改时使其矩形无效。然后在绘制期间,仅绘制与 e.ClipRectange 相交的矩形。这大大减少了绘图操作的数量。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Samples
{
class Gadget
{
public readonly Control Canvas;

public Gadget(Control canvas) { Canvas = canvas; }

private Rectangle bounds;
public Rectangle Bounds
{
get { return bounds; }
set
{
if (bounds == value) return;
// NOTE: Invalidate both old and new rectangle
Invalidate();
bounds = value;
Invalidate();
}
}

private Color color;
public Color Color
{
get { return color; }
set
{
if (color == value) return;
color = value;
Invalidate();
}
}

public void Invalidate()
{
Canvas.Invalidate(bounds);
}

public void Draw(Graphics g)
{
using (var brush = new SolidBrush(color))
g.FillRectangle(brush, bounds);
}
}


static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

var form = new Form { WindowState = FormWindowState.Maximized };
int rows = 9, cols = 9;
var gadgets = new Gadget[rows, cols];
var rg = new Random();
Color[] colors = { Color.Yellow, Color.Blue, Color.Red, Color.Green, Color.Magenta };
int size = 64;
var canvas = form;
for (int r = 0, y = 8; r < rows; r++, y += size)
for (int c = 0, x = 8; c < cols; c++, x += size)
gadgets[r, c] = new Gadget(canvas) { Color = colors[rg.Next(colors.Length)], Bounds = new Rectangle(x, y, size, size) };
int paintCount = 0, drawCount = 0;
canvas.Paint += (sender, e) =>
{
paintCount++;
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
if (e.ClipRectangle.IntersectsWith(gadgets[r, c].Bounds))
{
gadgets[r, c].Draw(e.Graphics);
drawCount++;
}
}
}
form.Text = $"Paint:{paintCount} Draw:{drawCount} of {(long)paintCount * rows * cols}";
};
var timer = new Timer { Interval = 100 };
timer.Tick += (sender, e) =>
{
gadgets[rg.Next(rows), rg.Next(cols)].Color = colors[rg.Next(colors.Length)];
};
timer.Start();


Application.Run(form);
}
}
}

关于c# - 如何使用 Graphics.Draw 高效渲染图 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36279425/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com