การป้อนข้อมูลที่ขับเคลื่อนด้วยเหตุการณ์ Polling


19

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

ฉันกำหนดโพลเป็น: แต่ละลูปการอัปเดตฉันจะตรวจสอบว่ามีการกดปุ่มใดที่เมาส์อยู่ปุ่มกดจากนั้นทำงานผ่านพวกเขาและดำเนินการตามข้อมูลที่รวบรวมไว้

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

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

แก้ไข

เกมนี้ใช้ Java / OpenGL ดังนั้นจะวางจำหน่ายใน Windows / Mac / Linux ความเป็นไปได้ของการขยายไปยังอุปกรณ์มือถือนั้นอยู่ในระดับต่ำ เกมดังกล่าวเป็นสไตล์ RTS, บุคคลที่สาม 3D

แก้ไข 2

ฉันยังคงไม่มีความสุขกับวิธีที่ฉันใช้สิ่งนี้ แต่สิ่งที่ฉันกำลังมุ่งไปคือการจับกิจกรรมใน UI ของฉันและหากพวกเขาไม่ได้รับการจัดการโดยองค์ประกอบ UI ใด ๆ ของฉันฉันจะส่งต่อเหตุการณ์ไปยัง "โลก" สำหรับการเลือก / การเลือก สิ่งที่ต้องการ:

@Override  
private boolean handleEvent(Event event) {  
    if(hud.handleEvent(event)) {  
        return true;  
    }  
    return WORLD.handleEvent(event);  
}

วิธีนี้ฉันจะไม่ได้รับการคลิกที่รั่วผ่าน UI เพื่อเลือกวัตถุที่อยู่ด้านหลังปุ่มและสิ่งที่ไม่

ปัจจุบันการควบคุมกล้องของฉันยังคงใช้การสำรวจและดูเหมือนว่าจะใช้งานได้ในตอนนี้ แต่ฉันอาจอัปเดตในภายหลัง

ฉันขอขอบคุณคำตอบทั้งหมดขอโทษที่ฉันเลือกได้เพียงหนึ่งข้อเท่านั้น!


6
ฉันไม่แน่ใจใน Java แต่โดยทั่วไปคุณต้องสำรวจความคิดเห็นเสมอ จากนั้นคุณอาจโพสต์เหตุการณ์เมื่อสิ่งต่าง ๆ เปลี่ยนแปลง แต่สิ่งนี้ยังคงอิงกับระบบการลงคะแนนเลือกตั้ง
James

จุดสนใจที่สำคัญที่สุดในความคิดของฉันคือการออกแบบวนรอบเหตุการณ์ที่ไม่มีการวางซ้อนอื่น ๆ นอกเหนือจากการรวบรวมอินพุต ให้ฉันอธิบาย: ระบบปฏิบัติการจะทำการขัดจังหวะอินพุตและจัดการกับมันใน "อินพุตเธรด" ทั่วโลกจากนั้น OS-thread นี้จะเปลี่ยนเส้นทางข้อความไปยังแอปพลิเคชันที่อยู่ในโฟกัสในปัจจุบันและเขียน intel ลงในคิวข้อความ คิวข้อความจะต้องมีการสำรวจโดย PeekMessage หรือ GetMessage วิธีที่เร็วที่สุดในการรับสิ่งนี้คือการใช้ GetMessage และให้ตัวกำหนดตารางเวลาปลุกคุณขึ้นมาจากนั้นคุณสามารถประทับเวลาของข้อความได้อย่างแม่นยำมาก
v.oddou

คำตอบ:


17

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

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


ขอบคุณฉันได้รวมข้อมูลเพิ่มเติมเกี่ยวกับแพลตฟอร์มและวัตถุประสงค์ของเกมแล้ว
MichaelHouse

1
โปรดทราบว่าGetAsyncKeyStateเป็นวิธีที่ง่ายในการใช้การสำรวจบน Win32
Macke

Derp ฉันถามคำถามในความคิดเห็นของ Nate Bross ที่คุณจัดการกับที่นี่ดังนั้นฉันเดาว่าฉันจะปรับแก้ พีซีทุกเครื่องเสนอว่าฮาร์ดแวร์ 1: 1 ถูกขัดจังหวะกับความสัมพันธ์ของเหตุการณ์แป้นพิมพ์ OS และแพลตฟอร์มประเภทใดที่ จำกัด การโพลระดับต่ำ
michael.bartnett

@Macke: บางครั้งโปรแกรมป้องกันไวรัสรายงานโปรแกรมที่ใช้ API นี้เพราะพวกเขาสามารถรับการกดคีย์จากระบบทั่วโลกทั้งหมดดังนั้นการเปิดใช้งานการล็อกคีย์ที่เป็นอันตราย บทความที่ยอดเยี่ยมที่สุดเกี่ยวกับเรื่องนี้บนอินเทอร์เน็ตทั้งหมด (ฉันรู้) คือบทความนี้: securelist.com/analysis/publications/36358/…
v.oddou

7

ฉันไม่เห็นเหตุผลที่คุณไม่สามารถทำได้ทั้งสองอย่างและรับประโยชน์สูงสุดจากทั้งสองโลก

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

mouseInput = GetMouse();
kbInput = GetKeyboard();


// refactor this out to its own method if it makes sense
if menuState == Showing
    if mouseInput.LeftButton == State.Pressed
        LeftButton(mouseInput.X, mouseInput.Y)

// rest of game input code processing

void LeftButton(int x, int y)
{
    // left button event handler
}

ฉันรู้ว่าคุณกำหนดกิจกรรมให้ขัดจังหวะและสิ่งที่ฉันใส่ไว้ที่นี่ไม่ใช่ "อิงตามเหตุการณ์จริง" แต่ฉันไม่เห็นสิ่งที่กล่าวมาข้างต้นไม่ให้คุณเห็นว่าการขัดจังหวะทำให้คุณ - ผู้ใช้ส่วนใหญ่จะไม่สังเกตเห็น เฟรมเดียวหายไปยกเว้นว่าเกมของคุณทำงานที่อัตราเฟรมต่ำมาก


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

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

5

มีสองประเด็นที่แตกต่างกันที่นี่:

  1. คุณอ่านอินพุตของผู้ใช้จากระบบปฏิบัติการ / ฮาร์ดแวร์ได้อย่างไร?

  2. คุณประมวลผลอินพุตของผู้ใช้ในเอ็นจินของคุณอย่างไร?

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

สำหรับการประมวลผลมีตัวเลือกไม่กี่ตัวเลือก:

  • สำหรับการควบคุมการเคลื่อนไหวของผู้เล่น (และรูปแบบที่คล้ายกัน) การสำรวจอาจง่ายกว่าเนื่องจากคุณต้องคำนวณความเร็วใหม่ในแต่ละเฟรม มีโอกาสมากที่ลูปด้านในของคุณจะทำการสำรวจโดย:

    นั่นคือสิ่งที่ชอบ speed += 1 if button.down else -1; clamp(speed, 0, 42);

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

หวังว่ามันจะช่วย

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