ฉันจะจัดการข้อมูลและการพึ่งพาระหว่างคลาสได้อย่างเรียบร้อยและสวยงามได้อย่างไร


12

ฉันกำลังเล่นเกม 2d topdown ใน SFML 2 และต้องการหาวิธีที่สวยงามที่ทุกอย่างจะทำงานร่วมกันได้

ให้ฉันอธิบาย ฉันมีจำนวนคลาสที่สืบทอดมาจากฐานนามธรรมที่ให้วิธีการวาดและวิธีการอัปเดตไปยังคลาสทั้งหมด

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

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

สิ่งนี้ใช้ได้ดีสำหรับส่วนใหญ่ แต่ฉันเชื่อว่ามันสามารถทำได้ดีกว่าฉันไม่แน่ใจว่าจะทำอย่างไร

ตอนนี้ฉันมีสิ่งที่ซับซ้อนกว่าที่ฉันต้องนำไปใช้เช่นผู้เล่นสามารถเดินไปที่วัตถุบนพื้นดินกดปุ่มเพื่อหยิบขึ้นมา / ยกมันขึ้นมาแล้วมันจะปรากฏในสินค้าคงคลัง นี่หมายความว่าต้องมีบางสิ่งเกิดขึ้น:

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

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

ความช่วยเหลือ / คำแนะนำใด ๆ ที่จะได้รับการชื่นชมอย่างมาก! หากสิ่งใดไม่ชัดเจนฉันยินดีที่จะขยายสิ่ง


1
คุณอาจต้องการพิจารณาองค์ประกอบที่นี่มากกว่าการสืบทอด ลองดูตัวอย่างองค์ประกอบและมันอาจให้แนวคิดบางอย่างกับคุณ สำนวน pimpl อาจช่วยในการคัดแยกสิ่งต่าง ๆ ออกมาเช่นกัน
OriginalDaemon

5
หนึ่งในบทความเกี่ยวกับการเขียนเรียงความของแคนนอน: วิวัฒนาการลำดับชั้นของคุณ
doppelgreener

ดูเหมือนว่ามีการแปลเกินไป ลองใช้ Code Review SE หรือไม่
Anko

คำตอบ:


5

ไม่แน่ใจว่าองค์ประกอบจะแก้ปัญหาทั้งหมดได้ไหม อาจช่วยได้บ้าง แต่ถ้าสิ่งที่คุณต้องการคือการแยกชั้นเรียนฉันจะพิจารณาตรรกะที่ขับเคลื่อนด้วยเหตุการณ์เพิ่มเติม วิธีนี้เช่นคุณจะมีฟังก์ชั่นOnLootซึ่งจำเป็นต้องมีตำแหน่งของผู้เล่นและข้อมูลเกี่ยวกับก้อนที่มีอยู่เพื่อค้นหาสิ่งที่ใกล้เคียงที่สุด จากนั้นฟังก์ชั่นส่งกิจกรรมไปยังรายการที่ปล้น ไอเท็มที่ถูกปล้นในวัฏจักรกระบวนการเหตุการณ์จะจัดการกับเหตุการณ์นี้ดังนั้นไอเท็มจะต้องรู้วิธีการอัพเดตเท่านั้น ฟังก์ชั่นOnLootยังสามารถอัพเดทสินค้าคงคลังของผู้เล่นหรือไอเท็มนั้นอาจส่งupdateInventory / * OnLootSucess * event และผู้เล่น / สินค้าคงคลังจะจัดการมันในวงจรกิจกรรมกระบวนการของตัวเอง

ข้อดี: คุณแยกคลาสบางส่วนออกแล้ว

ข้อด้อย: เพิ่มคลาสของเหตุการณ์อาจมีค่าใช้จ่ายของโค้ดที่ไม่จำเป็น

นี่คือหนึ่งในวิธีที่เป็นไปได้ของวิธีที่อาจมีลักษณะ:

case LOOT_KEY:
   OnLoot(PLayer->getPos(), &inventoryItems);
....

// note onLoot do not needs to know anything about InvItem class (forward decl in enough)
int onLoot(vec3 pos, InvItems& pitems)
{
    InvItem* pitem = findInRange(pos, pitems, LOOT_RANGE);
    if(pitem)
     EventManager::Instance->post( Event::makeLootEvent(pitem));
}
....

// knows only about EventManager
InvItem::processEvents()
{
    while(!events.empty())
    {
        Event* pev = events.pop();
        ...
        case LOOT_EVENT:
            // in case you broadcasted it, but better is to sort all posted/sent events and add them only if they addressed to particular item 
            if(pev->item == this && handleLoot((LootEvent)pev))
            {
                EventManager::Instance->post(Event::makeLootSuccessEvent(this));
            }
    }
}

int handleLoot(LootEvent* plootev)
{
    InvItem* pi = plootev->item;
    if(pi->canLoot())
    {
        updateTexture(pi->icon, LOOTED_ICON_RES);
        return true;
    }
    return false; 
}


...
// knows only LootSuccessEvent and player
Inventory::processEvents()
{
    while(!events.empty())
    {
        Event* pev = events.pop();
        ...
        case LOOT_SUCCESS_EVENT:
             player->GetInventory()->add( ((LootSuccessEvent*)pev)->item );
        ...
}

นี่เป็นเพียงหนึ่งในวิธีที่เป็นไปได้ อาจเป็นเพราะคุณไม่ต้องการกิจกรรมมากมาย และฉันแน่ใจว่าคุณสามารถรู้ข้อมูลของคุณได้ดีขึ้นนี่เป็นเพียงหนึ่งในหลาย ๆ วิธี

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