Trạng thái bàn phím toàn cầu


7

Tôi có ý tưởng về việc xử lý đầu vào bàn phím. Chúng tôi nắm bắt đầu vào trong lớp Trò chơi "chính" như thế này:

protected override void Update(GameTime gameTime)
{
    this.CurrentKeyboardState = Keyboard.GetState();

    // main :Game class logic here

    base.Update(gameTime);

    this.PreviousKeyboardState = this.CurrentKeyboardState;
}

sau đó, sử dụng lại trạng thái bàn phím (có internalphạm vi) trong tất cả các thành phần trò chơi khác. Lý do đằng sau điều này là 1) giảm thiểu tải xử lý bàn phím và 2) giảm "ô nhiễm" của tất cả các lớp khác có các biến trạng thái bàn phím tương tự.

Vì tôi khá là không thích hợp trong cả phát triển game và XNA, tôi muốn biết liệu tất cả những điều này nghe có hợp lý không.

CẬP NHẬT: Nếu ai đó quan tâm, lớp tiện ích thực tế, như được đề xuất bởi David Gouveia , tôi đã tạo có thể được tìm thấy ở đây .

Câu trả lời:


12

Vâng, nó hoàn toàn hợp lý, và tôi có thể để nó ở đó!

... nhưng cá nhân tôi thích đóng gói hơn một chút. Vì vậy, thay vì quản lý trạng thái bên trong Gamelớp và cung cấp quyền truy cập toàn cầu vào nó, tôi thích bọc nó trong lớp riêng hơn.

Đây là một ví dụ từ bộ nhớ. Không chắc chắn nếu tôi bỏ lỡ một số chi tiết nhưng điều quan trọng là ý tưởng chung:

public static class InputManager
{
    public static void Update()
    {
        _previousKeyboardState = _currentKeyboardState;
        _currentKeyboardState = Keyboard.GetState();
    }

    public static bool IsKeyDown(Keys key) 
    {
        return _currentKeyboardState.IsKeyDown(key);
    }

    public static bool IsKeyUp(Keys key)
    {
        return _currentKeyboardState.IsKeyUp(key);
    }

    public static bool OnKeyDown(Keys key)
    {
        return _currentKeyboardState.IsKeyDown(key) && _previousKeyboardState.IsKeyUp(key);
    }

    public static bool OnKeyUp(Keys key)
    {
        return _currentKeyboardState.IsKeyUp(key) && _previousKeyboardState.IsKeyDown(key);
    }

    private static KeyboardState _currentKeyboardState;
    private static KeyboardState _previousKeyboardState;
}

Sau đó, ở đầu Game.Updatetôi chỉ cần gọi Cập nhật trên trình quản lý:

InputManager.Update();

Và cuối cùng ở mọi nơi khác trong trò chơi, tôi có thể sử dụng trình bao bọc trực tiếp:

if(InputManager.OnKeyDown(Keys.Space))
{
    // Shoot once
}

Một số ưu điểm:

  • Giống như trong giải pháp của bạn, chỉ có một nơi trong ứng dụng cần quản lý trạng thái bàn phím hiện tại và trước đó.
  • Nhưng thay vì làm ô nhiễm lớp trò chơi bằng cách xử lý bàn phím, nó được gói gọn trong lớp riêng của nó chỉ vì điều đó.
  • Lớp này là tĩnh khiến nó có thể truy cập toàn cầu, do đó, nếu bạn không muốn, bạn không cần cung cấp quyền truy cập toàn cầu vào lớp trò chơi của mình.
  • Nó cũng dễ dàng sử dụng lại - nếu bạn bắt đầu một dự án mới, bạn có thể bỏ lớp đó vào và bạn sẽ ổn.

Trong khi bạn đang ở đó, hãy làm cho API dễ dàng ghi lại và phát lại. Bằng cách này, bạn có thể sử dụng đầu vào đóng hộp cho mục đích thử nghiệm sau này.
Patrick Hughes

@PatrickHughes bạn có thể vui lòng giải thích một chút về nhận xét của bạn? Những cách tiếp cận nào tôi có thể thực hiện cho việc này? Một số liên kết có thể hữu ích.
Petr Abdulin

2
@PetrAbdulin Bạn muốn giữ một danh sách các KeyboardStateđối tượng được liên kết với dấu thời gian trong một cấu trúc. Khi bạn chơi trò chơi của mình để thử nghiệm, hãy lấy gameTime.TotalGameTimetừng khung hình và đặt nó vào một cấu trúc với _currentKeyboardStatevà thoát khỏi trò chơi, hãy ghi danh sách KeyboardStates và TimeSpan.Milliseconds ints đó vào đĩa. Sau đó, khi bạn chạy trò chơi ở chế độ nhập thử nghiệm, hãy đọc KeyboardStates và ints từ tệp này và đọc chúng từ danh sách kiểm tra xem KeyboardStatedấu thời gian được liên kết tiếp theo khớp với thuộc tính hiện tại gameTime.TotalGameTime.Milliseconds.
michael.bartnett

@ michael.bartnett cảm ơn bạn rất nhiều vì đã giải thích chi tiết. Tất cả điều này có ý nghĩa.
Petr Abdulin
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.