Các kết hợp chính trên đầu vào dựa trên cuộc thăm dò


9

Vì vậy, giả sử bạn có một hệ thống đầu vào dựa trên bỏ phiếu

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

Giả sử bạn muốn có thể nhận ra 3 đến 8 tổ hợp phím dài (như xuống, xuống dưới, tiến lên, A cho hado-ken)

Làm thế nào tốt nhất bạn có thể tạo ra một hệ thống nhập liệu kết hợp khóa chung (dễ sửa đổi / lập trình) trên đầu vào được thăm dò ?

Câu trả lời:


7

Về cơ bản, bạn không thể . Các kết hợp chính yêu cầu đặt hàng và yêu cầu đặt hàng.

Những gì bạn có thể làm là biến việc bỏ phiếu thành các sự kiện bằng cách so sánh các trạng thái chính của từng khung và tạo ra các sự kiện keyup / keydown sau hoc từ sự khác biệt. Điều đó không đáng tin cậy vì bạn mất dấu thời gian và thứ tự nội khung khác mà hệ thống sự kiện "bản địa" cung cấp, nhưng nó sẽ cho phép bạn phát hiện và đặt hàng ít nhất một khóa trên mỗi khung.

Khi bạn đã có những sự kiện được đặt hàng đó, bạn có thể sử dụng máy trạng thái hữu hạn hoặc công cụ khác để khớp chúng với danh sách di chuyển của bạn và thực hiện đúng sự kiện.


Có một chút sai lầm khi nói rằng bạn không thể làm điều này mà không có sự kiện. Về mặt kỹ thuật, các sự kiện chỉ là một cách để gọi một phương thức hoặc danh sách các phương thức khi một số điều kiện được đáp ứng. Theo nghĩa đó, bạn cần các sự kiện. Tuy nhiên, tôi có thể áp dụng các sự kiện từ (không đúng cách) cho nhiều tác vụ lập trình phù hợp với mô tả đó. Tôi đã thêm một câu trả lời giải quyết vấn đề theo cách mà tôi thường làm, nó không sử dụng những gì hầu hết các lập trình viên có xu hướng nghĩ là "sự kiện".
Olhovsky

2
Mã của bạn thực hiện chính xác những gì tôi đã nói sẽ làm mà không có sự kiện, nhưng bỏ qua những cảnh báo - đó là bạn mất thứ tự trong khung. Khi bạn nhận được các sự kiện từ vòng lặp thông báo Win32, bạn sẽ nhận được chúng theo thứ tự có độ chi tiết cao hơn toàn cầu trên mỗi khung. Khi bạn tính toán deltas mình, bạn mất điều đó. Đối với một trò chơi chiến đấu trong đó người chơi có thể nhập một số phần của một kết hợp trong một khung hình duy nhất, bạn cần biết liệu những phần đó có trong hoặc không theo thứ tự.

Đủ công bằng. Với điều kiện chúng tôi đang bỏ phiếu ở mức 60hz, tôi nghi ngờ chúng tôi muốn phân biệt giữa các máy ép cách nhau ít hơn 16ms mà cuộc thăm dò 60Hz cung cấp (giả sử người chơi của chúng tôi là con người).
Olhovsky

Chúng tôi làm. Người chơi trò chơi chiến đấu có kỹ năng có thể nhập lệnh gậy hadouken / shoryuken trong chưa đầy ba khung hình, nghĩa là chúng ta phải phân biệt giữa chúng.

Sau đó, bạn cần thăm dò thường xuyên hơn 60hz.
Olhovsky

3

Một cách là lưu trữ các trạng thái đầu vào hiện tại và trước đó và so sánh chúng mỗi khi bạn thăm dò ý kiến ​​đầu vào.

Đối với mỗi phím có thể được nhấn, lưu trữ một đối tượng có dấu thời gian của lần cuối cùng mà khóa chuyển từ trạng thái xuống sang trạng thái lên.

Cập nhật các đối tượng này bằng cách thực hiện điều này tại mỗi cuộc thăm dò:

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;
        }
    }
}

Bây giờ bạn có thể mô hình phù hợp với combo của bạn so với nội dung của keys.

Có một đối tượng kết hợp cho mỗi kết hợp và gọi cập nhật () trên từng đối tượng kết hợp tại mỗi cuộc thăm dò.

Phương thức update () của một đối tượng kết hợp sẽ tạo mẫu khớp với kết hợp, kiểm tra xem tất cả các điều kiện cần thiết cho kết hợp có được thỏa mãn tại cuộc thăm dò này không. Tức là tất cả các dấu thời gian của các phím cho đến nay đều được sắp xếp theo thứ tự và không có phím nào khác có thể phá vỡ kết hợp đã được nhấn vào khung này. Đối với mỗi điều kiện được đáp ứng, tăng một bộ đếm trong đối tượng kết hợp sang điều kiện tiếp theo để kiểm tra. Khi tất cả các điều kiện được đáp ứng trong một kết hợp, hãy gọi phương thức mà kết hợp sẽ thực hiện. Nếu some_key_has_been_pressed == truenhưng phím đó là điều kiện tiếp theo cho combo chưa được nhấn, thì hãy đặt lại bộ đếm điều kiện thỏa mãn của combo thành 0.

Trên đây là phương pháp ưa thích của tôi, vì nó đơn giản để thực hiện, dễ bảo trì, hiệu quả và có tính mô đun cao.

Tuy nhiên, đối với một phương pháp tốt khác, hãy xem mẫu trình tự đầu vào XNA , được viết bằng C # và logic có thể chuyển sang ngôn ngữ bạn đang sử dụng.


Trong câu lệnh if thứ hai if(current_input[key].down){, bạn cũng không muốn kiểm tra xem khóa có ở previous_inputtrạng thái không? Như đã viết, tôi nghĩ rằng nó sẽ liên tục cập nhật một khóa được giữ down_timestamp.
webdevkit

Liên tục cập nhật dấu thời gian xuống là hành vi dự định. Điều này cho phép bạn so sánh up_timestamp và down_timestamp của bất kỳ khóa nào, để kiểm tra xem nó đã được giữ trong bao lâu. Nếu bạn liên tục giữ một khóa, bạn sẽ không thay đổi up_timestamp, vì vậy (down_timestamp - up_timestamp) vẫn cung cấp cho bạn thời lượng được giữ.
Olhovsky

Cảm ơn bạn đã làm rõ. Tôi đã nghĩ ngược lại, trong đó up_timestamp - down_timestamp là thời lượng của một khóa được giữ.
webdevkit

1

Tạo một ngăn xếp của các sự kiện phím X cuối cùng, đối với mỗi sự kiện khóa, hãy thêm một đối tượng bằng phím và thời gian nhấn / nhả, sau đó kiểm tra xem các thành viên cuối cùng của ngăn xếp có khớp với một mẫu đặc biệt không và liệu các phím đó có được nhấn đủ nhanh không được tính là sự kết hợp Cuối cùng loại bỏ đối tượng cũ nhất khỏi ngăn xếp.


2
Một ngăn xếp mà bạn có thể xóa đối tượng dưới cùng không thực sự là một ngăn xếp;)
Olhovsky

Một loạt các thực thể dữ liệu được sắp xếp, một danh sách có thể là thuật ngữ chính xác.
aaaaaaaaaaaa

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

3
Một chuỗi được sắp xếp trong đó các đối tượng được đặt vào một đầu và được loại bỏ khỏi đầu kia được gọi đúng nhất là một hàng đợi .

1
Bạn có thể tạo bộ đệm vòng (BufferLpm> = lệnh dài nhất) và ghi các phím vào nó (Position = Number MOD BufferLpm). Không cần thêm / xóa hoàn toàn
Kromster
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.