การเขียนโปรแกรมเกม Java 2D: แนวทางที่แตกต่างกันในการสร้างเกมลูป


10

ฉันยังใหม่กับการเขียนโปรแกรมเกม Java แต่ยิ่งฉันอ่านมากขึ้นฉันก็สับสนเพราะฉันได้เห็นวิธีการที่แตกต่างกันในการทำลูปเกม: 1. วิธีการมาตรฐานที่ใช้คลาส Timer (ดูเหมือนจะน้อยกว่า) แม่นยำ) 2. วิธีที่แม่นยำยิ่งขึ้นที่ใช้ System.nanoTime 3. วิธีการง่ายๆที่ใช้ schedAtFixedRate

โดยทั่วไปควรเลือกข้อใดข้อหนึ่งและข้อดี / ข้อเสียของแต่ละวิธีอยู่ที่ใด ขอบคุณล่วงหน้าสำหรับข้อมูลใด ๆ

คำตอบ:


7

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

ใช้http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime%28%29คุณสามารถสำรวจความคิดเห็นในเวลาที่ผ่านไปได้ โดยทั่วไป ...

public static void main(String [ ] args)
{
    long current_frame_time = system.nanoTime();
    long last_frame_time = current_frame_time;

    while(gameIsRunning)
    {
        last_frame_time = current_frame_time;
        current_frame_time = system.nanoTime();

        long timeTaken = current_frame_time - last_frame_time;

        //update and render game here
    }
}

วิธีการขั้นพื้นฐานนี้สามารถปรับปรุงให้ดีขึ้นเช่นhttp://www.koonsolo.com/news/dewitters-gameloop/และhttp://gafferongames.com/game-physics/fix-your-timestep/

หรือคุณสามารถสร้างตัวจับเวลาและตั้งค่าตัวจับเวลานี้เพื่อเรียกใช้การอัปเดตและการแสดงผลของคุณทุก ๆ X มิลลิวินาที แต่มีข้อเสียบางประการในการสร้างเกมสล็อตเช่นนั้น

อ้างอิงจากhttp://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html : "การตอบสนองต่อวัตถุตัวจับเวลาแต่ละตัวเป็นเธรดพื้นหลังเดียวที่ใช้ในการเรียกใช้ตัวจับเวลาทั้งหมด ภารกิจตามลำดับงานตัวจับเวลาควรเสร็จอย่างรวดเร็วหากงานตัวจับเวลาใช้เวลามากเกินไปในการดำเนินการมันจะ "hogs" เธรดการเรียกใช้งานตัวจับเวลาซึ่งจะทำให้ล่าช้าในการประมวลผลงานที่ตามมาซึ่งอาจ "มัด" และ ดำเนินการอย่างต่อเนื่องอย่างรวดเร็วเมื่อ (และถ้า) งานที่กระทำผิดในที่สุดก็เสร็จสมบูรณ์ "

ตามhttp://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html#scheduleAtFixedRate%28java.util.TimerTask,%20java.util.Date,%20long%29 : " ในการประมวลผลอัตราตายตัวการดำเนินการแต่ละครั้งจะถูกกำหนดสัมพันธ์กับเวลาดำเนินการตามกำหนดการของการดำเนินการเริ่มต้นหากการดำเนินการล่าช้าด้วยเหตุผลใด ๆ (เช่นการรวบรวมขยะหรือกิจกรรมพื้นหลังอื่น ๆ ) การประหารชีวิตสองครั้งขึ้นไปจะเกิดขึ้นอย่างรวดเร็ว ถึง "catch up." ในระยะยาวความถี่ของการดำเนินการจะเป็นส่วนกลับของช่วงเวลาที่ระบุอย่างแน่นอน (สมมติว่านาฬิกาของระบบอ้างอิง Object.wait (ยาว) มีความแม่นยำ) "

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

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


คำถามเกี่ยวกับลูปของเกมดังนั้นข้อมูล awt / swing นั้นไม่ได้อยู่ในหัวข้อ อย่างไรก็ตามดูเหมือนว่าข้อมูลนั้นมีความเกี่ยวข้องเนื่องจากมีความไม่เกี่ยวข้องและสับสนในคำถามดังนั้นฉันจึงลบออก
jhocking

ฉันปรับคำตอบเพื่อให้สอดคล้องกับการเปลี่ยนแปลงของคำถาม
Exilyth

7

ฉันจะไม่ใส่ลูปหลักในตัวจับเวลา แต่ฉันจะทำลูป 'ในขณะที่ประมวลผลทุกเฟรมแล้วใช้ฟังก์ชันการจับเวลาแบบเรียงลำดับ (ดูเหมือนใน Java ที่จะเป็น System.nanoTime) เพื่อคำนวณเวลาที่ผ่านไปนับตั้งแต่เฟรมสุดท้าย / การทำซ้ำครั้งสุดท้ายของ ห่วง

บางภาษามีข้อยกเว้นที่นี่ (เช่น JavaScript, ActionScript) เนื่องจากภาษาเหล่านั้นทำงานภายในสภาพแวดล้อมที่มีการวนรอบหลักโดยนัยที่จะเชื่อมโยง (เช่นเบราว์เซอร์, Flash Player) แต่ข้อยกเว้นนั้นไม่มีผลกับ Java

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