ฉันจะออกแบบการโจมตีประเภทต่าง ๆ จำนวนมากที่สามารถรวมกันได้อย่างไร


17

ฉันสร้างเกม 2D จากบนลงล่างและฉันต้องการที่จะมีประเภทการโจมตีที่แตกต่างกันมากมาย ฉันต้องการทำให้การโจมตีมีความยืดหยุ่นมากและรวมกันได้อย่างที่ The Binding of Isaac ทำงานได้ นี่คือรายชื่อของสะสมทั้งหมดในเกม ที่จะหาตัวอย่างที่ดีให้ดูที่ช้อนประมาทรายการ

Spoon Bender ทำให้ไอแซคมีความสามารถในการยิงน้ำตากลับบ้าน

หากคุณดูที่ส่วน "การทำงานร่วมกัน" คุณจะเห็นว่ามันสามารถใช้ร่วมกับของสะสมอื่น ๆ เพื่อเอฟเฟกต์ที่น่าสนใจ แต่ใช้งานง่าย ตัวอย่างเช่นถ้ามันรวมเข้ากับThe Inner Eyeมัน "จะทำให้ Isaac ยิงกระสุนกลับบ้านหลายนัดพร้อมกัน" มันสมเหตุสมผลแล้วเพราะ The Inner Eye

ทำให้ Isaac ยิงได้สามครั้ง

สถาปัตยกรรมที่ดีในการออกแบบสิ่งนี้คืออะไร นี่คือวิธีการแก้ปัญหากำลังดุร้าย:

if not spoon bender and not the inner eye then ...
if spoon bender and not the inner eye then ...
if not spoon bender and the inner eye then ...
if spoon bender and the inner eye then ...

แต่นั่นจะออกไปจากมืออย่างรวดเร็ว เป็นวิธีที่ดีกว่าในการออกแบบระบบเช่นนี้คืออะไร?


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

2
ฉันต้องการชี้ให้เห็นว่าKirby 64ใช้วิธีการที่ดุร้ายและเอฟเฟกต์ที่ตั้งโปรแกรมอย่างหนักสำหรับการผสมผสานความสามารถที่เป็นไปได้ทั้งหมดดังนั้นจึงเป็นไปได้
Kevin

คำตอบ:


16

คุณไม่จำเป็นต้องใช้รหัสด้วยกันเลย คุณสามารถมุ่งเน้นไปที่คุณสมบัติที่แต่ละรายการให้คุณแทน ยกตัวอย่างเช่นรายการโฆษณา AProjectile=Fireball,Targetting=Homingชุด รายการ BFireMode=ArcShot,Count=3ชุด ArcShotตรรกะเป็นผู้รับผิดชอบสำหรับการส่งออกCountจำนวนProjectileรายการในโค้ง

ไอเท็มสองรายการเหล่านี้สามารถรวมกับไอเท็มอื่นที่แก้ไขคุณสมบัติเหล่านี้ (หรืออื่น ๆ ) ได้อย่างอิสระ หากคุณเพิ่ม projectile ชนิดใหม่มันจะทำงานโดยอัตโนมัติArcShotและถ้าคุณเพิ่มโหมดการยิงใหม่มันจะทำงานกับFireballprojectiles โดยอัตโนมัติ ในทำนองเดียวกันTargettingเป็นคุณสมบัติที่ตั้งค่าตัวควบคุมสำหรับ projectiles ในขณะที่FireModeสร้าง projectiles เพื่อให้สามารถรวมกันได้ง่ายและไม่สำคัญในชุดค่าผสมใด ๆ ตามที่เหมาะสม

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

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


นิด ๆ หน่อย ๆ แต่คุณดูเหมือนจะไม่ได้มีคุณสมบัติที่ถูกต้องสำหรับตัวอย่างที่คุณใช้ "Spoon Bender" เพิ่มการกลับบ้านและ "Inner Eye" เพิ่มการยิงสามเท่า ไม่เพิ่มส่วนโค้งและทั้งคู่เป็นน้ำตา หากคุณใช้คุณสมบัติโดยพลการในตัวอย่างของคุณเพื่อทำให้การออกแบบเป็นนามธรรมมันจะง่ายกว่าที่จะอ่านถ้าพวกเขาไม่ได้ตั้งชื่อในรูปแบบที่ทำให้เข้าใจผิด ฉันต้องการ "รายการ A" และ "รายการ B" สำหรับสิ่งนี้
Daniel Kaplan

1
@tietyT: ฉันวางนัยชื่อและขยายตัวอย่างเพื่อรวมโหมดการกำหนดเป้าหมายเพิ่มเติมจากโปรเจ็กต์ประเภทและโหมดการยิง ไม่เคยเล่น BoI มานานกว่าสองสามนาทีดังนั้นฉันจึงไม่มีชื่อภายในว่าเป็นคนอื่น :)
Sean Middleditch

สำหรับฉันแล้วดูเหมือนว่าส่วนที่ยุ่งยากนั้นจะระบุประเภทของคุณสมบัติ เช่น: การกำหนดเป้าหมายเป็นหนึ่ง, FireMode เป็นอีก, Count อาจเป็นอันดับ 3 ... หรืออาจจะไม่ บางทีขีปนาวุธ 3 ลูกอาจเป็นลูกไฟและ 5 ลูกอาจระเบิดได้แม้ว่าจะเป็นอาวุธเดียว
Daniel Kaplan

@tietyT: แน่นอน คุณสามารถขยายระบบเพิ่มเติมเพื่อให้สามารถใช้ชุดค่าผสมพิเศษหรือตรรกะได้อย่างแน่นอน แต่นั่นควรเป็นข้อยกเว้นมากกว่ากฎ ปรับให้เหมาะสมสำหรับกรณีทั่วไปไม่ใช่ตัวพิมพ์มุม
Sean Middleditch

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

8

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

ตัวอย่าง c ++ ที่หยาบคาย:

class AttackBehaviour
{
    /* other code */
    virtual void Attack(double angle);
};

class TearAttack: public AttackBehaviour
{
    /* other code */
    void Attack(double angle);
};

class TripleAttack: public AttackBehaviour
{
    /* other code */
    AttackBehaviour* baseAttackBehaviour;
    void Attack(double angle);
};

void TripleAttack::Attack(angle)
{
    baseAttackBehaviour->Attack(angle-30);
    baseAttackBehaviour->Attack(angle);
    baseAttackBehaviour->Attack(angle+30);
}

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


หากฉันต้องการเปลี่ยนภาพเคลื่อนไหวเหตุใดจึงไม่เหมาะกับฉัน นอกจากนี้ถ้าฉันทำงานด้วยภาษาที่ใช้งานได้มากกว่า คุณรู้จักรูปแบบการออกแบบที่เหมาะกับพวกเขาหรือไม่?
Daniel Kaplan

มันเข้มงวดมากขึ้นเพราะตัวดัดแปลงจะจบลงด้วยการเรียกAttackเมธอดของวัตถุที่รวมเข้าด้วยกันเสมอ TripleAttackชั้นไม่ควรรู้เกี่ยวกับTearAttackระดับ หากสิ่งนี้เป็นจริงแล้วมันจะนำไปสู่การปวดหัวมากเท่ากับelse-ifบล็อก ซึ่งหมายความว่าภาพเคลื่อนไหวฉีกขาดใด ๆ จะต้องอยู่ภายในTearAttackBehaviourวัตถุ วัตถุนี้ไม่ได้ (และไม่ควร) รู้ว่ามันถูกตกแต่งโดยTripleAttackวัตถุ ผลที่ได้คือภาพเคลื่อนไหว 3 ภาพฉีกขาดดำเนินการอย่างอิสระเพราะเป็นอิสระ
NauticalMile

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

สำหรับการใช้งานในภาษาที่ใช้งานได้มากขึ้นฉันจะคิดถึงมันสักพักหนึ่งและแก้ไขคำตอบของฉันเมื่อฉันพร้อม
NauticalMile

1

ในฐานะแฟนของ Binding of Isaac ฉันก็สงสัยว่าจะทำอะไรแบบนี้ได้บ้าง ระบบในเกมนั้นแข็งแกร่งพอที่พฤติกรรมที่เกิดขึ้นมาจากการผสมผสานของเอฟเฟกต์ (สิ่งที่อยู่ในใจของฉันคือการได้รับกระจก, ช้อนดัด, และบางช่วงบูสเตอร์ส่งผลให้ผนังหมุนวนรอบสไตล์ไอแซก ) จำนวนที่แท้จริงของพวกเขาจะทำให้บล็อก "ถ้า" ทำไม่ได้

ข้อสรุปของฉันคือการที่ไอแซคและน้ำตาของเขาเป็นสองหน่วยงานในใจกลางของขนาดใหญ่ตัวแทน-Entity Framework เอนทิตีมีสถิติพื้นฐานบางอย่าง (movespeed, ชีวิต, ช่วง, ความเสียหาย, สไปรต์, ฯลฯ ) และแต่ละองค์ประกอบจะนำตัวดัดแปลงสถิติและคำกริยา

ในรหัสไอแซคและน้ำตาของเขาจะมีรายการที่จะมีสิ่งต่าง ๆ ของอินเทอร์เฟซ Isaac จะมีรายการของสิ่งต่าง ๆ ที่สมัครใช้งานอินเตอร์เฟส IsaacMutator และน้ำตาของเขา tearMutator IsaacMutator จะมีฟังก์ชั่นในการปรับเปลี่ยนสุขภาพ, ความเร็ว, ช่วง, รูปลักษณ์และกริยาพิเศษบางอย่างของ Isaac TearMutator จะคล้ายกัน ไอแซคหนึ่งครั้งต่อเกมหนึ่งเกมจะวนซ้ำผ่านไอแซคทั้งหมดที่มีและทุกน้ำตาก็มีชีวิตเช่นกัน หากต้องการไปตามตัวอย่างภาษาอังกฤษของคุณมันจะอ่าน:

Isaac has IsaacMutators:
--spoonbender which gives no stat change and: Tears are made homing
--MeatEater which give +1 health, +1 damage and: nothing
--MagicMirror which gives no stat change and: Tears are made reflecting

Tears have tearMutators:
--(depends on MeatEater) +1 damage and: nothing
--(depends on MagicMirror) no stat change and: +1 vector towards isaac
--(depnds on spoonbender) no stat change and: +1 vector towards enemytype

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


-5

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

คุณสามารถทำได้โดยการสร้างคำนิยามใหม่เมื่อมีรายการทั้งสองอยู่ แต่สิ่งนี้จะเพิ่มความเป็นจริง:

if spoon bender and the inner eye then new spoon bender inner eye

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