ใช้อินสแตนซ์หรือคลาสสำหรับทรัพยากรเกม (ไม้เหล็กทอง)


31

ดังนั้นฉันจึงสร้างเกมที่คุณสามารถส่งเรือไปยังสถานที่ต่างๆเพื่อขายหรือซื้อทรัพยากรเช่นไม้เหล็กทองคำ ฯลฯ

ตอนนี้ฉันกำลังสงสัยว่าจะสร้างทรัพยากรในเกมได้อย่างไร ฉันมากับ 2 ตัวเลือก

  1. สร้างคลาสสำหรับแต่ละทรัพยากร:

    public class ResourceBase {
        private int value;
        // other base properties
    }
    
    public class Gold : ResourceBase {
         public Gold {
             this.value = 40 // or whatever
         }
    }
    
  2. สร้างอินสแตนซ์ของคลาสทรัพยากร

    public class Resource {
        string name;
        int value;
    
        public Resource(string name, int value) {
            this.name = name;
            this.value = value;
         }
     }
    
    // later on...
    
    Resource gold = new Resource("Gold",40);
    

ด้วยตัวเลือกที่สองเป็นไปได้ที่จะเติมทรัพยากรของเกมจากไฟล์ resources.json ฉันชอบโครงสร้างนั้น

ยินดีต้อนรับแนวคิด / รูปแบบการออกแบบ / โครงสร้างใหม่!

แก้ไข:มันเหมือนกับแอปสหายของ Assassins Creed Black Flag ดูแถบทรัพยากรในภาพด้านล่าง

แก้ไข 2:ฉันได้ทำบางวิจัยเพิ่มเติมเกี่ยวกับ "โหลดรายการ / ทรัพยากรจากไฟล์ JSON" และพบว่าบล็อกนี้: พลังของ JSON ในการพัฒนาเกม - รายการ มันแสดงให้เห็นถึงสิ่งที่ดีที่สุดของตัวเลือกที่ 1 และตัวเลือกที่ 2 คุณยังสามารถเพิ่มฟังก์ชันการทำงานให้กับแต่ละทรัพยากร :)

ป้อนคำอธิบายรูปภาพที่นี่


1
Minecraft มีคลาสที่แยกต่างหากสำหรับแต่ละทรัพยากร (ไม่ใช่ที่คุณควรจะเป็น)
MCMastery

@MCMastery ohh เป็น minecraft โอเพนซอร์สหรือไม่ ฉันต้องการดูโครงสร้างนั้น และขอบคุณสำหรับการกล่าวถึง
MDijkstra

1
มันไม่ใช่ แต่มันถูกทำให้สับสนอยู่เสมอสำหรับเซิร์ฟเวอร์ ... ดูgithub.com/Wolf-in-a-bukkit/Craftbukkit/tree/master/src/main/
MCMastery

12
อย่าใช้สายเช่นนั้น ทุกอย่างง่ายเกินกว่าที่จะพิมพ์ "ทองคำ" ด้วย "glod" หรือสิ่งที่คล้ายกันได้ง่ายเกินไป ใช้enumแทน
Nolonar

Minecraft นั้นไม่ได้เป็นโอเพ่นซอร์สทางเทคนิคแต่มันก็เกือบจะถูกย่อยสลายและ deobfuscated คุณไม่ควรหาแหล่ง deobfuscated ที่ใดก็ได้บนอินเทอร์เน็ต แต่คุณสามารถดาวน์โหลดและเรียกใช้กระบวนการเพื่อทำจากfiles.minecraftforge.net (การดาวน์โหลด MDK เป็นสิ่งที่คุณต้องการ)
JamEngulfer

คำตอบ:


51

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


แก้ไข:

เพื่ออธิบายเพิ่มเติมเกี่ยวกับสาเหตุที่เป็นไปตามแนวปฏิบัติทั่วไปแม้ว่าคุณจะมั่นใจได้ 100% คุณค่าบางอย่างจะไม่เปลี่ยนแปลง

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

เมื่อปล่อยเกมบนคอนโซลเหล่านี้มักจะต้องผ่านกระบวนการตรวจสอบซึ่งผู้ผลิตคอนโซลควบคุมคุณภาพของตัวเองจะทดสอบเกมเล่นมันค้นหาปัญหา ฯลฯ นี่เป็นข้อบังคับและค่าใช้จ่ายเงินเป็นจำนวนมาก ฉันคิดว่าฉันเคยอ่านว่าการเปิดตัวอาจมีค่าใช้จ่าย 30,000-50,000 เหรียญสหรัฐสำหรับการรับรองเพียงอย่างเดียว

ทีนี้ลองนึกดูว่าคุณกำลังผลักดันเกมของคุณให้เป็นอิสระโดยจ่ายเงิน 30,000 เหรียญแล้วรอ และทันใดนั้นคุณสังเกตเห็นว่าคุณค่าของเกมบางส่วนของคุณเสียอย่างแท้จริง สมมติว่าคุณสามารถซื้อแท่งเหล็กราคา 50 ทองและขายได้ 55 ทอง

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

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

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


6
+1 สำหรับ DDD สิ่งนี้เหมาะสมมากสำหรับสิ่งต่างๆเช่นทรัพยากร
Kromster พูดว่าสนับสนุน Monica

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

2
ฉันไม่เห็นว่าคุณจะต้องเขียนโค้ดใหม่ด้วยวิธีแรกอย่างไร สิ่งที่คุณต้องทำคือเพิ่มชั้นเรียน (ยกเว้นกรณีที่ฉันขาดอะไรไป)
SirPython

4
และนี่คือความแตกต่างระหว่างรหัส Oriented Object และรหัส Obsessed Object เพียงเพราะคุณสามารถสร้างลำดับชั้นวัตถุไม่ได้หมายความว่าคุณควร
corsiKa

2
@ AgustínLadoถ้าฉันมีเงินดอลลาร์สำหรับลูกค้าทุกครั้งที่พูดว่า "สิ่งนี้จะไม่เปลี่ยนแปลง" และมันก็เปลี่ยนไปฉันสามารถพาเราทั้งสองไปที่ร้านอาหารที่เหมาะสมสำหรับมื้อค่ำ (แม้ว่าเราจะต้องอ่านเคล็ดลับเล็กน้อยดังนั้นอาจจะ เพียงร้านอาหารธรรมดา ... ยังคงมีเวลาพอสำหรับอาหารค่ำสำหรับสองคนแม้ว่า.)
corsiKa

29

กฎง่ายๆคือคุณใช้คลาสที่แตกต่างกันเมื่อวัตถุต้องการรหัสที่แตกต่างกันและอินสแตนซ์ของคลาสเดียวกันเมื่อวัตถุต้องการค่าที่แตกต่างกันเท่านั้น

เมื่อทรัพยากรมีกลไกเกมที่แตกต่างกันซึ่งเป็นเอกลักษณ์ของพวกเขามันอาจสมเหตุสมผลที่จะเป็นตัวแทนของพวกมันด้วยคลาส ตัวอย่างเช่นเมื่อคุณมีพลูโตเนียมซึ่งมีเวลาครึ่งชีวิตและกระต่ายซึ่งกำเนิดตามลำดับ Fibonacciแล้วมันอาจทำให้ความรู้สึกที่มีฐานชั้นResourceที่มีวิธีการUpdateดำเนินการเป็นไม่มี-op และสองชั้นเรียนมาHalfLifeResourceและSelfGrowingResourceที่ แทนที่วิธีการนั้นเพื่อลด / เพิ่มมูลค่า (และอาจรวมถึงตรรกะเพื่อควบคุมสิ่งที่เกิดขึ้นเมื่อคุณจัดเก็บทั้งสองอยู่ติดกัน)

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


ขอบคุณ @Phillipp สำหรับคำตอบของคุณ นี่คือสิ่งที่ฉันคิด แต่ทรัพยากรจะไม่เปลี่ยนแปลงอย่างแท้จริงในแง่ของคุณสมบัติ / วิธีการดังนั้นฉันจะไปกับตัวเลือก 2 สำหรับตอนนี้
MDijkstra

14

ฉันต้องการเพิ่มมีสองตัวเลือกพิเศษ:
ส่วนต่อประสาน:คุณสามารถพิจารณาได้หากคลาสทรัพยากรจะเป็น "พื้นที่เก็บข้อมูล" สำหรับจำนวนเต็ม 5 ตัวและแต่ละเอนทิตีจะมีตรรกะที่แตกต่างกันเกี่ยวกับทรัพยากร (เช่นผู้เล่นใช้ / ยกเค้า ทรัพยากร). ในกรณีนี้คุณอาจไม่ต้องการคลาสเลย - คุณเพียงแค่ต้องการเปิดเผยว่าเอนทิตีบางอย่างมีตัวแปรที่คนอื่นสามารถโต้ตอบด้วย:

interface IHasResources {
  int Gold { get; set; }
  int Wood { get; set; }
  int Cloth { get; set; }
  // ....
}

class Player : IHasResources { }
class City: IHasResources { }

นอกจากนี้ยังมีส่วนต่าง ๆ ที่คุณสามารถปล้นเมืองด้วยรหัสเดียวกับที่คุณปล้นกองยานศัตรูการส่งเสริมการใช้รหัสซ้ำ
ข้อเสียคือการใช้อินเทอร์เฟซดังกล่าวสามารถพิสูจน์ได้ว่าน่าเบื่อถ้าหลายคลาสใช้งานมันดังนั้นคุณอาจจะจบลงด้วยการใช้อินเทอร์เฟซ แต่ไม่ใช่สำหรับปัญหาดั้งเดิมแก้ไขด้วยตัวเลือก 1 หรือ 2:

interface IHasResources { 
   IEnumerable<Resource> Resources { get; }
}

อินสแตนซ์ (with enum):ในบางกรณีมันจะเป็นที่พึงปรารถนาที่จะใช้ enum แทนสตริงเมื่อกำหนดประเภททรัพยากร:

enum Resource {
   Gold, Wood, Cloth, //...
}

class ResourceStorage {
   public Resource ResourceType { get; set; }
   public int Value { get; set; }
}

สิ่งนี้จะให้ "ความปลอดภัย" เล็กน้อยเนื่องจาก IDE ของคุณจะให้รายการทรัพยากรที่ถูกต้องทั้งหมดเมื่อกำหนดให้หลังจากเขียนจุดResourceType = Resource.นอกจากนี้ยังมี "เทคนิค" เพิ่มเติมที่มี enums ที่คุณอาจต้องการเช่นประเภทหรือองค์ประกอบ / ธงซึ่งฉันสามารถจินตนาการว่าจะมีประโยชน์เมื่อสร้าง:

[Flags]
enum Metal {
 Copper = 0x01/*01*/, Tin = 0x02/*10*/, Bronze = 0x03/*11*/
}
Metal alloy = Metal.Copper; //lets forget Value(s) for sake of simplicity
alloy |= Metal.Tin; //now add a bit of tin
Console.WriteLine(alloy); //will print "Bronze"


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


2
ขอบคุณสำหรับคำตอบของคุณ @wondra ฉันชอบตัวเลือก enum และคุณสร้างทองแดงจากดีบุกและทองแดงได้อย่างไร p
MDijkstra

2
ฉันเข้าร่วมชุมชนนี้โดยเฉพาะเพื่อให้ฉันสามารถโหวตโซลูชัน Enum ได้มากขึ้น คุณยังสามารถดูการใช้แอตทริบิวต์คำอธิบาย enumเพื่อแมปจากการแสดง JSON บางส่วนของ enum ( my-great-enum) กับการแทนค่า C # บางส่วนของ enum ( MyGreatEnum)
Dan Forbes

เห็นได้ชัดว่าฉันออกจาก Java-loop มานานเกินไป ตั้งแต่เมื่อไหร่ที่อนุญาตให้มีการประกาศฟิลด์สำหรับอินเตอร์เฟส? เท่าที่ฉันรู้ว่าสิ่งเหล่านั้นเป็นแบบสแตติกและครั้งสุดท้ายโดยอัตโนมัติและไม่ค่อยมีการใช้เพื่อวัตถุประสงค์ที่อธิบายไว้ในคำถาม
M.Herzkamp

2
@ M.Herzkamp ไม่ใช่เขตข้อมูลเป็นคุณสมบัติ - และ Java ไม่รองรับคุณสมบัติ คำถามถูกแท็ก C #, C # อนุญาตให้ใช้คุณสมบัติในส่วนต่อประสาน - คุณสมบัติเป็นวิธีการที่ไม่ได้ผล ฉันกลัวเหมือนกันว่าจะมีการเพิ่มคำอธิบายประกอบเป็นธง แต่ไม่รองรับใน Java แต่ฉันก็ไม่แน่ใจ
พุธที่

ขอบคุณที่ล้างข้อมูล! ฉันพลาดแท็ก C # และรหัสในคำถามดูน่า
เกลียดชัง

2

คุณควรใช้ตัวเลือกที่ 1 ซึ่งมี 3 ข้อได้เปรียบ:

  1. มันง่ายกว่าที่จะยกตัวอย่างทรัพยากร - แทนที่จะต้องผ่านประเภทของทรัพยากรเป็นพารามิเตอร์ที่คุณเพิ่งทำตัวอย่างเช่น new Gold(50)
  2. หากคุณต้องการมอบพฤติกรรมพิเศษให้กับทรัพยากรคุณสามารถทำได้โดยเปลี่ยนคลาส
  3. ง่ายกว่าที่จะตรวจสอบว่าทรัพยากรเป็นประเภทที่แน่นอน - resource instanceof Gold

คำตอบทั้งหมดมีข้อดีข้อเสียมันยากที่จะเลือกว่าจะดีกว่า ฉันได้แก้ไขคำถามคุณคิดอย่างไรกับโครงสร้างนั้น
MDijkstra

1

หากทรัพยากรของคุณไม่มีตรรกะทางธุรกิจของตนเองหรือสถานการณ์กรณีพิเศษด้วยวิธีที่พวกเขาโต้ตอบกับสิ่งแวดล้อมทรัพยากรอื่น ๆ (นอกเหนือจากการค้าที่คุณได้ครอบคลุม) หรือผู้เล่นตัวเลือกที่สองทำให้การเพิ่มใหม่ง่ายมาก

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

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