ฉันควรใช้เทคนิคใดเพื่ออำนวยความสะดวกในการสื่อสารระหว่าง XNA GameComponents (หรือระหว่างองค์ประกอบของเกมประเภทใดก็ได้)


9

ฉันเริ่มโครงการเกม 'ถูกต้อง' ครั้งแรกของฉันและฉันก็โดนบล็อกที่พยายามตัดสินใจว่าองค์ประกอบของเกมใน XNA ควรสื่อสารอย่างไร

จากเหตุการณ์การเขียนโปรแกรม GUI (Java) GUI ก่อนหน้าตัวจัดการและผู้ฟังดูเหมือนจะเป็นทางไปข้างหน้า ดังนั้นฉันจึงมี Event Bus บางประเภทที่ยอมรับการลงทะเบียนกิจกรรมและคลาสที่สมัครเป็นสมาชิกของกิจกรรมเหล่านั้นพร้อมกับตัวจัดการเพื่อจัดการกับพวกเขา ตัวอย่างเช่น (pseudocode):

class SpriteManager
    Update(){
        if(player.collidesWith(enemy)
             // create new 'PlayerCollisionEvent'
    }

class HUDManager
    onPlayerCollisionEvent(){
        // Update the HUD (reduce lives etc)
    }

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

ดูเหมือนจะมีการกล่าวถึงมากมายเกี่ยวกับบริการเกมโดยที่คุณสามารถลงทะเบียน GameComponent ในคลาส Game.cs หลักของคุณจากนั้นดึงข้อมูลจากที่ใดก็ได้ในรหัสของคุณที่มีการอ้างอิงถึงวัตถุ 'เกม' หลัก ฉันได้ลองสิ่งนี้กับวัตถุ SpriteBatch ของฉันแล้วและดูเหมือนง่ายมาก .. อย่างไรก็ตามฉันไม่เห็นว่าสิ่งนี้ยืดหยุ่นได้เหมือนแบบจำลองเหตุการณ์

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

หรือกลยุทธ์ที่ด้อยกว่าเหล่านี้เป็นอย่างอื่น?

ฉันรู้ว่านี่เป็นส่วนหนึ่งของความรู้ C # ที่แย่ของฉันมากเท่ากับกระบวนทัศน์การสื่อสารเกม แต่ฉันต้องการทำให้สิ่งพื้นฐานนี้ถูกต้อง

ปรับปรุง

การดูบริการเป็นรายละเอียดที่มากกว่าฉันมั่นใจน้อยกว่า - โดยทั่วไปแล้วมันจะผ่านตัวแปรระดับโลกรอบ ๆ (จากสิ่งที่ฉันเข้าใจ)

อัปเดต 2

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


ฉันอยากจะแนะนำให้คุณลอง FlatRedBall ก่อน มันตั้งอยู่บน XNA และทำให้ชีวิตง่ายขึ้น
ashes999

3
ฉันต้องการที่จะเข้าใจพื้นฐานของสิ่งที่เกิดขึ้นก่อนที่จะกระโดดไปที่เครื่องยนต์
เข้ารหัส

ฉันคิดว่าความล้มเหลวของคุณที่นี่คือการขาดข้อมูลเกี่ยวกับ C # C # ใช้กิจกรรมเพื่ออำนวยความสะดวกในการสื่อสารระหว่างชั้นเรียนปกติ มันขึ้นอยู่กับคุณว่าจะทำอย่างไร - XNA มอบคลาส SpriteBatch และงานส่วนใหญ่ขึ้นอยู่กับคุณที่จะเขียน เครื่องยนต์จะให้แนวคิดที่ชัดเจนเกี่ยวกับวิธีการทำงานของสิ่งต่าง ๆ ในระดับที่สูงขึ้นก่อนที่จะลงลึกในรายละเอียด
ashes999

1
ฉันเห็นด้วยกับขอบเขต แต่จากฉันได้อ่านการสื่อสารระหว่าง InterClass ส่วนใหญ่ระหว่าง GameComponents สามารถทำได้โดยใช้บริการ ฉันคุ้นเคยกับการใช้กิจกรรม ฉันไม่แน่ใจว่าวิธีไหนดีที่สุดหรือมีทางเลือกที่ใช้ได้ (singletons, static static masquerading as globals เป็น 2 วิธีอื่นที่ฉันไม่ได้ใช้)
codinghands

คำตอบ:


4

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

เหตุผลที่คุณจะไม่พบเหตุการณ์เกี่ยวกับรถเมล์ใน C # มากนักเพราะฉันไม่คิดว่าใครที่อยู่นอก Java จะเรียกสิ่งนี้ว่า 'bus' ในประสบการณ์ของฉัน คำศัพท์ทั่วไปอื่น ๆ อาจเป็นคิวข้อความผู้จัดการเหตุการณ์สัญญาณ / ช่องโฆษณา / สมัครสมาชิก ฯลฯ

คุณไม่ต้องการให้เกมทำงาน แต่ถ้าเป็นระบบที่คุณคุ้นเคยมันก็จะให้บริการคุณที่นี่เช่นกัน น่าเสียดายที่ไม่มีใครสามารถบอกคุณได้ว่าจะทำอย่างไรเพราะทุกคนกลิ้งมันให้แตกต่างกันเล็กน้อยถ้าพวกเขาใช้มันเลย (ตัวอย่างเช่นฉันไม่ทำเช่นนั้น) คุณอาจเริ่มต้นด้วยการเรียบง่ายSystem.Collections.Generic.List<Event>สำหรับคิวโดยที่เหตุการณ์ต่าง ๆ ของคุณเป็นประเภทย่อยของกิจกรรมและรายชื่อสมาชิกสำหรับแต่ละประเภทเหตุการณ์ สำหรับแต่ละเหตุการณ์ในคิวที่ได้รับรายชื่อของสมาชิกและสำหรับสมาชิกแต่ละโทรhandle(this_event)กับมัน จากนั้นลบออกจากคิว ทำซ้ำ

ดูเหมือนจะมีการกล่าวถึงมากมายเกี่ยวกับบริการเกมโดยที่คุณสามารถลงทะเบียน GameComponent ในคลาส Game.cs หลักของคุณจากนั้นดึงข้อมูลจากที่ใดก็ได้ในรหัสของคุณที่มีการอ้างอิงถึงวัตถุ 'เกม' หลัก ฉันได้ลองสิ่งนี้กับวัตถุ SpriteBatch ของฉันแล้วและดูเหมือนง่ายมาก .. อย่างไรก็ตามฉันไม่เห็นว่าสิ่งนี้ยืดหยุ่นได้เหมือนแบบจำลองเหตุการณ์

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

ฉันรู้ว่านี่เป็นส่วนหนึ่งของความรู้ C # ที่แย่ของฉันมากเท่ากับกระบวนทัศน์การสื่อสารเกม แต่ฉันต้องการทำให้สิ่งพื้นฐานนี้ถูกต้อง

C # เป็นภาษาที่เหมือนกันมากกับ Java สิ่งที่คุณทำใน Java สามารถทำได้ใน C # เพียงแค่มีไวยากรณ์ที่แตกต่าง หากคุณมีปัญหาในการแปลแนวคิดอาจเป็นเพราะคุณรู้จักชื่อเฉพาะของ Java เท่านั้น


ขอบคุณ @Kylotan ด้วยความอยากรู้อยากเห็นคุณใช้ระบบใดในการสื่อสารแบบ Interclass - แนวทางของบริการหรืออย่างอื่น
เข้ารหัส

AFAIK บัสเหตุการณ์คล้ายกับการส่งข้อความคิว แต่สำหรับกิจกรรม
ashes999

2
@ codehands ปกติแล้วฉันจะไม่ใช้วิธีการสื่อสาร interclass แบบเป็นทางการ ฉันแค่ทำสิ่งต่าง ๆ ให้เรียบง่าย - ถ้าชั้นหนึ่งต้องเรียกอีกชั้นหนึ่งมันมักจะมีการอ้างอิงถึงชั้นที่สองในฐานะสมาชิกหรือมีชั้นที่สองส่งผ่านเป็นอาร์กิวเมนต์ บางครั้งเมื่อฉันทำงานกับเอ็นจิ้น Unity ซึ่งมีวิธีการคล้ายกับสิ่งที่คุณเรียกใช้ 'บริการ' ในการที่ฉันจะค้นหาวัตถุตามชื่อที่มีส่วนประกอบที่ฉันต้องการให้ค้นหาส่วนประกอบ บนวัตถุจากนั้นเรียกใช้วิธีการกับองค์ประกอบนั้น
Kylotan

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

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

1

คุณได้ลองใช้เหตุการณ์คงที่ง่ายๆหรือไม่? ตัวอย่างเช่นหากคุณต้องการให้คลาสคะแนนของคุณรู้ว่าเมื่อศัตรูตายคุณจะทำสิ่งนี้:

Score.cs

class Score
{
    public int PlayerScore { get; set; }

    public Score()
    {
        EnemySpaceship.Death += new EventHandler<SpaceshipDeathEventArgs>(Spaceship_Death);
    }

    private void Spaceship_Death(object sender, SpaceshipDeathEventArgs e)
    {
        PlayerScore += e.Points;
    }
}

EnemySpaceship.cs

class EnemySpaceship
{
    public static event EventHandler<SpaceshipDeathEventArgs> Death;

    public void Kill()
    {
        OnDeath();
    }

    protected virtual void OnDeath()
    {
        if (Death != null)
        {
            Death(this, new SpaceshipDeathEventArgs(50));
        }
    }
}

SpaceshipDeathEventArgs.cs

class SpaceshipDeathEventArgs : EventArgs
{
    public int Points { get; private set; }

    internal SpaceshipDeathEventArgs(int points)
    {
        Points = points;
    }
}

1

หากคุณรู้สึกไม่สบายใจกับวิธีการจัดกิจกรรมให้ลอง Artemis C # เป็นกรอบระบบ Entity ที่อ้างอิงจากhttp://t-machine.org/index.php/2007/09/03/entity-systems-are -The อนาคตของ MMOG พัฒนาส่วน-1 /

ที่มา: https://github.com/thelinuxlich/artemis_CSharp เกมตัวอย่าง: https://github.com/thelinuxlich/starwarrior_CSharp


0

ลองใช้ตัวรวบรวมเหตุการณ์แบบนี้


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