การจัดการระบบป้อนข้อมูลด้วยแป้นพิมพ์


13

หมายเหตุ: ฉันต้องสำรวจแทนที่จะโทรกลับเนื่องจากข้อ จำกัด API (SFML) ฉันยังขอโทษที่ไม่มีชื่อ 'ที่เหมาะสม'

ฉันคิดว่าฉันมีสองคำถามที่นี่; วิธีการลงทะเบียนข้อมูลที่ฉันได้รับและจะทำอย่างไรกับมัน

การจัดการอินพุต

ฉันกำลังพูดถึงหลังจากที่คุณได้ลงทะเบียนว่ามีการกดแป้น 'A' ตัวอย่างเช่นและวิธีการทำจากที่นั่น

ฉันเคยเห็นชุดแป้นพิมพ์ทั้งหมดเช่น:

bool keyboard[256]; //And each input loop check the state of every key on the keyboard

แต่ดูเหมือนว่าจะไม่มีประสิทธิภาพ ไม่เพียง แต่คุณจะมีการเชื่อมต่อปุ่ม 'A' ถึง 'ผู้เล่นที่เลื่อนไปทางซ้าย' แต่มันจะตรวจสอบทุก ๆ 30-60 ครั้งต่อวินาที

ฉันลองระบบอื่นซึ่งเพิ่งค้นหากุญแจที่ต้องการ

std::map< unsigned char, Key> keyMap; //Key stores the keycode, and whether it's been pressed. Then, I declare a load of const unsigned char called 'Quit' or 'PlayerLeft'.
input->BindKey(Keys::PlayerLeft, KeyCode::A); //so now you can check if PlayerLeft, rather than if A.

อย่างไรก็ตามปัญหานี้คือตอนนี้ฉันไม่สามารถพิมพ์ชื่อได้โดยไม่ต้องผูกทุกปุ่มเดียว

จากนั้นฉันมีปัญหาที่สองซึ่งฉันไม่สามารถคิดวิธีแก้ปัญหาที่ดีสำหรับ:

กำลังส่งอินพุต

ตอนนี้ฉันรู้แล้วว่ามีการกดแป้น A หรือว่าผู้เล่นซ้ายเป็นจริง แต่ฉันจะไปจากที่นี่ได้อย่างไร

ฉันคิดเกี่ยวกับการตรวจสอบเพียงแค่ if(input->IsKeyDown(Key::PlayerLeft) { player.MoveLeft(); }
คู่นี้นำเข้าข้อมูลอย่างมากต่อเอนทิตีและฉันคิดว่ามันค่อนข้างยุ่ง ฉันต้องการให้ผู้เล่นจัดการกับการเคลื่อนไหวของตัวเองเมื่อได้รับการอัปเดต ฉันคิดว่าระบบเหตุการณ์บางอย่างสามารถทำงานได้ แต่ฉันไม่รู้ว่าจะไปได้อย่างไร (ฉันได้ยินสัญญาณและช่องเสียบนั้นดีสำหรับงานประเภทนี้ แต่เห็นได้ชัดว่าช้ามากและฉันไม่สามารถเห็นได้ว่ามันจะเข้ากันได้อย่างไร)

ขอบคุณ

คำตอบ:


7

สิ่งที่ฉันทำคือใช้รูปแบบผู้สังเกตการณ์และมีคลาสอินพุตที่เก็บรักษารายการของการเรียกกลับหรือวัตถุการจัดการอินพุต วัตถุอื่น ๆ สามารถลงทะเบียนตัวเองด้วยระบบอินพุตเพื่อรับการแจ้งเตือนเมื่อมีบางสิ่งเกิดขึ้น มีการโทรกลับหลายประเภทที่คุณสามารถลงทะเบียนได้โดยขึ้นอยู่กับประเภทของผู้สังเกตการณ์เหตุการณ์อินพุตที่ต้องการรับการแจ้งเตือน สิ่งนี้อาจอยู่ในระดับต่ำเช่น 'key x is down / up' หรือมากกว่าเฉพาะเกมเช่น 'เหตุการณ์กระโดด / ยิง / การเคลื่อนไหวที่เกิดขึ้น'

โดยทั่วไปแล้ววัตถุเกมมีองค์ประกอบการจัดการอินพุตที่รับผิดชอบในการลงทะเบียนตัวเองกับคลาสอินพุตและให้วิธีการจัดการกับเหตุการณ์ที่เป็นที่สนใจสำหรับการเคลื่อนไหวฉันมีองค์ประกอบผู้เสนอญัตติอินพุตที่มีวิธีการย้าย (x, y) มันลงทะเบียนตัวเองด้วยระบบอินพุตและได้รับการแจ้งเตือนเกี่ยวกับเหตุการณ์การเคลื่อนไหว (โดยที่ x และ y จะเป็น -1 และ 0 เพื่อบ่งบอกถึงการเคลื่อนย้ายไปทางซ้าย) ส่วนประกอบผู้เสนอญัตติแล้วเปลี่ยนพิกัดวัตถุเกมหลักของมันตามทิศทางการเคลื่อนที่

ฉันไม่รู้ว่านี่เป็นวิธีแก้ปัญหาที่ดีหรือไม่ โดยเฉพาะอย่างยิ่งช่วยให้ฉันมีระบบอินพุตที่แตกต่างกันซึ่งแมปกับเหตุการณ์เกมตรรกะเดียวกันเพื่อให้ปุ่ม gamepad x และพื้นที่คีย์บอร์ดทั้งคู่สร้างเหตุการณ์กระโดดเช่น (มันซับซ้อนกว่านั้นเล็กน้อยทำให้ผู้ใช้สามารถกำหนดคีย์ใหม่ได้ แมป)


สิ่งนี้ทำให้ฉันสนใจ องค์ประกอบอินพุตจะลงทะเบียนตัวเองสำหรับเหตุการณ์บางอย่าง (เช่น playerInput รีจิสเตอร์ 'ซ้าย', 'ถูกต้อง' ฯลฯ ) หรือส่วนประกอบอินพุตที่ลงทะเบียนจะได้รับข้อความทั้งหมดหรือไม่
The Duck Communist

มันขึ้นอยู่กับความต้องการของคุณและวิธีการใช้งาน ในกรณีของฉันผู้ฟังลงทะเบียนตัวเองสำหรับเหตุการณ์เฉพาะและใช้อินเทอร์เฟซตัวจัดการอินพุตที่เหมาะสม การให้ทุกองค์ประกอบอินพุตได้รับข้อความทั้งหมดควรใช้งานได้ แต่รูปแบบข้อความต้องกว้างกว่าที่ฉันมี
Firas Assaad

6

ฉันคิดว่าการสนทนาของ OP กำลังรวมเรื่องต่าง ๆ เข้าด้วยกันและปัญหาก็สามารถทำให้ง่ายขึ้นอย่างมากโดยทำให้มันแตกหัก

คำแนะนำของฉัน:

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

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

ถัดไปสร้างวิธีการสร้างการแมปของคีย์กับการกระทำ คุณต้องการทำสิ่งนี้สองสามครั้ง หนึ่งครั้งสำหรับสิ่งต่าง ๆ ของ UI (และสอบถามการแมปของ Windows เพราะคุณไม่สามารถสันนิษฐานได้ว่า scancode เมื่อคุณกด 'A' จะให้ A บนคอมพิวเตอร์ของผู้ใช้) อีกรายการสำหรับ "โหมด" ในแต่ละเกม นี่คือการแม็พของรหัสการกระทำ คุณสามารถทำได้สองวิธีวิธีหนึ่งคือการรักษา enum ที่ใช้โดยระบบรับอีกวิธีหนึ่งคือตัวชี้ฟังก์ชั่นที่บ่งชี้ว่าฟังก์ชั่นที่จะเรียกว่าการเปลี่ยนแปลงสถานะ อาจเป็นลูกผสมของทั้งสองขึ้นอยู่กับเป้าหมายและความต้องการของคุณ ด้วย "โหมด" เหล่านี้คุณสามารถกดและวางลงบนสแต็กโหมดคอนโทรลเลอร์ด้วยแฟล็กที่อนุญาตให้อินพุตถูกข้ามไปเรื่อย ๆ หรืออะไรก็ตาม

ในที่สุดจัดการกับการกระทำที่สำคัญเหล่านั้นอย่างใด สำหรับการเคลื่อนไหวคุณอาจต้องการทำอะไรที่ยุ่งยากแปล 'W' ลงเพื่อหมายถึง "ก้าวไปข้างหน้า" แต่มันไม่จำเป็นต้องเป็นวิธีแก้ปัญหาแบบไบนารี คุณสามารถมี "W is down" หมายถึง "เพิ่มความเร็วด้วย X จนกระทั่งสูงสุด Y" และ "W is up" เป็น "ลดความเร็วโดย Z จนกว่าจะถึงศูนย์" โดยทั่วไปคุณต้องการให้ "คอนโทรลเลอร์การจัดการอินเตอร์เฟสในระบบเกม" ค่อนข้างแคบ ทำการแปลคีย์ทั้งหมดในที่เดียวจากนั้นใช้ผลลัพธ์ของที่อื่น ๆ นี่คือตรงกันข้ามกับการตรวจสอบโดยตรงเพื่อดูว่ามีการกด Spacebar ที่ใดก็ได้ในรหัสเพราะถ้าอยู่ในจุดสุ่มมันอาจจะโดนเวลาสุ่มเมื่อคุณไม่ต้องการและคุณแค่สวม ' ไม่ต้องการจัดการกับสิ่งนั้น ...

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


คุณไม่คิดว่ามันเป็นเรื่องสกปรกที่จะผูกเหตุการณ์กับเฟรมภาพหรือไม่? ฉันคิดว่าควรแยกจากกัน
Jo So

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

แท้จริง; ไม่มีเหตุผลว่าทำไมการสำรวจความคิดเห็นของแป้นพิมพ์ (หรืออุปกรณ์อินพุตอื่น ๆ ) ไม่สามารถทำงานในอัตราที่แตกต่างจากจอแสดงผล แน่นอนถ้าคุณสำรวจข้อมูลที่ 100Hz คุณสามารถมอบประสบการณ์การควบคุมผู้ใช้ที่สอดคล้องกันโดยไม่คำนึงถึงความถี่ในการอัปเดตฮาร์ดแวร์วิดีโอ คุณจะต้องฉลาดกว่านี้เล็กน้อยเกี่ยวกับวิธีการจัดการข้อมูลของคุณ (เกี่ยวกับการล็อค ฯลฯ ) แต่มันจะทำให้สิ่งต่าง ๆ เช่นท่าทางสัมผัสง่ายขึ้นเพื่อให้สอดคล้องกัน
dash-tom-bang

3

ใน SFML คุณมีคีย์ตามลำดับที่ถูกกดด้วยประเภทเหตุการณ์ KeyPressed คุณประมวลผลแต่ละคีย์ในขณะที่ (getNextEvent ())

ดังนั้นหากปุ่มกดอยู่ใน Key-> Action map ของคุณให้เรียกใช้การกระทำที่เกี่ยวข้องและหากไม่เป็นเช่นนั้นให้ส่งต่อไปยังวิดเจ็ต / สิ่งที่อาจจำเป็นต้องใช้

เกี่ยวกับคำถามที่สองของคุณฉันขอแนะนำให้คุณทำเช่นนี้เพราะจะทำให้ปรับการเล่นเกมของคุณง่ายขึ้น หากคุณใช้สัญญาณหรือเช่นนั้นคุณจะต้องสร้างช่องสำหรับ "RunKeyDown" และอีกช่องสำหรับ "JumpKeySlot" แต่จะเกิดอะไรขึ้นถ้าในเกมของคุณมีการดำเนินการพิเศษเมื่อกดทั้งคู่?

หากคุณต้องการตกแต่งการป้อนข้อมูลและเอนทิตีคุณสามารถทำให้สถานะของคุณ (RunKey = true, FireKey = false, ... ) และส่งไปยังผู้เล่นเหมือนกับที่คุณส่งเหตุการณ์อื่น ๆ ไปยัง AIs ของคุณ


ฉันไม่ได้จัดการเหตุการณ์แป้นพิมพ์ด้วย sf :: Event ค่อนข้าง sf :: Input เพราะมันตรวจจับ IIRC แบบเรียลไทม์ ฉันพยายามทำให้มันเป็น API ที่ไม่เชื่อเรื่องพระเจ้ามากที่สุด : P (คำถามคือ)
The คอมมิวนิสต์ Duck

1
แต่ฉันคิดว่าประเด็นที่ Calvin1602 กำลังทำอยู่ก็คือคำแถลงเดิมของคุณในคำถามที่ว่า "ฉันต้องสำรวจความคิดเห็นมากกว่าที่จะโทรกลับเพราะข้อ จำกัด API (SFML)" ไม่ใช่ความจริง คุณมีกิจกรรมเพื่อให้คุณสามารถโทรกลับเมื่อคุณจัดการกับเหตุการณ์
Kylotan

3

การแก้ไขที่ถูกต้องมักเป็นการรวมสองวิธีที่คุณพูดถึง:

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

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

ดังนั้นคุณต้องการใช้การเลือกโพลสำหรับการป้อนข้อมูลการเล่นเกมและการจัดการเหตุการณ์สำหรับอินพุตการพิมพ์ชื่อ (หรือการสำรวจแป้นพิมพ์ทั้งหมดหากการจัดการเหตุการณ์ไม่พร้อมใช้งาน)


1

ฉันชอบคำตอบของเส้นประ - ทอม - ปังมากมันเน้นบางด้านที่คุณควรจำไว้เมื่อออกแบบระบบอินพุต

ฉันต้องการที่จะเพิ่มการกวดวิชาเล็ก ๆ น้อย ๆ ที่ฉันได้พบซึ่งไปในทิศทางเดียวกัน (รวมถึงบริบทการป้อนข้อมูล 3 ชั้น, ... ):

http://www.gamedev.net/blog/355/entry-2250186-designing-a-robust-input-handling-system-for-games/

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