การเข้ารหัสสถานะต่าง ๆ ในเกมผจญภัย


12

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

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

ฉันคิดอย่างไร้เหตุผลว่าจะใช้คำสั่ง switch {} เพื่อตัดสินใจว่า NPC ควรพูดอะไรหรือควรจะหาคำตอบได้ที่ไหนและทำให้วัตถุประสงค์การสืบเสาะสามารถโต้ตอบได้หลังจากตรวจสอบสภาพของตัวแปร game_state ทั่วโลกแล้ว แต่ฉันรู้ว่าฉันจะวิ่งเข้าสู่สภาวะเกมและสวิทซ์เคสที่แตกต่างกันอย่างรวดเร็วเพื่อเปลี่ยนพฤติกรรมของวัตถุ คำสั่ง switch นั้นยากที่จะดีบั๊กอย่างหนาแน่นและฉันคิดว่ามันอาจยากที่จะใช้ในตัวแก้ไขระดับ

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

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

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

PS: ฉันยังไม่มีเครื่องมือแก้ไขเลเวล - คิดจะใช้ JME SDK หรือทำเอง

คำตอบ:


9

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

ตัวอย่างหนึ่งของลักษณะอินเตอร์เฟสของรัฐ (ประกอบขึ้นอย่างสมบูรณ์ - เพียงเพื่อแสดงระดับการควบคุมชุดรูปแบบนี้ให้คุณ):

interface NPCState {
    Scene whereAmI(NPC o);
    String saySomething(NPC o);
}

และการใช้งานสองคลาส:

class Busy implements NPCState {
    Scene whereAmI(NPC o) {
        return o.getWorkScene();
    }
    String saySomething(NPC o) {
        return "Can't talk now, I'm busy!";
    }
}

class Available implements NPCState {
    Scene whereAmI(NPC o) {
        return TAVERN;
    }
    String saySomething(NPC o) {
        String[] choices = o.getRandomChat();
        return choices[RANDOM.getInt(choices.length)];
    }
}

และเปลี่ยนสถานะ:

// The time of day passed from "afternoon" to "evening"
NPCState available = new Available();
for ( NPC o : list ) {
    Scene oldScene = o.state.whereAmI(o);
    o.state = available;
    Scene newScene = o.state.whereAmI(o);
    moveGameObject(o, oldScene, newScene);
    ...

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

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

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


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

ฉันยอมรับว่ามันเป็นการดีที่จะแยกเกมออกจากเครื่องยนต์ของมันและตรรกะของเกม hardcoding จะเสริมสร้างความสัมพันธ์ระหว่างพวกเขา (ลดความเป็นไปได้ที่จะนำมาใช้ซ้ำ) มีการถ่วงดุลอำนาจเป็น แต่เนื่องจากขึ้นอยู่กับความซับซ้อนของพฤติกรรมตั้งใจของคุณพยายามที่จะ "รหัสอ่อน" ทุกอย่างที่อาจทำให้เกิดความยุ่งเหยิงที่ไม่จำเป็น ในกรณีนี้วิธีการแบบผสมอาจเป็นที่ต้องการ (เช่นมีตรรกะการเปลี่ยนสถานะ "ทั่วไป" แต่อนุญาตให้มีการรวมรหัสที่กำหนดเองได้เช่นกัน)
— mgibsonbr

ดังนั้นเมื่อฉันเข้าใจแล้วมีการแมปแบบหนึ่งต่อหนึ่ง btwn NPCState และ GameState จากนั้นฉันก็วาง NPC ในอาร์เรย์แล้ววนซ้ำมันกำหนด NPCState ใหม่เมื่อสังเกตเห็นการเปลี่ยนแปลงสถานะของเกม NPCState จะต้องมีความสามารถในการรู้วิธีการจัดการทุก NPC ต่าง ๆ ที่ถูกส่งไปดังนั้น NPCState จึงมีพฤติกรรมของ NPC ทั้งหมดสำหรับสถานะที่กำหนด? ฉันชอบที่พฤติกรรมทั้งหมดเก็บอย่างหมดจดใน NPCState เดียวซึ่งแมปอย่างหมดจดกับการใช้งานโปรแกรมแก้ไขเกม แต่มันทำให้ NPCState ค่อนข้างใหญ่
— Cardin

โอ้ฉันคิดว่าฉันเข้าใจผิด ฉันเปลี่ยนมันเล็กน้อยเพื่อรวมผู้สังเกตการณ์ ดังนั้นมันจึงเป็น NPCState ที่แตกต่างกันสำหรับทุก NPC ที่ต่างกันยกเว้น Super NPC ทั่วไปอย่าง Crowd NPC ที่สามารถแชร์สถานะได้ สำหรับแต่ละสถานะของเกม NPC จะลงทะเบียนตัวเองและ NPCState กับผู้สังเกตการณ์ ดังนั้นผู้สังเกตการณ์จะรู้ว่า NPC ใดที่ลงทะเบียนไว้เพื่อเปลี่ยนพฤติกรรมที่สถานะเกมและเพียงแค่ทำซ้ำผ่านพวกเขา และในด้านเครื่องมือแก้ไขเกมตัวแก้ไขเกมจะต้องส่งสัญญาณไปยังผู้สังเกตการณ์เพื่อเปลี่ยนสถานะของทั้งระดับ
— Cardin

1
ใช่นั่นคือความคิด! NPC ที่สำคัญจะมีหลายรัฐและการเปลี่ยนสถานะจะขึ้นอยู่กับเหตุการณ์สำคัญที่เสร็จสมบูรณ์ Generic NPCs อาจตอบสนองต่อเหตุการณ์สำคัญบางครั้งและยังมีสถานะที่เลือกไว้ขึ้นอยู่กับคุณสมบัติภายใน (สมมติว่า NPCs ทั้งหมดมีสถานะเริ่มต้นเริ่มต้นและเมื่อคุณพูดคุยกับหนึ่งในนั้นเป็นครั้งแรกที่เขาแนะนำตัวเองแล้วป้อน วงจรการเปลี่ยนสถานะปกติ)
— mgibsonbr

2

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

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

if (state in behaviors) {
  behaviors[state]();
}

ไฟล์ข้อมูลนั้นเป็นภาษาสคริปต์ชนิดหนึ่งหรือไม่ ฉันคิดว่าไฟล์ข้อมูลข้อความธรรมดาอาจไม่เพียงพอที่จะอธิบายพฤติกรรม ไม่ว่าคุณจะถูกโหลดแบบไดนามิกก็ตาม ฉันไม่คิดว่าจะใช้ตัวแก้ไขเกมเพื่อสร้างรหัส Java ที่ถูกต้อง แต่อย่างใดต้องแยกวิเคราะห์อย่างแน่นอน
— Cardin

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

โอ้ .. แน่นอนว่าง่ายกว่า! : D เปรียบเทียบกับสถานการณ์การฝังบางอย่างเช่น Lua haha ​​..
— Cardin

2

สิ่งที่เกี่ยวกับการใช้รูปแบบการสังเกตการณ์เพื่อมองหาการเปลี่ยนแปลงครั้งสำคัญ? หากมีการเปลี่ยนแปลงเกิดขึ้นบางคลาสจะจดจำสิ่งนี้และจัดการกับตัวอย่างการเปลี่ยนแปลงที่ต้องทำกับ npc

แทนที่จะใช้รูปแบบการออกแบบของรัฐที่กล่าวถึงฉันจะใช้รูปแบบกลยุทธ์

หาก npc มี n วิธีในการโต้ตอบกับตัวละครและตำแหน่ง m ซึ่งเป็นไปได้เขาจะมีคลาส +1 (m * n) +1 สูงสุดที่คุณต้องออกแบบ การใช้รูปแบบกลยุทธ์คุณจะจบลงด้วยคลาส n + m + 1 แต่กลยุทธ์เหล่านี้สามารถใช้โดย npcs อื่น ๆ ได้

ดังนั้นอาจมีชั้นเรียนจัดการเหตุการณ์สำคัญและชั้นเรียนที่สังเกตชั้นเรียนนี้และจัดการทั้ง npc หรือศัตรูหรือสิ่งที่ควรมีการเปลี่ยนแปลง หากผู้สังเกตการณ์ได้รับการปรับปรุงพวกเขาจะตัดสินใจว่าพวกเขาจะต้องเปลี่ยนบางสิ่งเป็นกรณีที่พวกเขาปกครองหรือไม่ ตัวอย่างเช่นคลาส NPC ใน Constructor จะแจ้งให้ NPC-Manager ทราบเมื่อเขาต้องได้รับการอัปเดตและสิ่งที่ต้องอัปเดต ...


รูปแบบการสังเกตการณ์ที่น่าสนใจ ฉันคิดว่ามันสามารถทิ้งความรับผิดชอบทั้งหมดไว้กับ NPC อย่างหมดจดเพื่อลงทะเบียนตัวเองกับผู้สังเกตการณ์ของรัฐ รูปแบบกลยุทธ์ให้ความรู้สึกคล้ายกับ Trigger และพฤติกรรม AI ของ Unity Engine ซึ่งใช้เพื่อแชร์พฤติกรรม btwn diff object เกม (ฉันคิดว่า) ฟังดูเป็นไปได้ ฉันไม่แน่ใจว่าสิ่งที่ข้อดี / ข้อเสียในขณะนี้ แต่ Unity ใช้วิธีเดียวกันก็ค่อนข้างมั่นใจฮ่าฮ่า ..
— Cardin

ฉันใช้สองรูปแบบเหล่านี้สองสามครั้งดังนั้นฉันไม่สามารถบอกคุณเกี่ยวกับข้อเสีย: - / แต่ฉันคิดว่ามันดีในกรณีที่มีความรับผิดชอบเดียวและความพร้อมในการทดสอบทุกกลยุทธ์ :) อาจทำให้สับสนถ้าคุณ ใช้กลยุทธ์ในคลาสที่แตกต่างกันมากมายและคุณต้องการค้นหาทุกคลาสที่ใช้
— TOAOGG

0

วิธีการทั้งหมดที่ให้มานั้นถูกต้อง ขึ้นอยู่กับสถานการณ์ที่คุณอยู่ ณ เวลาใดเวลาหนึ่ง การผจญภัยหรือ MMO จำนวนมากใช้การรวมกันของสิ่งเหล่านี้

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

OTOH ถ้าตัวละครเดินไปรอบ ๆ แผนที่และทำสิ่งต่าง ๆ ในสถานที่ต่าง ๆ คุณมักจะมีนักแสดงคนเดียวที่หมุนผ่านวัตถุพฤติกรรมต่าง ๆ (เช่นเดินตรงไปข้างหน้า / ไม่มีการสนทนาเทียบกับที่นี่ / สนทนาเกี่ยวกับความตายของมิทช์) "ซ่อน" หากจุดประสงค์ของพวกเขาสำเร็จ

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

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

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