Sitemap

From Zero to Visual Novel 2: Excel-Script and Automated

5 min readMay 29, 2025

--

Introduce

  • จากบทความที่แล้ว (From Zero to Visual Novel) ถ้าเพื่อนๆ Follow ตามบทความจนจบ เพื่อนๆ น่าจะได้พื้นฐานพอในการสร้าง Visual Novel ของตัวเองแล้วนะครับ
  • เพื่อนๆ น่าจะสังเกตได้ว่า โค๊ต Renpy นั้นมี “ความซ้ำซ้อน” มากครับ
สังเกตว่าจากบทเปล่าๆ เราจำเป็นต้องเติมอะไรที่ ”ซ้ำซ้อน” บ้าง (ภาษาโปรแกรมมิ่งเรียกว่า boilerplate) ; dissolve เอย , _th _en, path ยาวๆของ voice เอย
  • บทความนี้จะเป็นการแนะนำให้เพื่อนๆ ลดงาน boilerplate เหล่านี้ ด้วยการทำงานผ่าน Excel แล้วใช้ Script เพื่อแปลงเป็น Renpy แทน

คนที่เขียน Automated จะต้องเป็น “คนที่เข้าใจสิ่งนั้นๆอย่างลึกซึ้งเท่านั้น” ถ้าเพื่อนๆยังใช้ Renpy ไม่คล่อง อยากจะให้ฝึกเขียนแบบปกติให้คล่องก่อนนะครับ

Advantages of using Excel

  • ก่อนที่เราจะพูดถึง “การใช้ Script แปลง Excel ให้กลายเป็น Renpy Code” เราควรจะเข้าใจตรงกันก่อนว่า Excel ที่ว่าคืออะไร
บทแรกของ Memary: Memory of the nameless one
  • ถ้าเพื่อนๆ มอบบทข้างบนให้ Programmer เพื่อนๆคิดว่า Programmer ในทีมเพื่อนๆ จำเป็นต้องเดาอะไรบ้างครับ เพื่อให้เขียน Renpy ขึ้นมาได้
  • Background ใช้เป็นอะไร?, มี SFX ไหม?, มี Effect พิเศษอะไรไหม?, แล้วแมวที่เจอนี่ มันต้องทำหน้ายังไง?, เสียงแมวใช้ Voice file ไหน?
  • ซึ่งมีโอกาสไม่น้อยเลย ที่ภาพในหัว Programmer, Director, Writer จะออกมาเป็นคนละภาพกันครับ
Script บทแรกของ Re:Fragment ~Absolute Ambition~
  • ทางกลับกัน ถ้าเป็น Excel นี้, Programmer ในทีมเพื่อนๆ จะทำงานได้ง่ายกว่าใช่ไหมครับ
  • Excel ที่เรากำลังพูดถึงในบทความนี้จะเป็นตัวแทนของ “ภาพในหัวของผู้กำกับ” ที่ต้องการให้ Programmer ทำตามครับ
  • ข้อดีที่สุดของ Excel นี้คือ “ภาพของทั้งทีมจะเป็นภาพเดียวครับ” ซึ่งทำให้การสื่อสารกันในทีมนั้นทำได้ง่ายกว่าครับ
  • ถือเป็นการรวมงานของทุกฝ่ายด้วยครับ ทั้ง ภาพของ Illustrator, บทของ Writer, Voice ของฝั่งนักพากย์ และอาจจะรวมถึงการแปลภาษา ไว้ในที่เดียวครับ
  • อาจมีข้อเสียคือ เรากำลัง Double Work อยู่ (คิดภาพว่า แทนจะเขียน Code ไปเลย เราสร้าง Excel มาก่อน -> เอา Excel ไปเขียนเป็น Code ) จึงเป็นเหตุผลที่หลายๆทีม อาจจะข้ามขั้นตอนการสร้าง Excel นี้ครับ

Advantages of using Automated Scripts

  • ลดงาน boilerplate ที่เราต้องเขียนไปได้เยอะมาก
เมื่อเปรียบเทียบกัน การเขียนใน Excel นั้นสั้นกว่าอย่างชัดเจน เพียง 5 Line เราลดการพิมพ์ dissolve 5 คำ , double quote 20 ครั้ง+ แถมยังอ่านเข้าใจได้ง่ายกว่าด้วย
  • ถ้าทีมเพื่อนๆ มีการสร้าง Excel อยู่แล้ว เราแทบจะลดงาน Scripting ได้แบบ 90%+ เลยครับ เนื่องจากผ่าน Automated หมดครับ
  • ลดความผิดพลาดที่เกิดขึ้นจากการเขียน Code ของเราได้มากครับ ถ้าผิด = Excel เขียนผิดเลย ซึ่งจริงๆ หาความผิดพลาดใน Excel มันง่ายกว่าใน Code มากครับ
  • แบ่งงานที่ Programmer ถือให้เพื่อนในทีมช่วยได้ สมมุติถ้า Illustrator ทีมเพื่อนๆ วาดรูปไม่ทัน เพื่อนในทีมช่วยไม่ได้แน่นอนครับ
  • แต่ถ้า Programmer ทำงาน Script ไม่ทัน ยังอาจจะแบ่งให้ Director, Writer ช่วยสร้าง Excel ขึ้นมาได้ครับ (เผลอๆ 2 Role นี้ ภาพอาจชัดกว่า Programmer ด้วยซ้ำไปครับ)

Disadvantages of using Automated Scripts

  • “ไม่มี Automated ใดที่ทำงานได้อย่างสมบูรณ์แบบ” บางครั้งจะ Director อาจจะเห็นภาพที่ Automated ไม่ Support ครับ; Case นี้ Programmer เองจำเป็นต้องเขียนเองอยู่ดีครับ
  • Automated บัคเยอะมากในการพัฒนาครับ เพราะเราต้องเขียน Automated ให้ครอบคลุมที่สุดครับ (ทางผู้เขียนบทความใช้จนเกมส์จะจบแล้ว ยังเจอบัคในบทท้ายๆ ได้อยู่เลยครับ)
  • เขียนยากระดับหนึ่งครับ รอบนี้สาวบ้านที่เพื่อนๆ Assign เป็น Programmer อาจจะทำไม่ได้แล้วครับ
  • ต่ำๆคือต้องเข้าใจ Renpy ระดับหนึ่งจนเห็นรูปแบบซ้ำๆ ได้ครับ
  • แต่ที่ยากที่สุดคือ ต้องรู้ว่า การ Automated feature นั้นๆ มันเขียนยากแค่ไหน และคุ้มค่าการเขียนไหมนะครับ
  • ยกตัวอย่างง่ายๆ Automated Voice file เป็นสิ่งที่เขียนได้ง่ายครับ ใช้แค่ 1–2 line น่าจะทำงานได้ครับ แถมทั้งเกมส์ถ้าเรา Full voice เราใช้ Feature นี้หลายร้อยครั้งครับ ไม่มีเหตุผลอะไรที่จะไม่ Implement ครับ
  • อีกตัวอย่างคือ Choice ครับ อันนี้ถือว่า implement ได้ค่อนข้างยาก แถมทั้งเกมส์ เราน่าจะใช้ Feature นี้เพียงไม่กี่ครั้งครับ
  • แต่ถ้า Visual Novel ของเพื่อนๆ เป็นแบบ Gal game ยุคเก่าๆเลย การ Implement Feature นี้ อาจจะคุ้มค่าขึ้นมาครับ

สำหรับบทความนี้ ผู้เขียนแนะนำให้เพื่อนๆ Clone Project เริ่มต้นมาจาก GitHub ของผู้เขียนนะครับ โดย Excel ที่จะนำมาแปลงเป็น Renpy Script สามารถ Download ได้จาก Link นี้นะครับ ซึ่งจริงๆใน GitHub ผู้เขียนได้แนบ Excel ไว้ให้แล้วล่ะครับ

เมื่อเพื่อนๆ ลองเปิด Excel ดู จะได้เป็นหน้าตาประมาณนี้ครับ

File Structure

game/

├── audio/
│ ├── bgm/ # เพลงประกอบหรือเพลงพื้นหลัง
│ └── sfx/ # เอฟเฟคเสียงต่างๆ

├── gui/ # GUI

├── images/
│ ├── bg/ # ภาพพื้นหลัง
│ ├── character/ # Sprite ตัวละคร
│ └── sd/ # ภาพ SD

├── saves/ # ไฟล์บันทึกเกม

├── tl/ # ไฟล์แปลภาษา (Translation)

├── gen.py # Automated Script ที่เราใช้ในบทความนี้ครับ
├── char.rpy # การกำหนดตัวละคร
├── gui.rpy # การกำหนดค่า GUI
├── LayijiMahaniyomV1_61.ttf # ไฟล์ฟอนต์
├── options.rpy # การตั้งค่าต่างๆ ของเกม
├── screens.rpy # การกำหนดหน้าจอต่างๆ
└── script.rpy # สคริปต์หลักของเกม

#จะเห็นว่า Sturcture ใกล้เคียงกับเดิมเลย แค่เพิ่ม gen.py เข้ามาครับ

Architecture

  • ถ้าเพื่อนๆใช้ Renpy แสดงว่า เพื่อนๆน่าจะมีความคุ้นเคยกับภาษา Python ในระดับหนึ่ง คืออย่างน้อยก็ต้องมีในเครื่องแน่ๆ ล่ะครับ Automated ของเราจึงจะใช้ภาษานี้มา Implement นะครับ
  • อีกทั้งเป็นภาษา Script ทำให้รันได้ง่าย จัดการ Environment ได้ง่ายครับ
  • ในเมื่อเราทำงานกับ Table Data ผู้เขียนจึงใช้ Pandas เป็น Reader นะครับ เนื่องจากใช้งานได้ง่ายมาก แล้วโค๊ตค่อนข้าง Clean ครับ
เป็นตัวเดียวกับที่แก๊ง Data Science ชอบใช้กันนั่นละครับ

Initialization

#gen.py

import pandas as pd
FILE_NAME = "renpy_script_tutorial1.csv"
VOICE_BASE_PATH="audio/voice"
VOICE_PATH = ""
SFX_BASE_PATH="audio/sfx"
data = pd.read_csv(FILE_NAME,encoding="utf-8")
data = data.fillna("")

#เป็นการประกาศ Constant ของ Project ทั่วไปครับ
#encoding="utf-8" ใส่เพื่อให้มันอ่านภาษาไทยได้ครับ ไม่งั้นจะเป็นภาษาอะไรแปลกๆเลย
#fillna("") คือการเติม NaN (ค่าว่าง) ด้วย "" (String เปล่า) ครับ
#จะไม่ต้องลำบาก check เป็น NaN ไหม ตลอดครับ


Main Loop & Assign

for i,c in data.iterrows():
### Assign ##############################

bg = c['bg']
bg_effect = c['bg_effect']
bgm = c['bgm']
character1 = c['character1']
character2 = c['character2']
face = c['face']
who_talk = c['who_talk']
talk = c['talk']
voice = c['voice']
sfx = c['sfx']

#เป็น Main Loop ที่เราจะวิ่งไปในทุก Row ใน Table ครับ
#ในแต่ละ C (คือ 1 Row) จะประกอบด้วยหลายๆ Column ถูกไหมครับ
#ให้เราเก็บ Value ต่างๆใน Excel ตามชื่อ Column เลยครับ

Action

### Action ###############################    
if(bg):
print(f'scene {bg} with Dissolve(1.0)')

if(bgm and bgm != 'stop'):
print(f"stop music")
print(f'play music "audio/bgm/{bgm}.mp3" volume 0.5')

if(bgm =='stop'):
print(f"stop music")

show_charector(character1, character2)

if(sfx):
print(f'play sound "{SFX_BASE_PATH}/{sfx}.mp3"')

if(voice):
print(f'play sound "{VOICE_BASE_PATH}/{who_talk}/{VOICE_PATH}/{voice}.mp3"')

if(bg_effect):
print(f'{bg_effect}')

if(talk):
if(who_talk):
print(f'{who_talk} {(face)} "{talk}" with dissolve')
else:
print(f'th "{talk}" with dissolve')

print(f"return")

# ล้อจากบทที่แล้วมาครับ สังเกตว่า แค่ครอบคำสั่ง renpy ที่เราใช้ปกติใน Method print ครับ
# print(f'') ทำให้เราสามารถใช้ Variable ใน คำสั่ง print ได้ครับ
# โดยเราจะใช้ Variable จากหัวข้อข้างบนครับ
# น่าสนใจคือ show_charector เป็น Method ที่เรายังไม่ได้ define ครับ โดยจะอธิบายเพิ่มเติมในหัวข้อถัดไป
# อย่าลืมปิดด้วย return นะครับ

Show Character Method

def show_charector(charector1,charector2):

# ถ้ามี Character ใหม่ จะเอาตัวเก่าออกหมดก่อนครับ
if (character1 != "" or character2 != ""):
print(f'hide eri')
print(f'hide ayase')
print(f'hide mikan')
# ถ้าไม่มี Character เลย จะไม่ทำ Method นี้ครับ
if ( charector1 == "" ):
return

#2 Charector Case
# ถ้ามี Chartertor2 show Character ทั้งสอง ซ้ายและขวาครับ
if ( charector2 != ""):
print(f'show {character1} normal at left')
print(f'show {character2} normal at right')
return

#1 Character Case
# ถ้ามี 1 Character จะ Show Character1 ครับ
print(f'show {character1} normal at center')
return

# Method นี้จะซับซ้อนหน่อย เลยแยกมาเป็น Method ครับ
# ใช้สำหรับการเปลี่ยน Character ครับ

How to Run

set PYTHONIOENCODING=utf-8
set PYTHONLEGACYWINDOWSSTDIO=utf-8
python gen.py > chap1.rpy

# Automated Script นี้ต้องรันผ่าน Cmd(Windows) or Terminal(Osx, Linux) นะครับ
# 2 Line แรกเป็นการแก้ปัญหาที่ Windows ไม่ทราบว่าเรากำลังจะ Print ภาษาไทยอยู่ครับ
# print gen.py เป็นการ run python แบบปกติครับ
# > chap1.rpy เป็นคำสั่ง pipeline ของ CMD
# ปกติแล้ว print จะแสดงผลลัพท์ของโปรแกรมผ่านทาง CMD ใช่ไหมครับ
# การใช้ > chap1.rpy ทำให้นำผลลัพท์ไปเก็บใน File chap1.rpy แทนครับ
# Run เสร็จแล้ว อย่าลืมจัด indent + ครอบด้วย Label ด้วยนะครับ
เพื่อนๆสามารถใช้ได้ทั้ง cmd , หรือ terminal ที่ติดมากับ VSCode ได้เลยนะครับ อย่าลืม pip install pandas ก่อนนะครับ

It’s your turn

  • ถ้าเพื่อนๆ Follow ตาม Medium นี้; น่าจะพอเห็นภาพของการใช้ Automated มาแปลง Excel เป็น Program แล้วใช่ไหมครับ
  • แต่จริงๆแล้ว ตัวอย่างโค๊ตที่ผู้เขียนยกมา ยังมีจุดให้ปรับปรุงอีกเยอะมากครับ
  • จากโค๊ตนี้ เราไม่สามารถกำหนดการแสดงผลให้ในจอไม่มี Sprite เลยได้ครับ
  • การ Hide ทุก Character ตอนที่มีตัวละครใหม่เข้ามา นั้นทำให้โค๊ตอ่านยากโดยไม่จำเป็นครับ สมมุติเพื่อนๆ มี 5–6 ตัวละคร ตัวละครละ 2 ชุดนี่ เราได้ Hide กัน 12 Line++ ครับ
  • เราควรจะ Hide แค่ Character ที่อยู่ในจอเท่านั้นครับ
  • ยังไม่ Support 2 ภาษาครับ
  • หลาย Feature อย่าง Assign Variable, Choice ยังไม่ Support ครับ

Extra

  • cha.rpy เป็นการ Define Sprite Image ของ Character ทั้งหมดครับ
  • ซึ่งรวมเป็น 1,000 Line เลย Case แบบนี้ไม่ใช่ Scale ที่ควรจะเขียนเองครับ (ขนาดมีแค่ 3 ตัวละคร ตัวละครละชุด)
  • อย่าง Re:Fragment ~Absolute Ambition~ File นี้มีขนาดราวๆ 12,000 Line ครับ
  • ซึ่งเราจะไม่เขียนเองแน่นอนครับ เราจะใช้ gencharacter.py ในการ Gen ขึ้นมาครับ
  • ซึ่งผู้เขียนสัญญาว่าจะเอามาเล่าให้ฟังในบทหน้าๆ แน่นอนครับ แต่ถ้าแกะ Code ดูเองเลย จะเข้าใจได้ว่าไม่มีอะไรมากครับ LOL

Epilogue

  • บทความนี้ถือว่าเป็นความท้าทายของทั้งผู้เขียน และเพื่อนๆที่ ติดตามมากๆ ครับ เนื่องจากความยากเพิ่มจากบทแรกอย่างก้าวกระโดดเลยครับ
  • นอกจากที่เพื่อนๆ ต้องเขียน Renpy เป็นแล้ว ยังต้องเข้าใจ Python ในระดับหนึ่ง, ต้องเข้าใจ Basic Terminal ด้วยครับ
  • และที่ยากจริงๆคือ “เราไม่สามารถ Automated ทุกอย่างได้ครับ” การจะเลือกว่า จะ Automated ใน Feature ไหนนั้น ขึ้นอยู่กับ ลักษณะ Visual Novel ของเพื่อนๆ เลยครับ
  • แถม Debug ได้ยากมากด้วยครับ ถ้าเพื่อนๆ คิด Case ได้ไม่ครอบคลุมพอครับ
  • แน่นอนว่า ทีมเพื่อนๆ อาจจะไม่ได้ใช้ Excel Format เดียวกับทีมของผู้เขียน (หรืออาจจะไม่มีเลยก็ได้ lol)
  • ผู้เขียนจึงอยากให้มองว่า บทความนี้เป็นเพียง Inspire ให้เพื่อนๆ เท่านั้นครับ การจะนำไปใช้จริงนั้น ต้องพัฒนาอีกระดับนึงเลยครับ (แต่จริงๆแก้ให้ Hide Character ได้ มันก็ใช้จริงได้ 80–90% แล้วนะครับ)
  • จากประสบการณ์ตรงเลยคือ Memary: Memory of the nameless one นั้น ผู้เขียนไม่ได้ทำผ่าน Automated ครับ
  • จริงๆ เกมส์นั้นถือว่าไม่เหมาะกับการ Automated เท่าไหร่ เนื่องจาก Condition, if else Case เยอะแบบมากๆ ครับ
  • แต่จริงๆแล้ว จังหวะที่ใส่ Voice , English Translate นี่ ทำเองโดยไม่ผ่าน Script นี่ เสียเวลามากๆ ครับ
  • ท้ายที่สุด ก็ขอขอบคุณทาง Rayedge จากทีม AstralSeal สำหรับ Asset ที่ใช้ในบทความ รวมถึงเพื่อนๆที่ตามกันมาถึงบทความที่ 3 ของ Series Visual Novel นะครับ

--

--

No responses yet