설문 조사 기반 입력의 키 조합


9

따라서 폴링을 기반으로 한 입력 시스템이 있다고 가정하십시오.

void update()
{
    if( Keyboard[ 'A' ] )
        // A is down
}

3 ~ 8 개의 길이 키 조합 (아래쪽, 아래쪽, 앞쪽, hado-ken의 경우 A)을 인식 할 수 있다고 가정하십시오.

폴링 된 입력 에서 일반 (쉽게 수정 가능 / 프로그램 가능) 키 조합 입력 시스템을 어떻게 가장 잘 작성 하시겠습니까?

답변:


7

근본적으로, 당신은 할 수 없습니다 . 키 조합에는 주문이 필요하며 주문에는 이벤트가 필요합니다.

할 수있는 일은 각 프레임의 키 상태를 비교하고 차이점에서 사후 키업 / 키 다운 이벤트를 생성하여 폴링을 이벤트로 전환하는 것입니다. "네이티브"이벤트 시스템이 제공하는 타임 스탬프 및 기타 프레임 내 순서를 잃어 버릴 수 있기 때문에 신뢰할 수 없지만 프레임 당 하나 이상의 키를 감지하고 주문할 수 있습니다.

주문한 이벤트가 있으면 유한 상태 머신 또는 기타 도구를 사용하여 이동 목록과 일치시키고 올바른 이벤트를 실행할 수 있습니다.


이벤트 없이는 할 수 없다고 말하는 것은 약간 잘못된 것입니다 . 기술적으로 이벤트는 조건이 충족 될 때 메소드 또는 메소드 목록을 호출하는 방법입니다. 그런 의미에서 이벤트가 필요합니다. 그러나 해당 이벤트에 해당하는 많은 프로그래밍 작업에 이벤트를 잘못 적용 할 수 있습니다. 필자는 일반적으로하는 방식으로 문제를 해결하는 답변을 추가했습니다. 대부분의 프로그래머가 "이벤트"로 생각하는 것을 사용하지 않습니다.
Olhovsky

2
귀하의 코드는 이벤트없이 말한 것을 정확하게 수행하지만주의 사항은 무시합니다. 즉, 프레임 내 순서가 손실됩니다. 예를 들어 Win32 메시지 루프에서 이벤트를 받으면 프레임 당 glob보다 세분화 된 순서로 이벤트를 가져옵니다. 델타를 직접 계산하면 잃게됩니다. 플레이어가 단일 프레임에 콤보의 여러 부분을 입력 할 수있는 격투 게임의 경우 순서가 맞았는지 틀렸는 지 알아야합니다.

그럴 수 있지. 60Hz에서 폴링을하고 있다면 60Hz 폴링이 제공하는 16ms 미만의 프레스 (플레이어가 사람이라고 가정)를 구분하고 싶지는 않습니다.
Olhovsky

우리는하다. 숙련 된 전투 게임 플레이어는 3 개 미만의 프레임에서 hadouken / shoryuken 스틱 명령을 입력 할 수 있습니다.

그런 다음 60hz보다 자주 폴링해야합니다.
Olhovsky

3

한 가지 방법은 현재 및 이전 입력 상태를 저장하고 입력을 폴링 할 때마다 비교하는 것입니다.

누를 수있는 각 키에 대해 키가 마지막으로 다운 상태에서 업 상태로 전환 된 시간 소인이있는 오브젝트를 저장하십시오.

모든 폴에서이를 수행하여 이러한 오브젝트를 업데이트하십시오.

void update(){
    some_key_has_been_pressed = false;
    foreach(key in keys){
        if(previous_input[key].Down && current_input[key].Up){
            keys[key].up_timestamp = current_time();
        }

        if(current_input[key].Down){
            keys[key].down_timestamp = current_time();
            some_key_has_been_pressed = true;
        }
    }
}

이제 콤보를 패턴의 내용과 일치시킬 수 있습니다. keys .

각 콤보마다 콤보 객체를 만들고 각 폴에서 각 콤보 객체에 대해 update ()를 호출하십시오.

콤보 객체의 update () 메소드는 콤보와 패턴 일치하여 콤보에 필요한 모든 조건이이 폴에서 충족되는지 확인합니다. 즉, 지금까지 콤보에 대한 모든 키 타임 스탬프가 순서대로 있으며 콤보를 깨는 다른 키는이 프레임에서 눌리지 않았습니다. 충족 된 각 조건에 대해 콤보 개체의 카운터를 다음 조건으로 증가시켜 확인하십시오. 콤보에서 모든 조건이 충족되면 콤보가 수행해야하는 메소드를 호출하십시오. 경우 some_key_has_been_pressed == true만 콤보에 대한 다음 조건 키를 누를되지 않은, 다음 0으로 콤보의 만족 상태 카운터를 재설정합니다.

위의 방법은 구현하기 쉽고 유지 관리가 쉽고 효율적이며 모듈성이 높기 때문에 선호하는 방법입니다.

그러나 다른 좋은 방법 은 C #으로 작성된 XNA 입력 시퀀스 샘플을 확인 하고 논리는 사용중인 언어로 전송할 수 있습니다.


두 번째 if 문 if(current_input[key].down){에서 키가 previous_input상태 에 있는지 확인하고 싶지 않습니까? 서면으로, 개최 키를 지속적으로 업데이트 할 것이라고 생각합니다 down_timestamp.
webdevkit

다운 타임 스탬프를 지속적으로 업데이트하는 것이 의도 된 동작입니다. 이를 통해 어떤 키의 up_timestamp와 down_timestamp를 비교하여 키가 얼마나 오랫동안 유지되었는지 확인할 수 있습니다. 키를 계속 누르고 있으면 up_timestamp를 변경하지 않으므로 (down_timestamp-up_timestamp)는 여전히 지속 시간을 제공합니다.
Olhovsky

설명 주셔서 감사합니다. up_timestamp-down_timestamp가 보류 키의 지속 시간 인 반대의 생각이었습니다.
webdevkit

1

마지막 X 키 이벤트를 스택으로 만들고, 각 키 이벤트에 대해 키 / 시간의 키와 시간이있는 객체를 추가 한 다음 스택의 마지막 멤버가 특수 패턴과 일치하는지, 해당 키가 충분히 빠르게 눌 렸는지 확인하십시오. 조합으로 계산합니다. 마지막으로 스택에서 가장 오래된 개체를 제거하십시오.


2
하단 객체를 제거 할 수있는 스택은 실제로 스택이 아닙니다.)
Olhovsky

순서가 지정된 데이터 엔터티 인 목록은 올바른 용어 일 수 있습니다.
aaaaaaaaaaaa

deque;) O (1) enq / deq ftw.
michael.bartnett

3
객체를 한쪽 끝에 놓고 다른 쪽에서 제거하는 순서를 가장 적절하게 대기열 이라고합니다 .

1
링 버퍼를 만들고 (BufferLength> = 가장 긴 명령) 키를 쓸 수 있습니다 (Position = Number MOD BufferLength). 추가 / 제거는 전혀 필요하지 않습니다
Kromster
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.