C # / XNA có được vị trí chuột phần cứng


10

Tôi đang sử dụng C # và đang cố lấy vị trí chuột phần cứng. Điều đầu tiên tôi đã thử là chức năng XNA đơn giản, dễ sử dụng

Vector2 position = new Vector2(Mouse.GetState().X, Mouse.GetState().Y);

Sau đó, tôi cũng vẽ chuột và so sánh với chuột phần cứng windows, con chuột mới này với tọa độ xna được cung cấp là "chùng xuống". Ý tôi là, nó ở đằng sau vài khung hình. Ví dụ: nếu trò chơi đang chạy ở tốc độ 600 khung hình / giây, thì lời nguyền sẽ phản ứng nhanh, nhưng ở tốc độ 60 khung hình / giây, độ trễ chuột không còn được chấp nhận. Vì vậy, tôi đã thử sử dụng những gì tôi nghĩ là một con chuột phần cứng,

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);

nhưng kết quả hoàn toàn giống nhau Tôi cũng đã thử lấy con trỏ biểu mẫu Windows và đó cũng là một ngõ cụt - hoạt động tốt, nhưng với cùng độ trễ. Loay hoay với chức năng xna:

GraphicsDeviceManager.SynchronizeWithVerticalRetrace = true/false
Game.IsFixedTimeStep = true/fale

đã thay đổi thời gian trì hoãn vì những lý do rõ ràng, nhưng điểm mấu chốt là bất kể nó vẫn đứng sau chuột Windows mặc định. Tôi đã thấy trong một số trò chơi, họ cung cấp tùy chọn cho chuột được tăng tốc phần cứng và trong các trò chơi khác (tôi nghĩ) nó đã được mặc định. Bất cứ ai có thể đưa ra một số dẫn về làm thế nào để đạt được điều đó.


2
Tôi không nghĩ Mouse.GetState()là bị hỏng. Bạn có chắc chắn rằng bạn đang có được vị trí chuột trong cùng một khung với bạn đang vẽ nó không? Cũng nên nhớ rằng con trỏ Windows đã kích hoạt tăng tốc / giảm tốc, do đó, nó cảm thấy nhạy hơn. Nếu bạn muốn đến gần hơn với phần cứng, bạn nên nhấn DirectInput, điều này sẽ cung cấp cho bạn các vùng chuyển động thay vì vị trí chuột tuyệt đối. Nhưng tôi tin rằng Mouse.GetState()vẫn là cách chính xác để làm điều đó trong XNA.
Panda Pyjama

Không, Mouse.GetState()không bị hỏng và miễn là IsFixedTimeStep == truemọi người không thể thấy độ trễ trừ khi so sánh trực tiếp với chuột cửa sổ có thể nhìn thấy. Tuy nhiên, cài đặt IsFixedTimeStep thành false ở tốc độ khung hình thấp hơn, nó sẽ hiển thị với mọi người. Về đầu vào trực tiếp tôi coi đó là một khả năng (phương sách cuối cùng).
Sunder

Không chắc chắn nếu đó là những gì bạn muốn, nhưng điều gì về việc thay đổi con trỏ sprite trong khi nó ở trong cửa sổ của bạn, và sau đó làm cho nó luôn hiển thị?
William Mariager

Đó chính xác là những gì tôi đang làm, điều đó là tôi không muốn chỉ hiển thị nó, mà còn để biết chính xác vị trí của con chuột. Nhưng những gì tôi đang nhận được hơi chậm so với những gì nó nên được.
Sunder

Câu trả lời:


16

Những gì bạn đang thấy không phải là độ trễ đầu vào.

Để có được vị trí của con trỏ trong Windows, bạn có thể sử dụng WM_MOUSEMOVEhoặc GetCursorPos. Cả hai đều cung cấp vị trí của con trỏ sau khi Windows xử lý nó, áp dụng những thứ như tăng tốc. Đây là vị trí con trỏ mà Windows sử dụng, bao gồm cả để vẽ. Và hầu như luôn luôn những gì bạn muốn sử dụng quá.

Đây là những gì XNA sử dụng . Cụ thể GetCursorPos( MSDN ). Điều này có nghĩa là, khi bạn gọi Mouse.GetState, bạn đang nhận được vị trí thực sự của con trỏ khi Windows nhìn thấy nó - với độ trễ thực tế bằng không.

Bây giờ, bạn có thể sử dụng WM_INPUT(hoặc DirectInput, mặc dù điều đó không được chấp nhận). Điều này cung cấp cho bạn dữ liệu con trỏ thô. Đây là trước khi Windows có thể áp dụng những thứ như tăng tốc và thường không phải là thứ bạn muốn.

Những gì bạn đang thấy độ trễ đầu ra.

Điều này là do " con trỏ phần cứng ". Đây là một sprite nhỏ đó được rút ra trên màn hình bằng GPU tại rất cuối đường ống dẫn của nó. Và tôi có nghĩa là kết thúc . Nó xuất hiện sau bộ đệm khung - nó được chèn vào luồng dữ liệu khi hình ảnh được gửi đến màn hình. Lý do nó phản ứng nhanh như vậy là vì vị trí của nó được đặt bằng cách trực tiếp thiết lập các thanh ghi GPU. Không có sự chờ đợi xung quanh trong đường ống ở tất cả.

Trò chơi của bạn, mặt khác, phải đi qua đường ống GPU. Điều này thêm nhiều sự chậm trễ trên chính nó. Vấn đề lớn nhất trong số này đối với bạn là bộ đệm đôi - điều này (tôi khá chắc chắn) bạn không thể tắt trong XNA 4. Bạn không vẽ trực tiếp vào bộ đệm khung - bạn vẽ vào bộ đệm. Được trình bày sau mỗi ~ 16ms (ở 60FPS). Điều đó có nghĩa là bạn đang xem tối thiểu khoảng 16ms giữa khi nhận được kết quả Mouse.GetStatenhận được thứ gì đó dựa trên kết quả đó trên màn hình. Có lẽ lâu hơn. Chắc chắn chậm hơn nhiều so với con trỏ phần cứng.

Vậy các giải pháp là gì?

Một là sử dụng SetCursor( MSDN ) để thay đổi hình ảnh được hiển thị bởi con trỏ phần cứng, để trở thành hình ảnh phù hợp hơn với trò chơi của bạn (hoặc chỉ sống với con trỏ Windows).

Và cái khác (dễ dàng hơn nhiều) là chỉ chấp nhận độ trễ và đặt Game.IsMouseVisible = falseđể ẩn độ trễ tương đối. Hiển thị con trỏ của riêng bạn trong trò chơi. Nó sẽ chậm hơn 16ms so với con trỏ Windows ẩn - nhưng ai quan tâm? Game thủ đã quen với nó. Và 16ms gần như không thể nhìn thấy bằng mọi cách (đó là lý do tại sao chúng tôi kết xuất mọi thứ ở 60FPS).


Cảm ơn bạn đã giải thích chi tiết về vấn đề này. Nhiều khả năng tôi sẽ chỉ gắn bó với chuột XNA. Sẽ chờ một chút trước khi chấp nhận trong trường hợp ai đó có một số cách giải quyết khác cho nó.
Sunder

Tôi đoán có chấp nhận độ trễ hay không là một câu hỏi nên được trả lời bằng cách chơi.
Zonko
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.