C # / XNA รับตำแหน่งเมาส์ของฮาร์ดแวร์


10

ฉันใช้ C # และพยายามรับตำแหน่งเมาส์ฮาร์ดแวร์ สิ่งแรกที่ฉันลองคือฟังก์ชั่น XNA ง่าย ๆ ที่ใช้งานง่าย

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

หลังจากนั้นฉันก็ทำการวาดเมาส์เช่นกันและเปรียบเทียบกับเมาส์ฮาร์ดแวร์ของ windows แล้วเมาส์ใหม่ที่มีพิกัด xna ที่ระบุนี้คือ "หยุดหย่อน" โดยที่ฉันหมายความว่ามันอยู่เบื้องหลังโดยไม่กี่เฟรม ตัวอย่างเช่นหากเกมทำงานที่ 600 fps คำสาปมันจะตอบสนอง แต่ที่ความล่าช้าของเมาส์ซอฟต์แวร์ 60 fps ไม่เป็นที่ยอมรับอีกต่อไป ดังนั้นฉันจึงลองใช้สิ่งที่ฉันคิดว่าเป็นเมาส์ฮาร์ดแวร์

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

แต่ผลลัพธ์ก็เหมือนกันทุกประการ ฉันยังลองรับเคอร์เซอร์ของ Windows และนั่นก็เป็นจุดสิ้นสุดเช่นกัน - ใช้งานได้ แต่มีความล่าช้าเท่าเดิม ล้อเล่นกับฟังก์ชัน xna:

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

เปลี่ยนเวลาหน่วงด้วยเหตุผลที่ค่อนข้างชัดเจน แต่บรรทัดล่างคือไม่ว่ามันจะยังคงอยู่หลังเมาส์ Windows เริ่มต้น ฉันเคยเห็นในบางเกมว่าพวกเขามีตัวเลือกสำหรับเมาส์ที่ใช้ฮาร์ดแวร์และในเกมอื่น ๆ (ฉันคิดว่า) เป็นค่าเริ่มต้นแล้ว ทุกคนสามารถเป็นผู้นำในการทำสิ่งนั้นได้อย่างไร


2
ฉันไม่คิดว่าMouse.GetState()จะพัง คุณแน่ใจหรือว่าคุณได้ตำแหน่งเม้าส์ในเฟรมเดียวกับที่คุณวาด นอกจากนี้โปรดจำไว้ว่าเคอร์เซอร์ Windows มีการเปิดใช้งานการเร่งความเร็ว / การชะลอความเร็วดังนั้นจึงรู้สึกตอบสนองได้ดีขึ้น หากคุณต้องการเข้าใกล้ฮาร์ดแวร์มากขึ้นคุณควรกด DirectInput ซึ่งจะทำให้เดลต้าเคลื่อนที่แทนตำแหน่งเมาส์แน่นอน แต่ฉันเชื่อว่าMouse.GetState()ยังคงเป็นวิธีที่ถูกต้องใน XNA
Panda Pyjama

ไม่Mouse.GetState()ไม่เสียและตราบใดที่IsFixedTimeStep == trueผู้คนไม่ควรเห็นความล่าช้าเว้นแต่จะเปรียบเทียบโดยตรงกับเมาส์หน้าต่างที่มองเห็นได้ อย่างไรก็ตามการตั้งค่า IsFixedTimeStep เป็น false ที่ framerate ต่ำกว่าจะปรากฏแก่ทุกคน เกี่ยวกับการป้อนข้อมูลโดยตรงฉันพิจารณาว่า posability (วิธีสุดท้าย)
Sunder

ไม่แน่ใจว่าเป็นสิ่งที่คุณต้องการหรือไม่ แต่สิ่งที่เกี่ยวกับการเปลี่ยนเคอร์เซอร์สไปรท์ในขณะที่อยู่ในหน้าต่างของคุณแล้วทำให้มองเห็นได้ตลอดเวลา
William Mariager

นั่นคือสิ่งที่ฉันทำสิ่งที่ฉันไม่ต้องการที่จะแสดงเพียง แต่รู้ตำแหน่งที่แน่นอนของเมาส์เช่นกัน แต่สิ่งที่ฉันได้รับนั้นเล็กน้อยตามที่ควรจะเป็น
Sunder

คำตอบ:


17

สิ่งที่คุณเห็นไม่ใช่ความล่าช้าในการป้อนข้อมูล

เพื่อให้ได้ตำแหน่งของเคอร์เซอร์ใน Windows คุณสามารถใช้WM_MOUSEMOVEหรือGetCursorPosหรือพวกเขาทั้งคู่ระบุตำแหน่งของเคอร์เซอร์หลังจาก Windows ประมวลผลแล้วใช้สิ่งต่าง ๆ เช่นการเร่งความเร็ว นี่คือตำแหน่งเคอร์เซอร์ที่ Windows ใช้รวมถึงการวาด และเกือบทุกสิ่งที่คุณต้องการใช้ด้วย

นี่คือสิ่งที่ใช้ XNA โดยเฉพาะGetCursorPos( MSDN ) ซึ่งหมายความว่าเมื่อคุณโทรMouse.GetStateคุณจะได้รับตำแหน่งที่แท้จริงของเคอร์เซอร์เมื่อ Windows เห็น - โดยไม่มีการหน่วงเวลาเป็นศูนย์

ตอนนี้คุณสามารถใช้WM_INPUT(หรือ DirectInput ได้แม้ว่าจะเลิกใช้แล้ว) สิ่งนี้จะให้ข้อมูลตัวชี้แบบดิบแก่คุณ นี่คือก่อนที่ Windows จะสามารถใช้สิ่งต่าง ๆ เช่นการเร่งความเร็วและโดยปกติจะไม่ใช่สิ่งที่คุณต้องการ

สิ่งที่คุณเห็นคือความล่าช้าในการส่งออก

นี่เป็นเพราะ " เคอร์เซอร์ฮาร์ดแวร์ " นี่คือผีสางขนาดเล็กที่ได้รับการวาดผ่านหน้าจอโดย GPU ที่มากในตอนท้ายของท่อ และฉันหมายถึงจุดสิ้นสุด มันมาหลังจากบัฟเฟอร์เฟรม - มันจะถูกแทรกเข้าไปในกระแสข้อมูลเมื่อภาพถูกส่งไปยังจอภาพ เหตุผลที่มันตอบสนองอย่างรวดเร็วนั้นเป็นเพราะตำแหน่งถูกกำหนดโดยการตั้งค่าการลงทะเบียน GPU โดยตรง ไม่มีการรอคอยในท่อเลย

ในทางกลับกันเกมของคุณต้องผ่าน GPU ไปแล้ว สิ่งนี้จะเพิ่มความล่าช้ามากมายด้วยตัวเอง ปัญหาที่สำคัญที่สุดสำหรับคุณคือการบัฟเฟอร์สองครั้งซึ่ง (ฉันค่อนข้างแน่ใจ) คุณไม่สามารถปิดได้ใน XNA 4 คุณไม่ได้วาดโดยตรงไปที่บัฟเฟอร์เฟรม - คุณวาดไปที่ backbuffer ซึ่งได้รับการนำเสนอทุก ๆ ~ 16ms (ที่ 60FPS) นั่นหมายความว่าคุณกำลังดูอย่างน้อยประมาณ 16ms ระหว่างการรับผลลัพธ์จากMouse.GetStateการรับบางสิ่งจากผลลัพธ์นั้นบนหน้าจอ อาจนานกว่านั้น แน่นอนว่าช้ากว่าเคอร์เซอร์ฮาร์ดแวร์มาก

ดังนั้นทางออกคืออะไร?

หนึ่งคือการใช้SetCursor( MSDN ) เพื่อเปลี่ยนภาพที่แสดงโดยเคอร์เซอร์ฮาร์ดแวร์เพื่อภาพที่เหมาะสมกับเกมของคุณ (หรือเพียงแค่อยู่กับเคอร์เซอร์ Windows)

และอีกอัน (ง่ายกว่า) คือยอมรับความล่าช้าและตั้งค่าGame.IsMouseVisible = falseให้ซ่อนความล่าช้าสัมพัทธ์ แสดงเคอร์เซอร์ของคุณเองในเกม ช้ากว่าเคอร์เซอร์ Windows ที่ซ่อนอยู่ 16ms แต่ใครจะสนใจล่ะ นักเล่นเกมคุ้นเคยกับมัน และ 16ms นั้นแทบมองไม่เห็นเลย (นี่คือเหตุผลที่เราแสดงสิ่งต่าง ๆ ที่ 60FPS)


ขอขอบคุณสำหรับคำอธิบายโดยละเอียดเกี่ยวกับเรื่องนี้ เป็นไปได้มากว่าฉันจะใช้ XNA mouse จะรอสักครู่ก่อนที่จะยอมรับในกรณีที่บางคนมีวิธีแก้ไขเพิ่มเติมบางประการ
Sunder

ฉันเดาว่ายอมรับความล่าช้าหรือไม่เป็นคำถามที่ควรตอบโดยการทดสอบ
Zonko
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.