适用于C#电脑游戏(WinForms)的简单,快速的实时图形 [英] Simple and fast real-time graphics for C# computer game (WinForms)

查看:121
本文介绍了适用于C#电脑游戏(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆