Como obter o tempo decorrido de pressionamento de tecla?
8
Preciso determinar por quanto tempo uma tecla foi mantida pressionada com alta precisão. Por exemplo, se a tecla for pressionada muito rapidamente, é possível relatar um tempo menor que o tempo para cada quadro de atualização.
Com base nos seus outros comentários, tenho que perguntar, a precisão de ~ 16ms é realmente prejudicial ao seu jogo? Praticamente todos os jogos que eu já fiz não se incomodaram com a entrada na escala de sub-quadros. Talvez existam algumas outras coisas que causam o jogo se sentir mal (que eu estou supondo que ele faz, caso contrário, por que você está perguntando?)
Tétrada
11
Você sabe, os jogos Mario não precisavam da precisão do sub-quadro para executar a coisa "guia rápido para salto baixo, pressão total para salto alto". É melhor adicionar um vetor de aceleração para os primeiros 2-3 quadros do salto.
Você pode capturar a entrada usando a classe System.Windows.Forms.NativeWindow. Você receberá uma notificação quando ocorrer um evento de entrada. Dessa forma, você será notificado o mais rápido possível, exatamente quando ocorrer, permitindo que você registre o tempo com maior precisão. Fica meio bagunçado (código nativo / não seguro), mas funciona.
Eu acho que isso só funciona no Windows, mas acho que essa é a plataforma de sua segmentação (não é necessário para isso no Xbox e no WP7).
Aqui está um bom exemplo (da estrutura nuclex): WindowInputCapturer (nota: esse código pode ter sido atualizado recentemente e eu não o codifiquei)
Editar: Isso também permite que você obtenha o código de caractere da tecla pressionada. Isso pode ser útil para receber entrada de texto (especialmente coisas como caracteres latinos). Não sei por que você precisaria obter entrada com uma precisão tão alta, mas seria uma boa maneira de fazê-lo na minha opinião.
XNA é uma estrutura baseada em loop, não uma estrutura baseada em eventos. Se você precisar da hora exata em que um evento ocorreu, considere um projeto winforms (um projeto baseado em evento) e conecte o XNA a um controle, se necessário para renderização.
Armazene o estado da chave em uma variável e compare no próximo loop com os estados da chave atual. Crie um DateTimeobjeto para manter o início e você poderá comparar DateTime.Nowquando o estado da chave anterior não corresponder.
Pedi especificamente algo que possa me dar um tempo menor que o tempo para cada atualização. Sua resposta só me dará tempo em incrementos de 16ms.
AttackingHobo
11
Então execute isso em seu próprio tópico. O XNA não possui manipulador de eventos para alterações no teclado.
riv_rec
Porém, o DateTime.Now tem uma resolução pior que a atualização. Tente o cronômetro.
Kyte
0
Não conheço nenhuma maneira oficial de fazer isso; você pode executar um segundo thread em um loop muito apertado apenas para verificar a entrada e enviá-lo para um buffer circular suficientemente grande para exigir muito pouca sincronização entre os threads.
(Armazene algum tipo de número crescente em cada slot do buffer e atualize que APÓS o thread gravou todos os dados, continue lendo os slots com dados do buffer até o número diminuir (não se esqueça de verificar se há números excedentes!))
Se você atualizar trinta vezes por segundo, um humano não poderá pressionar as teclas mais rapidamente do que você pode experimentar o estado do teclado. Se você atualizar mais lentamente do que um humano pode digitar, poderá precisar de um thread para renderizar gráficos e outro para ler e responder ao teclado / mouse.
Porém, se você atualizar mais lentamente do que um humano pode digitar, também não poderá fornecer feedback visual para cada tecla pressionada. Isso não importa se a idéia é exibir feedback agregado, como tempo médio entre as teclas pressionadas.
Eu nunca disse nada sobre digitação. Quero saber a hora em que uma tecla foi pressionada, os milissegundos exatos.
AttackingHobo
E, na verdade, um ser humano pode digitar a uma taxa de mais de 30 teclas por segundo, mas apenas em uma sequência de poucas teclas, não em uma taxa sustentada.
precisa
Se você atualizar sessenta vezes por segundo, obtém precisão de 16ms. Qual precisão você precisa e por quê?
precisa saber é o seguinte
Para o movimento do jogador, quero que o usuário toque rapidamente uma vez e faça com que o jogador mova menos de uma pressão completa.
AttackingHobo
@AttackingHobo Você não poderia usar equações de movimento para isso? Enquanto pressionado, aplica um vetor de aceleração a um vetor de velocidade? Quanto mais tempo ele é pressionado, maior a velocidade?
Respostas:
Você pode capturar a entrada usando a classe System.Windows.Forms.NativeWindow. Você receberá uma notificação quando ocorrer um evento de entrada. Dessa forma, você será notificado o mais rápido possível, exatamente quando ocorrer, permitindo que você registre o tempo com maior precisão. Fica meio bagunçado (código nativo / não seguro), mas funciona.
Eu acho que isso só funciona no Windows, mas acho que essa é a plataforma de sua segmentação (não é necessário para isso no Xbox e no WP7).
Aqui está um bom exemplo (da estrutura nuclex): WindowInputCapturer (nota: esse código pode ter sido atualizado recentemente e eu não o codifiquei)
Editar: Isso também permite que você obtenha o código de caractere da tecla pressionada. Isso pode ser útil para receber entrada de texto (especialmente coisas como caracteres latinos). Não sei por que você precisaria obter entrada com uma precisão tão alta, mas seria uma boa maneira de fazê-lo na minha opinião.
fonte
XNA é uma estrutura baseada em loop, não uma estrutura baseada em eventos. Se você precisar da hora exata em que um evento ocorreu, considere um projeto winforms (um projeto baseado em evento) e conecte o XNA a um controle, se necessário para renderização.
fonte
Armazene o estado da chave em uma variável e compare no próximo loop com os estados da chave atual. Crie um
DateTime
objeto para manter o início e você poderá compararDateTime.Now
quando o estado da chave anterior não corresponder.Exemplo muito simples do que quero dizer:
fonte
Não conheço nenhuma maneira oficial de fazer isso; você pode executar um segundo thread em um loop muito apertado apenas para verificar a entrada e enviá-lo para um buffer circular suficientemente grande para exigir muito pouca sincronização entre os threads.
(Armazene algum tipo de número crescente em cada slot do buffer e atualize que APÓS o thread gravou todos os dados, continue lendo os slots com dados do buffer até o número diminuir (não se esqueça de verificar se há números excedentes!))
fonte
Se você atualizar trinta vezes por segundo, um humano não poderá pressionar as teclas mais rapidamente do que você pode experimentar o estado do teclado. Se você atualizar mais lentamente do que um humano pode digitar, poderá precisar de um thread para renderizar gráficos e outro para ler e responder ao teclado / mouse.
Porém, se você atualizar mais lentamente do que um humano pode digitar, também não poderá fornecer feedback visual para cada tecla pressionada. Isso não importa se a idéia é exibir feedback agregado, como tempo médio entre as teclas pressionadas.
fonte