คิดเล่น ๆ: multi-thread architecture design สำหรับเกมแบบ visual novel

จริง ๆ มันเริ่มจากมีน้องคนนึงไปโพสต์ในกลุ่มบน Facebook ประมาณว่า เขาจะทำเกม Visual Novel แล้วจะทำตัว interpreter binary ไฟล์ยังไง ก็เลยตอบไปว่า … ใช้ภาษาสคริปท์ที่มีอยู่แล้วเถอะ สบายกว่าเยอะ !

แล้วก็มานั่งคิด เกมแบบอื่นเขาใช้ภาษาสคริปท์อย่างเช่น Lua กัน เพราะเป็นภาษาที่เขียนง่าย เร็ว เล็ก และ bind ได้ง่าย แต่ว่าพอเอามาใช้กับเกมอย่าง Visual Novel ถ้าใช้ Architecture เดิม ๆ อาจจะไม่เหมาะก็ได้

ที่ว่าไม่เหมาะเนี่ย มันเป็นยังไง … หน้าตาคร่าว ๆ ของตัวโปรแกรมหลักของเกมจะเป็นแบบนี้ครับ

while true do:  
    get_input();
    process_game_logic();  
    update_screen();  
end.  

ถ้าใครเขียนโปรแกรมพวก GUI ที่ใช้ API ระดับล่าง ๆ (เช่น Win32) จะรู้สึกว่ามันคล้ายกัน ต่างกันตรง get_input() เนี่ย มันจะไม่ block คำสั่งจนกว่าจะมี input ครับ คือถ้าไม่มี input มันก็จะ return ค่าออกมาว่า ไม่มี input ต่างกับโปรแกรม GUI ที่จะรอจนกว่าจะมี input ก่อน (เพราะถ้าไม่มี input ก็ไม่รู้จะทำอะไรนั่นเอง)

แล้วมันยังไงกับ Visual Novel ผมคิดว่า สคริปท์ของ Visual Novel ในส่วนของตัว Game มันควรจะเป็น…ประมาณนี้

translate girl1.school_uniform.stance 400 400  
add_image girl1.school_uniform.stance  
message "Girl: Oh, hi, how are you doing?"  
result = choice "I: Great! how about you?", "I: Not so well, I have a cold".  
if result = 1 then  
    message "Girl: I'm doing good, thanks!"  
else
    message "Oh, sorry to hear that. Get better soon!"  
end.  

หรืออะไรทำนองนี้ (อ่านรู้เรื่องไหมนี่)

คือทุกครั้งที่มีคำสั่ง message ขึ้นมา ตัวเกมมันควรจะหยุดให้คนอ่านอ่านข้อความจนจบ … และอาจจะต้องมี option อื่น ๆ ด้วย (ไม่พูดถึงนะ) แต่ถ้าเราเอาโค๊ดทุกอย่างไปใส่ในฟังก์ชั่น process_game_logic แล้วล่ะก็ …มันจะกลายเป็นว่ามีแต่ภาพสาวน้อยกับข้อความขึ้นมาว่าอะไรไม่รู้ (ฮา)… เพราะมันทำงานรวดเดียวตั้งแต่ต้นยันจบ !

แต่ถ้าเราทำ message ให้หยุดรอ จะกลายเป็นว่าตัวเกมจะค้างจนกว่า user จะกดปุ่มใด ๆ … ค้างชนิดที่ว่าโปรแกรมจะหยุดทำงานไปเลย กดปิดก็ไม่ได้ จนกว่า user จะกดผ่าน …

วิธีที่ทำได้อย่างหนึ่งคือ ให้ process_game_logic อ่านทีละบรรทัดแล้วทำตาม คือ interpret คำสั่งกันไป ในกรณีที่เราสร้างภาษาสคริปทืเองมันก็ทำได้แหละ (แต่จะกลายเป็นงานช้างไป อย่างที่บอก)

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

ทางออกเหรอ … แยกเอา process_game_logic() ออกมาเป็นอีก thread นึงไง …

ทีนี้เราก็จะมีสอง thread ละ

Thread แรกก็จะมีหน้าตาแบบนี้

while true do:  
    get_input();  
    update_screen();  
end.  

Thread ที่สอง … มีแค่  process_game_logic(); เท่านั้น โดยจะทำการ sync ดึงค่า input จาก thread แรกเข้ามา แล้วส่ง output กลับไปที่ thread แรกเมื่อ process เสร็จแล้ว

ถ้าเราเอาสคริปท์ข้างบนมาใช้ ก็แค่ว่า เขียนโปรแกรมให้คำสั่ง message และคำสั่ง choice มีการหยุดรอจนกว่าจะมี input ถามว่าตรงนี้ทำได้ยังไง … ก็คือ ใช้ condition variable ร่วมกันระหว่างสอง thread เมื่อถึงคำสั่ง message ตัว thread ที่สองจะสั่งบล๊อค cv แล้วรอจนกว่า thread แรกจะปลดล๊อคให้ เท่านั้นเอง

การออกแบบในเชิง multi-thread แบบนี้สามารถเอาไปใช้กับเกมแบบเดิม ๆ ได้ด้วย ก็คือ เราก็เขียนโค๊ดใน process_game_logic() เป็น infinite loop นั่นเอง

หนึ่งเครื่อง สี่ระบบ

วันนี้จะขอแชร์เรื่องการใช้งานเครื่องคอมของผมสักนิดนึงนะครับ คิดว่าน่าสนใจอยู่ประมาณนึง

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

ผมใช้ Virtual Machine ในการจัดการตรงจุดนี้ คือผมเคยลอง Multiboot แล้วรู้สึกว่ามันไม่เวิร์ค ต้องมานั่งสลับไปสลับมา น่าเบื่อ และหลาย ๆ ครั้งมันก็ทำให้ระบบผมรวนไปซะเฉย ๆ บางทีก็บูทไม่ขึ้น ผมใช้ VMWare Player ครับ

ตัว Host OS จะเป็น Windows 8 Pro 64-bit ครับ งานหลัก ๆ ของมันนอกจากการเป็น Host OS แล้ว ผมก็เอาไว้เล่นเกม กับใช้งานสัพเพเหระทั่ว ๆ ไป

ส่วน VM ผมมี 3 ตัวครับ

ตัวแรกคือ Windows XP เอาไว้ทำงาน คือ พวกงานออฟฟิศทั้งหลาย แล้วก็พวกงานเขียนโปรแกรมบน Windows พวกที่ใช้ .Net ทั้งหลาย อ้อ แล้วก็เพิ่งเพิ่มซอฟท์แวร์สำหรับทำเพลงลงไปใน VM ตัวนี้ เพราะพบว่ามันก็พอใช้งานได้ ผมเองก็ไม่ได้ใช้โปรแกรมที่หนักมาก ๆ อยู่แล้วก็เลยโอเคเลย

ตัวที่สองคือ Windows XP เหมือนกัน แต่เซ็ตเอาไว้เล่นเกม พวกเกมที่เป็นเกม 2D แปลก ๆ ที่ไม่กินแรงเครื่องมากนัก

ตัวที่สามคือ Ubuntu เอาไว้สำหรับพัฒนา App ที่ไม่จำเป็นต้องรันบน Windows ก็พวก Web App, Android App หรือ Java App นี่แหละ

ข้อดีของการแยกกันก็คือ ผมเหมือนมีคอมพิวเตอร์ 4 เครื่องที่ทำงานเฉพาะด้าน ถ้าเกิดว่ามีเครื่องใดเครื่องนึงมีปัญหา ผมก็แค่ฟอร์แมทเครื่องนั้นแล้วลงโปรแกรมที่ใช้เฉพาะเครื่องนั้นลงไป โดยที่ไม่ต้องไปแตะต้องเครื่องอื่น

ข้อเสียคือ อาจจะรู้สึกว่ามันช้านิดหน่อย แต่ผมเฉย ๆ นะ ผมค่อนข้างชินกับการใช้คอมช้า ๆ อยู่แล้ว แฮะๆๆ อ้อ อีกอย่างคือมันกิน HDD ครับ พอดี HDD เครื่องนี้มัน 750GB ก็เลยสบาย ๆ ไม่เบียดเสียดมาก ใหญ่จนไม่รู้จะเอาไว้เก็บอะไรอยู่แล้ว เพราะหนังเก็บบน External HDD!

2012 ผ่านไป และ 2013 กำลังมาถึง

อ้า Topic ไม่ผิดหรอกครับ เพราะที่เมืองไทยบ้านเราตอนนี้เป็นปี 2556 ไปแล้ว แต่ตัวผมอยู่ที่แคนาดา ยังเป็นปี 2012 อยู่ ไหน ๆ วันนี้ก็เป็นวันสิ้นปี/วันปีใหม่ทั้งที ก็ขอเขียนถึงตัวเองในอดีต และตัวเองในอนาคตเสียหน่อยก็แล้วกัน

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

ปีที่แล้วเคยเขียนประมาณว่า รู้สึกเหมือนได้พบเป้าหมายของตัวเองละ คือ รู้สึกเหมือนฉันเพิ่งตื่นจากฝันของคนอื่นเลยนะ จำเพลงนี้ได้มั้ยครับ เป็นเพลงของแสตมป์ชื่อว่า “เพลงที่นานมาแล้วไม่ได้ฟัง” ในอัลบัมชื่อเดียวกัน … ส่วนปีนี้ก็เหมือน Track ต่อไปเลย … รู้สึกแบบ … แล้วฉันไปทำอะไรกับใครไว้ ?… (เพลง Karma) คือมันเป็นความรู้สึกแบบงง ๆ ว่าอยู่ดี ๆ ไอ้สิ่งที่พยายามสร้างขึ้นมามันพังได้ไงเนี่ย ? จนถึงตอนนี้ก็ยังรู้สึกไม่เข้าใจว่ามันเกิดอะไรขึ้น ก็พยายามหาทางแก้ทั้ง ๆ ที่ไม่รู้ว่ามันเกิดอะไรขึ้นนี่ล่ะ … แล้วมันจะแก้ได้มั้ย ???

ก็หวังว่าปี 2013 มันจะไม่เป็นแบบเพลง “ภาษาไทย” ที่เป็น Track ต่อไปนะ – -‘ พอแล้วเหนื่อย

ส่วนครึ่งปีหลัง 6 เดือนที่มาอยู่ที่แคนาดา เหมือนชีวิตหยุดนิ่ง เหมือนคนไร้ค่าทำอะไรก็ไม่มีความหมาย อยู่ไปวัน ๆ เปลืองข้าวสุก 555 ฟังดูหดหู่นะ แต่รู้สึกแบบนี้จริง ๆ มันไม่ได้รู้สึกสนุกกับการได้ออกมาเปิดหูเปิดตาเลย กลับกันรู้สึกว่าคนที่ส่งผมมาเนี่ยเหมือนพยายามจะทำร้ายกันมากกว่า (ทั้ง ๆ ที่เขาไม่ได้คิดอะไรขนาดนั้นหรอก)

แผนสำหรับปี 2013 ก็คงไม่มีอะไรมาก ผมก็คงต้องเริ่มหาที่อยู่เป็นของตัวเอง หลังจากเป็นปลิงเกาะพ่อแม่กินมาสามสิบปี … ก็นานเกินไปละ ผมคิดว่าจะหาคอนโดสักห้องเป็นของตัวเอง แต่งให้เป็นสตูดิโอด้วย 555

อย่างที่สองก็คงเป็นต้องเรียนเปียโนจริง ๆ จัง ๆ เป็นเรื่องนึงที่ผลัดมาจากปี 2012 คือตอนแรกกะว่าจะเรียนปีนี้แต่ว่ารอให้เพื่อนย้ายงานมาที่เดียวกันก่อน จะได้มีเพื่อนเรียนด้วย แต่ไป ๆ มา ๆ เขาดันไปบ้าเล่นกีฬาซะงั้น 555 เลยไม่มีเพื่อนเรียนเลย (แต่ปรกติพวกนี้มันเรียนตัวต่อตัวนะ)

อย่างที่สามคือดันเวปไซท์ commercial ของตัวเอง http://www.playground-soft.com ขึ้นให้ได้ และจะรันโปรดักท์ตัวที่สองหลังจากตัวแรก Fail อย่างรุนแรง ตัวที่สองผมก็ไม่ได้คาดหวังอะไรมาก อยากทำเป็น portfolio เฉย ๆ เผื่อจะรับงานนอกทำ คืองานที่บริษัทจริง ๆ มันก็พอเลี้ยงตัวอยู่ได้ แต่มันน่าเบื่อสุด ๆ จนหัวหน้าผมยังบอกเลยว่าหาอะไรทำแก้เบื่อบ้างก็ดีนะ

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

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

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

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

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