irpg Community

Full Version: มาแก้ปัญหาภาษาไทยใน RPG Maker MV กันเถอะ (วรรณยุกต์ซ้อน, ปัญหาสระอำ, ญ/ฐ+สระอู)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2 3
------ EDITED BY ADMIN ----------
ถ้าอันนี้ใช้ไม่ได้
ให้ลองใช้ของท่าน admanon แทน จะใช้ง่ายกว่ากันครับ
http://irpg.in.th/thread-2978-post-28988.html#pid28988
-----------------------------------------


ติดตามเราได้ที่ Facebook ชื่อเพจ Planila Game Developer


(ตามเว็บต่าง ๆ เห็นมีแต่วิธีแก้ปัญหาภาษาไทยใน RPG Maker เวอร์ชันเก่า ๆ ไม่เห็นมีเว็บไหนมีวิธีแก้ปัญหาภาษาไทยใน RMMV เลย (ไม่นับวิธีเปลี่ยนฟอนต์ที่ไม่ค่อยจะได้ผล) มิกิก็เลยนำสคริปต์ที่พัฒนาขึ้นเองมาแจกให้ทุกคน)

อย่างที่ทราบกันดีว่าเกมเอนจินอย่าง RPG Maker มีปัญหากับการใช้งานภาษาไทยมาทุกเวอร์ชัน คนที่ใช้ภาษาไทยต้องหาสคริปต์เพิ่มเติมเอง เพื่อที่จะแสดงผลภาษาไทยได้อย่างถูกต้อง เวอร์ชันใหม่อย่าง RMMV (RPG Maker MV) ได้มีการเปลี่ยนระบบเอนจินใหม่หลายส่วน รวมทั้งเปลี่ยนไปใช้ตัวอักษรแบบ Unicode แบบเต็มตัวด้วย เมื่อเปลี่ยนไปใช้ Unicode ก็หมดปัญหาเรื่องภาษา เพราะ Unicode รองรับทุกภาษาในโลกนี้ นั่นเป็นข่าวดีสำหรับคนที่ใช้ภาษาไทยใน RMMV แต่เอ๊ะ! ทั้ง ๆ ที่ RMMV ก็เปลี่ยนไปใช้ Unicode แล้ว แต่ทำไมยังมีปัญหาในการแสดงผลภาษาไทยอยู่อีกล่ะ?



ลองพิมพ์ภาษาไทยใน RMMV
[Image: 07.png]
กล่องข้อความแสดงภาษาไทยถูกต้อง

[Image: 01.png]
หน้า Title ก็ปกติดี ทั้งตัวอักษรบน Title Bar ชื่อเกม ตัวอักษรในแถบเริ่มเกม ทุกอย่างไม่มีปัญหา

[Image: 02.png]
หน้าเมนูในเกมก็ปกติดี ทั้งชื่อตัวละครและแถบตัวเลือก

[Image: 03.png]
แถบบอกสถานที่ก็แสดงผลภาษาไทยได้อย่างถูกต้อง



วิธีแก้ปัญหาภาษาไทยใน RMMV
1. เปิดไฟล์ rpg_windows.js (อยู่ในโฟลเดอร์ js ของโปรเจคเกม) ด้วยโปรแกรม Editor ธรรมดาอย่าง Notepad
2. ลบ Window_Base.prototype.convertEscapeCharacters อันเดิมทิ้ง (ถ้าขี้เกียจมองหาเอง สามารถใช้ Edit > Find ช่วยหาได้)
[Image: 06.jpg]
3. คัดลอกสคริปต์ในหัวข้อด้านล่างนี้ไปไว้แทนที่สคริปต์ที่ลบไป (ไว้บรรทัดเดิม)
4. บันทึกไฟล์ rpg_windows.js



สคริปต์แก้ปัญหาภาษาไทย by Mikichan

......

นี่เพิ่งแค่ 69% ของบทความนี้เท่านั้น บทความฉบับเต็มมีเยอะกว่านี้อีก!


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

บทความต้นฉบับ https://planila.blogspot.com/2017/03/rpg-maker-mv.html

[Image: %25E0%25B8%259A%25E0%25B8%2597%25E0%25B8...9%2588.png]
ขอบคุณที่แบ่งปันนะคร้าบ ^^

อันนี้เป็นเคสที่เคยสงสัยเหมือนกัน ว่าทำไมมีปัญหาเฉพาะข้อความพูดคุย
บาง font มีปัญหาสระ + วรรณยุกต์ซ้อนแบบที่ท่านว่ามาเลยครับ ซึ่งจากเหตุผลที่ท่านว่ามาก็ถึงกับบางอ้อทันที Big Grin

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

[Image: Capture.jpg]

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

ซึ่งเคสนี้ตัวสคริปต์ของท่านยังแก้ปัญหาไม่ได้ครับ แต่คิดว่าน่าจะแก้ไม่ยาก สลับเงื่อนไขการตรวจสอบให้กลับตาลปัตรกัน
เช่น text = text.replace(/([ก-ฮ])/, "$1่");
ก็คือถ้าตัวอักษรใดๆ ตามด้วยวรรณยุกต์สูง ให้เปลี่ยนเป็นวรรณยุกต์ต้่ำ (จริงๆ มีเคสสระด้วย เช่น รู้ แต่ยกตัวอย่างเป็นแนวคิดเฉยๆ ครับ)

สาเหตุผมคิดว่าตัวไฟล์แต่ละฟ้อนต์อาจมีการกำหนดรูปแบบหรือ metadata ต่างกัน

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

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

อย่างไรก็ตาม ผมก็เดาเอา ไม่มีความรู้เรื่องฟอนต์หรอก ฮา

---

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

---

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

แบบข้อความในเกม
[Image: 1111111111.jpg]

แบบข้อความพูดคุย
[Image: 2222.jpg]
[Image: 5434.jpg]

สังเกตคำว่าปุ่ม แบบข้อความพูดคุย ตัวอักษรยาวจะไม่มีการเลื่อนวรรณยุกต์หรือสระไปทางซ้ายให้ครับ (อ่านเป็นบุ่ม เบิด บิด เฉยเบย *0*)
ซึ่งตอนนี้กำลังเขียนโค้ดแก้อยู่เหมือนกัน T_T คิดว่าลักษณะการแก้คือ replace string เช่นเดิมครับ เป็นอักขระแบบเลื่อนซ้ายแทน
แต่ถ้าเป็นเคสหนักสุด แบบทั้งวรรณยุกต์ลอยทั้งเลื่อนซ้าย เช่น ปิ่น โค้ดคงสับสนชีวิตน่าดู 555+

---

และก็คิดได้อีกเคส คือ ฎู กับ ฎู จะใช้อักขระสระล่าง ที่ต่ำกว่าเดิมครับ แต่คิดว่าแก้ไม่แก้ก็ได้ คงไม่มีใครใช้กัน

.
ผมเจอแต่เคสล่างแฮะ เคสบนผมเปลี่ยนฟอนต์ประจำตลอดเลยไม่เจอ
แต่จะมีปัญหากับมันลอยสูงไปมุดดินต่ำไปจนทะลุขอบนี่แหละ
splendith Wrote:มีบางฟอนต์มีปัญหาอีกประเภทหนึ่งครับ นั่นคือแสดงผลได้ สระไม่ซ้อน แต่กลับกลายเป็นว่าวรรณยุกต์ลอยแทน

เคสนี้ตัวสคริปต์ของท่านยังแก้ปัญหาไม่ได้ครับ


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



splendith Wrote:นอกจากเคสสระซ้อนแล้ว มันมีอีกเคสนึงนะครับคือ
เคสสระ / วรรณยุกต์ไม่เลื่อนซ้ายกรณีเป็นพยัญชนะตัวยาว เช่น
คำว่า ปุ่ม ในข้อความเกมกับข้อความพูดคุยจะแสดงผลต่างกันอยู่ครับ


มิกิลองไปสำรวจฟอนต์ต่าง ๆ มาเพิ่ม, พบว่าฟอนต์ต่าง ๆ นอกจากจะแยกวรรณยุกต์ตัวต่ำกับวรรณยุกต์ตัวสูงแล้ว, ยังแยกวรรณยุกต์และสระตัวบนที่ใช้คู่กับตัว ป, ฝ, ฟ ด้วย. วิธีแก้ก็ทำคล้าย ๆ กับแก้วรรณยุกต์ซ้อนกับสระตัวบนปกติ. ในส่วนนี้เดี๋ยวมิกินำไปพัฒนาเพิ่มเติม, แล้วนำสคริปต์มาแจกในเวอร์ชันใหม่ค่ะ. ขอบคุณค่ะ.



splendith Wrote:และก็คิดได้อีกเคส คือ ฎู กับ ฎู จะใช้อักขระสระล่าง ที่ต่ำกว่าเดิมครับ แต่คิดว่าแก้ไม่แก้ก็ได้ คงไม่มีใครใช้กัน


ไว้ว่าง ๆ เดี๋ยวมิกิจะทำส่วนนี้มาเพิ่มนะคะ. แต่อาจทำจะช้าหน่อยสำหรับส่วนนี้, เพราะไม่ค่อยจำเป็นเท่าไร.



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


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

ส่วนใหญ่ทุกเคสจะแก้ด้วยการ replace แต่มีปัญหาที่ผมเจอเคสนึงคือ ฟ้อนต์ที่ใช้อยู่ ตัวสระ/วรรณยุกต์ชนิดเลื่อนซ้ายหลบพยัญชนะยาว (เช่น ป ฟ) ดันเก็บด้วยรหัส UTF-16 ซึ่งการเก็บสตริงใน Javascript มาตรฐานปัจจุบัน (ECMA 5) ยังรองรับเพียง UTF-8 ผลก็คือไม่สามารถ replace font ได้ ต้องเลื่อนตำแหน่งตัวอักษรสถานเดียว ฮ่าาา

[Image: Capture.jpg]

ซึ่งตอนนี้คิดว่าแก้ปัญหาทุกเคสที่กล่าวไว้แล้ว เพียงแต่โค้ดก็น่าจะไม่ support ทุกฟอนต์ ซึ่งการจะทำให้รองรับทุกฟอนต์คงต้องเหมือนที่ท่านบอกคือคงต้องปรับโค้ดเป็นเลื่อนตำแหน่งให้ได้มากที่สุดเท่าที่เป็นไปได้ *0*

ยังไงก็ขอบคุณอีกครั้งสำหรับการแลกเปลี่ยนความคิดเห็นนะคร้าบ
.
เรื่องของ Font มันเป็นมานาน (มาก ตั้งแต่สมัยที่ยังไม่มี irpg เลยแหละ) ปัญหาตอนนี้คือมันไม่ได้อยู่ที่ระบบ Font Engine แล้วเพราะทาง Browser มีการพัฒนาส่วนนี้กันมาเรื่อยๆ (อย่างที่ลองกันไปในช่วงแรก)

แต่ปัญหาจริงๆ อยู่ที่

ระบบการแสดงทีละตัวอักษรของ RPG Maker ต่างหาก

ถ้าจะแก้ผมแนะนำว่าไปแก้พวกนี้จะให้ผลที่ดีกว่า (เพราะผมก็พลาดตอนที่ทำ script ให้กับ VXAce ไปแล้วเหมือนกัน)
(10-26-2016, 04:33 PM)admannon Wrote: [ -> ]เรื่องของ Font มันเป็นมานาน (มาก ตั้งแต่สมัยที่ยังไม่มี irpg เลยแหละ) ปัญหาตอนนี้คือมันไม่ได้อยู่ที่ระบบ Font Engine แล้วเพราะทาง Browser มีการพัฒนาส่วนนี้กันมาเรื่อยๆ (อย่างที่ลองกันไปในช่วงแรก)

แต่ปัญหาจริงๆ อยู่ที่

ระบบการแสดงทีละตัวอักษรของ RPG Maker ต่างหาก

ถ้าจะแก้ผมแนะนำว่าไปแก้พวกนี้จะให้ผลที่ดีกว่า (เพราะผมก็พลาดตอนที่ทำ script ให้กับ VXAce ไปแล้วเหมือนกัน)


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

1. ยกเลิกการใช้การแสดงทีละตัวอักษร, แล้วเปลี่ยนไปใช้การแสดงตัวอักษรทีเดียวทั้งหมด.

2. ใช้ระบบการแสดงทีละตัวอักษรเหมือนเดิม, แล้วพัฒนาระบบตรวจสอบตัวอักษรตัวอื่นที่อยู่ใกล้กัน. ระบบตรวจสอบส่วนนี้อาจจะเป็นวิธีเลื่อนตำแหน่งตัวอักษร, วิธีเปลี่ยนตัวอักษร หรือวิธีอื่น ๆ ก็ได้. สคริปต์ที่มิกินำมาแจกใช้วิธีเปลี่ยนตัวอักษร, ซึ่งมิกิคิดว่าวิธีนี้เป็นวิธีที่ง่ายที่สุดแล้ว (ในกรณีที่แก้สคริปต์แค่นิดเดียว).

วิธีแรกมีข้อดีตรงที่ไม่ต้องแก้ฟอนต์, ไม่ต้องแก้ตัวอักษร, ไม่ต้องห่วงเรื่องปัญหาระหว่างฟอนต์. แต่มิกิคิดว่าหลายคนคงชอบการแสดงทีละตัวอักษรมากกว่าการแสดงตัวอักษรทีเดียว, และการเปลี่ยนไปใช้การแสดงตัวอักษรทีเดียวต้องแก้สคริปต์หลายส่วน. มิกิเลยเลือกใช้วิธีที่สองแทนค่ะ, น่าจะเหมาะสมกับหลาย ๆ คนมากที่สุด.

ส่วนตัวมิกิคิดว่าวิธีแรกค่อนข้างยากกว่าและซับซ้อนกว่า. แต่ถ้าใช้วิธีที่สองแล้วยังมีปัญหามาให้ตามแก้อีกเยอะ, มิกิก็จะพัฒนาสคริปต์แก้ด้วยวิธีแรกมาแจกควบคู่กับวิธีที่สอง, แล้วปล่อยให้คนที่จะใช้เลือกเอาเองว่าจะใช้สคริปต์ตัวไหน.

ขอบคุณค่ะ.
เสร็จซะที (น่าจะประมาณ 95% ที่รองรับ ที่เหลือคือฟอนต์มันเป็นอย่างนั้นอยู่แล้ว)

ก่อนทำ
[Image: G1fce19.png]

หลังทำ
[Image: jJSGJ9j.png]

เปลี่ยน Font ด้วย
[Image: gPFr3zS.png]

ส่วนนี้ก็ Plugin เนอะ
Code:
//=============================================================================
// ThaiMessageBoxFix.js
//=============================================================================

/*:
* @plugindesc
* Fix font render that contain upper or/and lower glypts in message box.
* @author Admannon
*
* @help This plugin does not provide plugin commands.
*/

(function () {

   Window_Base.prototype.TH_VOVEL_MARK = "ุูึัี๊้็่๋ิฺื์ํ";

   var _WinBase_convertEscChar = Window_Base.prototype.convertEscapeCharacters;
   Window_Base.prototype.convertEscapeCharacters = function (text) {
       text = _WinBase_convertEscChar(text);
       text = text.replace(new RegExp("([" + this.TH_VOVEL_MARK + "])ำ", "g"), "ํ$1า");
       text = text.replace(/ำ/g, "ํา");
       return text;
   };

   var _Window_Base_processNormChar = Window_Base.prototype.processNormalCharacter;
   Window_Base.prototype.processNormalCharacter = function (textState) {
       var c = textState.text[textState.index++];
       var d = textState.text[textState.index];
       while (this.TH_VOVEL_MARK.contains(d)) {
           c += textState.text[textState.index++];
           d = textState.text[textState.index];
       }
       var w = this.textWidth(c);
       this.contents.drawText(c, textState.x, textState.y, w * 2, textState.height);
       textState.x += w;
   };

})();


ปล. แก้ ( c ) ที่บอร์ดนี้มันดันแก้เป็น ©

edited เพิ่ม by OP_Jum_RPG
ดาวน์โหลดเวอร์ชั่นแก้ไข (อันเดียวกับโพส 12)
https://gist.github.com/admannon/700168e...840f7473c4

/puke/puke/puke/puke/puke/puke/puke/puke/puke/puke/puke/puke/puke/puke/puke
.
เข้าใจแนวคิดของท่าน admannon แล้วครับ
น่าสนใจมาก คิดว่าน่าจะตอบโจทย์ฟอนต์ทุกประเภทได้จริงๆ

ขอบคุณมากๆ สำหรับแนวคิดครับผม Big Grin Big Grin
.
(10-26-2016, 09:15 PM)admannon Wrote: [ -> ]ส่วนนี้ก็ Plugin เนอะ
[shcode=rails]
//=============================================================================
// ThaiMessageBoxFix.js
//=============================================================================

/*:
* @plugindesc
* Fix font render that contain upper or/and lower glypts in message box.
* @author Admannon
*
* @help This plugin does not provide plugin commands.
*/

(function () {

Window_Base.prototype.TH_VOVEL_MARK = "ุูึัี๊้็่๋ิฺื์ํ";

var _WinBase_convertEscChar = Window_Base.prototype.convertEscapeCharacters;
Window_Base.prototype.convertEscapeCharacters = function (text) {
text = _WinBase_convertEscChar(text);
text = text.replace(new RegExp("([" + this.TH_VOVEL_MARK + "])ำ", "g"), "ํ$1า");
text = text.replace(/ำ/g, "ํา");
return text;
};

var _Window_Base_processNormChar = Window_Base.prototype.processNormalCharacter;
Window_Base.prototype.processNormalCharacter = function (textState) {
var c = textState.text[textState.index++];
var d = textState.text[textState.index];
while (this.TH_VOVEL_MARK.contains(d)) {
c += textState.text[textState.index++];
d = textState.text[textState.index];
}
var w = this.textWidth©;
this.contents.drawText(c, textState.x, textState.y, w * 2, textState.height);
textState.x += w;
};

})();

[/shcode]

ผมใส่ปลักอินนี้แล้วมันไม่หายอ่ะครับ ฟ้อนท์เริ่มต้นครับผม
Pages: 1 2 3