ฉันจะอัปเดตการตั้งค่าการแสดงผลจากหน้าจอตัวเลือกโดยไม่ต้องเริ่มต้นใหม่ได้อย่างไร


9

ขณะนี้ฉันกำลังสร้าง 2D RPG ใน C ++ 11 ด้วย Allegro 5 และเพิ่ม

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

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

คำอธิบายโดยละเอียด

ScreenManager มีรายการของGameScreenวัตถุทั้งหมดที่มีอยู่ในปัจจุบัน เหล่านี้จะเป็นหน้าจอต่าง ๆ ในเกมรวมถึงป๊อปอัป การออกแบบนี้จะปฏิบัติตามมากหรือน้อยไปตัวอย่างการจัดการสถานะของเกมใน C

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

อย่างไรก็ตามปัจจุบัน OptionsScreen ไม่สามารถเข้าถึงคลาสเกมได้ ดูแผนภาพด้านล่าง:

GameScreen สามารถส่งสัญญาณสามเหตุการณ์onFinished, และonTransitionStart onTransitionEndไม่มีonOptionsChangedเพราะมีเพียงหน้าจอเดียวเท่านั้นที่ทำเช่นนั้น ScreenManager ไม่สามารถตั้งค่าการจัดการเหตุการณ์สำหรับสิ่งนั้นเพราะมันจัดการหน้าจอทั้งหมดเป็นGameScreens

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


คำถามนี้ (แม้ว่าจะเกี่ยวข้องกับเกม) ดูเหมือนว่าเหมาะสมที่สุดสำหรับโปรแกรมเมอร์
stackexchange.com

คุณจะได้กราฟที่ดูดีขนาดไหน
joltmode

@psycketom: ตัวแรกคือจาก Visio 2013 และตัวที่สองถูกสร้างขึ้นจากรหัสภายใน VS2012 หวังว่าจะช่วย!
IAE

คำตอบ:


1

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

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

เมื่อเกมเริ่มต้นใหม่การตั้งค่าการแสดงผล (ตอนนี้ใหม่) จะถูกอ่านอีกครั้งจากไฟล์

--EDIT--

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

IIRC, Allegro มีฟังก์ชั่นการโทรที่ให้คุณเปลี่ยนการตั้งค่าการแสดงผลได้ทันที ฉันยังไม่คุ้นเคยกับ Allegro 5 แต่ฉันรู้ว่าคุณทำได้ใน 4


ฉันไม่คิดว่าปัญหาเกี่ยวข้องกับ Allegro และความสามารถของมัน "คำถามของฉันคือฉันจะเปลี่ยนการออกแบบของฉันอย่างไรเพื่อให้การเปลี่ยนแปลงใน OptionsMenu ไม่ต้องการการรีสตาร์ท แต่จะเปลี่ยนทันที" การรีสตาร์ทเป็นเพราะ "OptionsScreen ปัจจุบันไม่สามารถเข้าถึงคลาสเกม" และต้องโหลดจากไฟล์การตั้งค่าถ้าฉันเข้าใจถูกต้อง
ClassicThunder

@Casey: สวัสดี Casey! :) ใช่ฉันใช้ไฟล์กำหนดค่าเพื่อจัดเก็บข้อมูลการแสดงผลที่เกี่ยวข้อง แต่ฉันต้องการหลีกเลี่ยงการรีสตาร์ท มันเป็นเกมขนาดเล็กและเกมอื่น ๆ สามารถเปลี่ยนความละเอียดได้โดยไม่ต้องรีสตาร์ทดังนั้นฉันจึงไม่เห็นสาเหตุที่ฉันควรบังคับให้ผู้ใช้เริ่มต้นใหม่กับฉัน มันเป็นปัญหาการใช้งาน ในขณะที่ฉันสามารถเรียกฟังก์ชั่นการจ่ายเงินแบบอัลเลโกรฉันพยายามที่จะพัก OOP และไม่ผสมการโทรกราฟิกของฉันเพราะฉันทำได้ ฉันไม่คิดว่าการออกแบบที่ดี
IAE

ฉันเน้นบิต "โดยไม่ต้องรีสตาร์ท" เพื่อให้คนอื่นไม่เข้าใจประโยคสุดท้ายที่เหมือนกัน ความจริงสำคัญเช่นนี้ไม่ควรเกิดขึ้นในตอนท้ายฉันขอโทษ):
IAE

@SoulBeaver ใครบอกว่าคุณต้องสร้างมันขึ้นมาเพื่อที่คุณจะได้ไม่ต้องรีสตาร์ท? มันเป็นสิ่งที่ต้องปฏิบัติในความเป็นจริงมันกลายเป็นเรื่องธรรมดามากขึ้นทุกวัน รุ่นล่าสุดบางเกม (XCOM: Enemy Unknown, Skyrim และอื่น ๆ ) ของเกมที่มีงบประมาณสูงจำเป็นต้องเริ่มต้นใหม่ (ความจริงที่ว่าพวกเขาอยู่บน Steam อาจเป็นผู้ร้ายเนื่องจากการซิงค์ตัวเลือกฝั่งเซิร์ฟเวอร์ แต่อย่าไปที่นั่น ... )
Casey

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

1

นี่คือสิ่งที่ฉันทำสำหรับเกมของฉัน ฉันมี 2 ฟังก์ชั่นแยกต่างหากสำหรับการเริ่มต้นสิ่ง 'init' และ 'รีเซ็ต' Init เรียกเพียงครั้งเดียวเมื่อเริ่มต้นและทำสิ่งที่ไม่ต้องพึ่งพาการตั้งค่าใด ๆ เช่นการโหลดเนื้อหาหลัก การรีเซ็ตทำสิ่งต่าง ๆ เช่นการจัดวาง UI ตามความละเอียดของหน้าจอดังนั้นจึงเรียกว่าการตั้งค่าทุกครั้งที่มีการเปลี่ยนแปลง

init();
bool quit = false;
while( !quit )
{
    createWindow();
    reset();

    bool settings_changed = false;
    while( !quit && !settings_changed )
    {
        ... main loop
        // set quit=true if user clicks 'quit' in main menu
        // set settings_changed=true if user clicks 'apply' in options
    }

    destroyCurrentWindow();
}

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


นั่นเป็นทางออกที่น่าสนใจ ฉันพยายามควบคุมอย่างเข้มงวดทุกครั้งที่มีการรีเซ็ต แต่คุณทำโดยไม่คำนึงถึงการเปลี่ยนแปลง นั่นเป็นสิ่งที่ฉันสามารถนำไปใช้ได้และฉันจะตรวจสอบขอบคุณ!
IAE

1

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

ในการปรับให้เข้ากับการตั้งค่าใหม่จริง ๆGameคลาสจะต้องใช้ฟังก์ชั่นรีเซ็ตบางประเภทซึ่งดึงการตั้งค่าปัจจุบันและเริ่มต้นใหม่ตามการตั้งค่าเหล่านั้น

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

ด้วยผู้จัดการเหตุการณ์ระดับโลกผู้ใช้OptionsScreenสามารถเริ่มต้นวาดเหตุการณ์ที่Gameลงทะเบียนเพื่อฟังก่อนหน้าได้ทั่วโลก

โดยทั่วไปคุณสามารถใช้คลาสผู้จัดการจัดเก็บเหตุการณ์และโทรกลับฟังพวกเขาในแผนที่แฮช จากนั้นคุณสามารถสร้างอินสแตนซ์เดียวของผู้จัดการนั้นและส่งต่อพอยน์เตอร์ไปยังคอมโพเนนต์ของคุณ การใช้ C ++ รุ่นใหม่นั้นค่อนข้างง่ายเนื่องจากคุณสามารถใช้std::unordered_mapเป็นแผนที่แฮชและstd::functionจัดเก็บการเรียกกลับ มีวิธีการต่าง ๆ ที่คุณสามารถใช้เป็นคีย์ได้ ตัวอย่างเช่นคุณสามารถสร้างสตริงตัวจัดการเหตุการณ์ซึ่งทำให้องค์ประกอบเป็นอิสระมากขึ้น ในกรณีนั้นคุณจะใช้std::stringเป็นกุญแจในแผนที่แฮช ส่วนตัวแล้วฉันชอบสิ่งนี้และมันก็ไม่มีปัญหาเรื่องประสิทธิภาพ แต่ระบบเหตุการณ์แบบดั้งเดิมส่วนใหญ่ทำงานกับกิจกรรมเป็นคลาส


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

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

1

นี่เป็นกรณีเฉพาะของรูปแบบการสังเกตการณ์

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

SettingsStoreโดยทั่วไปคุณจะต้องมีการจัดเรียงของบางส่วน ที่นั่นคุณเก็บการตั้งค่า เมื่อคุณสร้างหน้าจอใหม่พวกเขาจะต้องมีตัวชี้ไปยังร้านค้า ในกรณีของOptionsScreenมันจะแก้ไขค่าการตั้งค่าบางอย่างเอง ในกรณีของGameScreenมันก็จะอ่านพวกเขา ดังนั้นในเกมของคุณคุณจะต้องสร้างเพียงตัวอย่างเดียวซึ่งจะถูกส่งผ่านไปทุกหน้าจอที่ต้องใช้

ตอนนี้ที่ชั้นจะมีรายชื่อของSettingsStore notifiablesพวกเขาเป็นชั้นเรียนที่ใช้ISettingChangedอินเตอร์เฟซที่แน่นอน อินเทอร์เฟซจะง่าย ๆ ที่ประกอบด้วยวิธีการต่อไปนี้:

void settingChanged(std::string setting);

จากนั้นในหน้าจอของคุณคุณจะใช้ตรรกะสำหรับการตั้งค่าแต่ละอย่างที่คุณสนใจ จากนั้นเพิ่มตัวคุณเองในร้านค้าเพื่อรับการแจ้งเตือน: store->notifyOnChange(this);. เมื่อมีการเปลี่ยนแปลงการตั้งค่าการโทรกลับจะถูกเรียกด้วยชื่อการตั้งค่า SettingsStoreค่าการตั้งค่าใหม่แล้วสามารถเรียกดูได้จาก

ตอนนี้สามารถเติมเพิ่มเติมด้วยแนวคิดต่อไปนี้:

  • ใช้คลาสที่เก็บสตริงการตั้งค่า - อาจเป็นแม้แต่SettingsStore(สตริง const) เพื่อป้องกันการวางสตริงการคัดลอก
  • ยิ่งไปกว่านั้นแทนที่จะใช้สตริงใช้ enum เพื่อระบุการตั้งค่าที่คุณมี
  • คุณสามารถระบุค่าเก่าและค่าใหม่เป็นอาร์กิวเมนต์ในการเรียกกลับ แต่จะมีความซับซ้อนมากขึ้นเนื่องจากคุณสามารถมีค่าสตริงหรือ int หรืออะไรก็ตาม มันขึ้นอยู่กับคุณ.

0

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

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