适用于C#电脑游戏(WinForms)的简单,快速的实时图形 [英] Simple and fast real-time graphics for C# computer game (WinForms)
问题描述
作为C#winforms项目的一部分,我试图使一个整数数组与位图协调工作,以便进行快速PictureBox编辑(避免使用慢速SetPixel命令).
I'm trying to make an integer array and Bitmap work in harmony as part of a C# winforms project for fast PictureBox editing (avoiding the slow SetPixel command).
我添加了一个Button和一个PictureBox,在上述Button上单击了一个事件,并且在Form上添加了一个关闭事件.
I added a Button and a PictureBox, a click event on the aformentioned Button and a closing event on the Form.
表单的代码现在如下所示:
The code for the Form is now like so:
public partial class Form1 : Form
{
uint[] _Pixels { get; set; }
Bitmap _Bitmap { get; set; }
GCHandle _Handle { get; set; }
IntPtr _Addr { get; set; }
public Form1()
{
InitializeComponent();
int imageWidth = 100; //1920;
int imageHeight = 100; // 1080;
PixelFormat fmt = PixelFormat.Format32bppRgb;
int pixelFormatSize = Image.GetPixelFormatSize(fmt);
int stride = imageWidth * pixelFormatSize;
int padding = 32 - (stride % 32);
if (padding < 32)
{
stride += padding;
}
_Pixels = new uint[(stride / 32) * imageHeight + 1];
_Handle = GCHandle.Alloc(_Pixels, GCHandleType.Pinned);
_Addr = Marshal.UnsafeAddrOfPinnedArrayElement(_Pixels, 0);
_Bitmap = new Bitmap(imageWidth, imageHeight, stride / 8, fmt, _Addr);
pictureBox1.Image = _Bitmap;
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < _Pixels.Length; i++)
{
_Pixels[i] = ((uint)(255 | (255 << 8) | (255 << 16) | 0xff000000));
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_Addr = IntPtr.Zero;
if (_Handle.IsAllocated)
{
_Handle.Free();
}
_Bitmap.Dispose();
_Bitmap = null;
_Pixels = null;
}
}
运行时,开始时会出现预期的黑色图像.
When run, a black image as expected is present in the beginning.
当单击按钮时,图像应该变成白色,但是我缺少一些东西.
The image should turn white when the button is clicked, but I'm missing something.
我忘了做什么?
推荐答案
解决方案
在更新_Pixels
数组后添加pictureBox1.Refresh()
.
更新速度非常快,并且能够以高分辨率呈现流畅的视频.
This updates quite quickly, and is capable of rendering smooth video at high resolutions.
添加对System.Runtime.InteropServices的引用(可通过nuget获得)
Add reference to System.Runtime.InteropServices (available via nuget)
表单的代码现在如下所示:
The code for the form is now like so:
public partial class Form1 : Form
{
uint[] _Pixels { get; set; }
Bitmap _Bitmap { get; set; }
GCHandle _Handle { get; set; }
IntPtr _Addr { get; set; }
public Form1()
{
InitializeComponent();
int imageWidth = 100; //1920;
int imageHeight = 100; // 1080;
PixelFormat fmt = PixelFormat.Format32bppRgb;
int pixelFormatSize = Image.GetPixelFormatSize(fmt);
int stride = imageWidth * pixelFormatSize;
int padding = 32 - (stride % 32);
if (padding < 32)
{
stride += padding;
}
_Pixels = new uint[(stride / 32) * imageHeight + 1];
_Handle = GCHandle.Alloc(_Pixels, GCHandleType.Pinned);
_Addr = Marshal.UnsafeAddrOfPinnedArrayElement(_Pixels, 0);
_Bitmap = new Bitmap(imageWidth, imageHeight, stride / 8, fmt, _Addr);
pictureBox1.Image = _Bitmap;
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < _Pixels.Length; i++)
{
_Pixels[i] = ((uint)(255 | (255 << 8) | (255 << 16) | 0xff000000));
}
pictureBox1.Refresh();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_Addr = IntPtr.Zero;
if (_Handle.IsAllocated)
{
_Handle.Free();
}
_Bitmap.Dispose();
_Bitmap = null;
_Pixels = null;
}
}
测试
自然,我想测试这种方法的性能,看它是否足够快以呈现流畅的视频.
Naturally, I wanted to test performance of this method to see if it would be fast enough to render smooth video.
替换带有计时器刻度的按钮
到目前为止,我的测试很简单.我用timer tick event
替换了button click event
,它每毫秒触发一次,然后用随机的颜色值填充_Pixels
数组.
My test so far is a simple one to begin with. I replaced the button click event
with a timer tick event
which fires once every millisecond, and I fill the _Pixels
array with random colour values.
为了确保在所有当前刷新完成之前PictureBox
不会尝试刷新,我使用了一个bool IsRefreshing
变量.
To ensure that the PictureBox
will not try to refresh until any current refreshes have completed, I use a single bool IsRefreshing
variable.
每秒帧数计算
我还通过增加单个int HzCount
变量,并在每次PictureBox
刷新开始时将此变量重置为零,来测量每次刷新之间经过的时间.在重设HzCount
*之前,我会在TextBox
中显示该值.
I also measure the time elapsed between each refresh, by incrementing a single int HzCount
variable, and resetting this variable to zero at the beginning of each PictureBox
refresh. Just before I reset the HzCount
*, I display the value in a TextBox
.
英特尔®酷睿TM i7-5600U CPU @ 2.60GHz 2.60GHz,具有16.0 GB RAM结果:
72Hz @ 2560x1440
* Hertz或Hz表示每秒经过的帧数(或某物多少次).通过扩展,这意味着MegaHertz每秒可转换成数百万次,而GigaHertz每秒可转换成千上万(美国十亿亿次).
*Hertz or Hz means frames (or how many times something) elapsed per second. By extension, this means that MegaHertz translates to millions of times a second and GigaHertz translates to thousand-millions (USA billions) of times a second.
这篇关于适用于C#电脑游戏(WinForms)的简单,快速的实时图形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!