ฉันจะรหัสทั้งลูกค้าและเซิร์ฟเวอร์ได้อย่างมีประสิทธิภาพในเวลาเดียวกันได้อย่างไร


15

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

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

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

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


คุณมีตัวเลือกโปรเซสเซอร์ล่วงหน้าหรือไม่ เช่น #ifdef CLIENT <บางโค้ด> #endif นั่นเป็นวิธีง่ายๆในการมีไฟล์คลาสที่แชร์ซึ่งอาจแตกต่างกันระหว่างเซิร์ฟเวอร์และไคลเอนต์และแชร์ส่วนต่างๆ มันค่อนข้างยุ่งนิดหน่อย
William Mariager

ฉันเห็นด้วยกับ MindWorX แม้ว่าการคอมไพล์แบบมีเงื่อนไขเป็นความเจ็บปวดใน Java แต่ก็มีวิธีแก้ไขที่ควรพิจารณา
sam hocevar

1
การรวบรวมแบบมีเงื่อนไขเป็นวิธีที่หยาบคายในการพูดว่า "ฉันไม่ได้มีเวลาในการออกแบบเพียงพอในแพ็คเกจของฉัน" ในความเห็นของฉัน =) "ความยุ่งเหยิงเล็กน้อย" มักจะแปลเป็น หกเดือนต่อมาเมื่อคุณอ่านแม้แต่รหัสของคุณเองและไม่เห็นด้วยกับสิ่งใดนอกจากการทำต้นแบบที่ถูกทิ้ง
Patrick Hughes

คำตอบ:


23

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

หากคุณแยกรหัสการแสดงผลออกจากรหัสลูกค้า / เซิร์ฟเวอร์ของคุณคุณจะได้รับข้อดีสองประการดังนี้:

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

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

5

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


+1 ฉันมักจะเห็นด้วยกับสิ่งนี้ หากเซิร์ฟเวอร์กำลังเรียกใช้ไคลเอนต์ใด ๆ ก็ควรทำเช่นนั้นเป็นกระบวนการที่แยกต่างหาก
วิศวกร

5

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

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

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