简体   繁体   English

OpenTK 按键?

[英]OpenTK keypress?

I'm looking for a cross platform (Win & MacOS) method to detect keypresses in C# for an OpenGL application.我正在寻找一种跨平台(Win 和 MacOS)方法来检测 OpenGL 应用程序的 C# 中的按键。

The following works, but for alphanumeric characters only.以下工作,但仅适用于字母数字字符。

protected override void OnKeyPress(OpenTK.KeyPressEventArgs e)
{
    if (e.KeyChar == 'F' || e.KeyChar == 'f')
        DoWhatever();
}

Currently, I'm hacking it, detecting when the user releases a key:目前,我正在破解它,检测用户何时释放密钥:

void HandleKeyUp (object sender, KeyboardKeyEventArgs e)
{
    if (e.Key == Key.Tab)
        DoWhatever();
}

Using OpenTK.Input, I can test if a key is being held, but I'm after the initial keypress only.使用 OpenTK.Input,我可以测试一个键是否被按住,但我只在初始按键之后。

var state = OpenTK.Input.Keyboard.GetState();

if (state[Key.W])
    DoWhatever();

So, what approaches are OpenTK users taking to register keypresses?那么,OpenTK 用户使用哪些方法来注册按键呢?

SOLUTION解决方案

As suggested by Gusman, simply by comparing the current keyboard state to that of the previous main loop.正如 Gusman 所建议的,只需将当前键盘 state 与之前的主循环进行比较即可。

KeyboardState keyboardState, lastKeyboardState;

protected override void OnUpdateFrame(FrameEventArgs e)
{
    // Get current state
    keyboardState = OpenTK.Input.Keyboard.GetState();

     // Check Key Presses
    if (KeyPress(Key.Right))
            DoSomething();

    // Store current state for next comparison;
    lastKeyboardState = keyboardState;
}

public bool KeyPress(Key key)
{
    return (keyboardState [key] && (keyboardState [key] != lastKeyboardState [key]) );
}

Change a bit your mind and you will see it clear. 稍微改变主意,您会清楚地看到它。

You're programming an OpenGL application, so you have a main loop where you update and render your objects. 您正在编写OpenGL应用程序,因此您有一个主循环,您可以在其中更新和渲染对象。

If in that loop you get the keyboard state and compare to the previous stored state you have all the keyboard changes, then it's very easy to fire your own events (or just call functions) with the key changes. 如果在该循环中您获得了键盘状态并与以前的存储状态进行了比较,则您拥有所有键盘更改,那么使用键更改来触发您自己的事件(或仅调用函数)非常容易。

In this way you will use the inherent mechanism to OpenTK and will be 100% portable. 这样,您将对OpenTK使用固有机制,并且100%可移植。

Local copy of variables is way faster than accessing class fields, and 1 order of magnitude accessing class properties.变量的本地副本比访问 class 字段和访问 class 属性快 1 个数量级。

This simple test (code below) gives the following results:这个简单的测试(下面的代码)给出了以下结果:

T1 - Run of 1000000000 steps in 4044,5982 ms.
Average time: 4,0445982E-06 ms/step
T2 - Run of 1000000000 steps in 15932,7434 ms.
Average time: 1,5932743399999998E-05 ms/step
T3 - Run of 1000000000 steps in 2625,8213 ms.
Average time: 2,6258213E-06 ms/step

Source Code:源代码:

public class Test1
{
    public int f1 = 10;
    public float f2 = 2f;
    public float f3 = 3f;
    public float f4 = 1f;

    public Test1(int k)
    {
        this.f1 *= k;
        this.f2 *= k;
        this.f3 *= k;
        this.f4 *= k;
    }
}

public class Test2
{
    public int f1 { get; set; } = 10;
    public float f2 { get; set; } = 2f;
    public float f3 { get; set; } = 3f;
    public float f4 { get; set; } = 1f;

    public Test2(int k)
    {
        this.f1 *= k;
        this.f2 *= k;
        this.f3 *= k;
        this.f4 *= k;
    }
}

internal class Program
{
    static void Main(string[] args)
    {
        int n = 1000 * 1000 * 1000;
        System.Diagnostics.Stopwatch watch;

        Test1 t1 = new Test1(2);
        watch = System.Diagnostics.Stopwatch.StartNew();
        for (int i = 0; i < n; i++)
        {
            float a = t1.f1 + t1.f2 * t1.f3 / t1.f4 - (float)i / (float)(i + 1);
        }
        watch.Stop();
        Console.WriteLine("T1 - Run of " + n + " steps in " + watch.Elapsed.TotalMilliseconds + " ms.");
        Console.WriteLine("Average time: " + watch.Elapsed.TotalMilliseconds / n + " ms/step");

        Test2 t2 = new Test2(2);
        watch = System.Diagnostics.Stopwatch.StartNew();
        for (int i = 0; i < n; i++)
        {
            float a = t2.f1 + t2.f2 * t2.f3 / t2.f4 - (float)i/(float)(i+1);
        }
        watch.Stop();
        Console.WriteLine("T2 - Run of " + n + " steps in " + watch.Elapsed.TotalMilliseconds + " ms.");
        Console.WriteLine("Average time: " + watch.Elapsed.TotalMilliseconds / n + " ms/step");

        Test1 t3 = new Test1(2);
        int f1 = t3.f1;
        float f2 = t3.f2;
        float f3 = t3.f3;
        float f4 = t3.f4;
        watch = System.Diagnostics.Stopwatch.StartNew();
        for (int i = 0; i < n; i++)
        {
            float a = f1 + f2 * f3 / f4 - (float)i / (float)(i + 1);
        }
        watch.Stop();
        Console.WriteLine("T3 - Run of " + n + "  steps in " + watch.Elapsed.TotalMilliseconds + " ms.");
        Console.WriteLine("Average time: " + watch.Elapsed.TotalMilliseconds / n + " ms/step");

        Console.ReadKey(true);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM