30 กรกฎาคม 2562

Ren'Py พื้นฐาน | บทที่ 4 ตัวแปรและตัวดำเนินการ

บทนี้จะเป็นเนื้อหาเกี่ยวกับการเขียนโปรแกรม ผู้อ่านที่ไม่เคยเขียนโปรแกรมมาก่อนไม่ต้องกังวลไป โปรแกรม Ren'Py ใช้รูปแบบเดียวกับภาษา Python ซึ่งเข้าใจง่ายกว่าภาษาคอมพิวเตอร์หลายตัว (เช่น C, Java) จุดประสงค์ของบทนี้คือเพื่อให้ผู้อ่านใช้งานตัวแปรเบื้องต้นได้ ไม่ได้สอนภาษา Python เต็มตัว ผู้เขียนละเนื้อหาเชิงเทคนิคที่ซับซ้อนไว้ เพื่อให้นักสร้างเกมที่ไม่เคยเขียนโปรแกรมสามารถเข้าใจได้ง่าย ๆ สำหรับผู้อ่านที่ต้องการเขียนโปรแกรมเต็มตัวให้ศึกษาภาษา Python จากตำราสอนเขียนโปรแกรม

คำสั่งของโปรแกรม Ren'Py ไม่มีตัวแปรใด ๆ เลย นั่นหมายความว่าเราไม่สามารถเก็บข้อมูลลงหน่วยความจำได้ แต่เกมแนว Visual Novel หลายเกมจำเป็นต้องเก็บข้อมูล เช่น เก็บค่าความรักของนางเอก, หรือเก็บตัวเลือกที่ผู้เล่นเคยเลือก เพื่อนำไปสู่ฉากจบที่แตกต่างกัน กรณีที่ต้องใช้ตัวแปรหรือเก็บข้อมูลแบบนี้ ถึงคราวที่ต้องใช้ภาษา Python แล้วล่ะ!

เนื้อหาในบทนี้จะเป็นเนื้อหาทฤษฎี เราจะนำเนื้อหาในบทนี้ไปต่อยอด และลงมือปฏิบัติจริงกันในบทต่อไป


ประเภทของตัวแปร

ตัวแปร (Variable) คือสิ่งที่เก็บข้อมูล เมื่อเกมหรือโปรแกรมทำงานบางครั้งมีข้อมูลที่ต้องใช้งานต่อในอนาคต เราต้องเก็บข้อมูลนั้นไว้ สิ่งที่เก็บข้อมูลก็คือตัวแปร เมื่อถึงเวลาที่ต้องการก็เรียกใช้ข้อมูลจากตัวแปรนั้น
(เชิงเทคนิค : ในทางทฤษฎีตัวแปรเป็นเพียงสิ่งที่สมมติขึ้น เพื่อใช้อ้างอิงตำแหน่งที่เก็บข้อมูลในหน่วยความจำ ตัวแปรไม่ได้เก็บข้อมูลจริง ๆ แต่ตามตำรามักสอนว่าตัวแปรเก็บข้อมูล เพื่อให้คนที่เพิ่งเรียนเขียนโปรแกรมเข้าใจง่าย)

ตัวแปรที่ควรทราบในภาษา Python มี 2 ประเภทได้แก่
  • ตัวแปรตัวเลข (Number) เก็บข้อมูลที่เป็นจำนวนเต็ม (Integer) หรือทศนิยม (Floating-Point) เช่น 0, -5, 91, -12.67
  • ตัวแปรข้อความ (String) เก็บข้อมูลที่เป็นตัวอักษรหรือข้อความ เช่น "A", "Planila Game Developer", 'Visual Novel'

ภาษา Python แตกต่างจากหลายภาษา (เช่น C, Java) ตรงที่ตัวแปรจะถูกประกาศทันทีที่ใช้งาน ไม่ต้องประกาศตัวแปรล่วงหน้า และไม่ต้องระบุประเภทของตัวแปร วิธีใช้ตัวแปรเพียงแค่ใส่ชื่อของตัวแปร (Identifier) และกำหนดค่าให้ตัวแปร ถ้าตัวแปรนั้นไม่เคยมีมาก่อนจะถือว่าเป็นการประกาศตัวแปรโดยอัตโนมัติ และโปรแกรมจะเลือกประเภทของตัวแปรให้โดยอัตโนมัติ ตัวอย่างเช่น


ตัวแปรตัวเลขแบ่งย่อยเป็นตัวแปรจำนวนเต็ม (Integer) และตัวแปรทศนิยม (Floating-Point) ความแตกต่างคือการเก็บค่าทศนิยม เช่น x = 1 เป็นตัวแปรจำนวนเต็ม, แต่ y = 1.0 เป็นตัวแปรทศนิยม (สังเกตจากการใส่จุดทศนิยม ไม่สนใจว่าเลขหลังทศนิยมคือเลขอะไร)

ข้อความหรือตัวอักษรที่ใส่ในตัวแปรข้อความต้องอยู่ในเครื่องหมาย ' ' หรือ " " เช่น name = 'Planila' หรือ name = "Planila" ก็มีค่าเหมือนกัน ภาษา Python ไม่มีตัวแปรตัวอักษร (Character) โดยเฉพาะเหมือนภาษา C ดังนั้นตัวแปรที่เก็บตัวอักษรเพียงตัวเดียวจะถูกจัดอยู่ในตัวแปรข้อความ

Boolean คือส่วนหนึ่งของ Integer

ภาษา Python ไม่มีตัวแปรตรรกศาสตร์ (Boolean) โดยเฉพาะเหมือนภาษา C หรือ Java แต่สามารถเก็บค่าทางตรรกศาสตร์ลงในตัวแปรจำนวนเต็มได้ (Boolean เป็นส่วนหนึ่งของ Integer) ผลลัพธ์ทางตรรกศาสตร์ในภาษา Python ได้แก่ 0 (และ 0.0) คือเท็จ (False) และนอกจากนั้นคือจริง (True) แต่โดยทั่วไปมักกำหนดให้จริงเท่ากับ 1 การกำหนดค่าตรรกศาสตร์ต้องใส่เป็นตัวเลขเท่านั้น เช่น love = 1 ไม่สามารถใส่เป็น True หรือ False ได้

นอกจากนี้ภาษา Python ยังมีตัวแปรประเภทอื่น เช่น Lists, Tuple, Set ตัวแปรเหล่านี้สามารถใช้ในโปรแกรม Ren'Py ได้ แต่ผู้เขียนจะไม่สอนในบทความนี้ เนื่องจากเป็นเนื้อหาที่ลึกและไม่จำเป็นสำหรับนักสร้างเกมมือใหม่


ตัวดำเนินการ (Operator)

นอกจากตัวแปรสามารถเก็บข้อมูลตามหัวข้อที่แล้ว เรายังสามารถคำนวณหรือเปรียบเทียบค่าแล้วเก็บลงในตัวแปรได้ การคำนวณหรือเปรียบเทียบต้องใช้ตัวดำเนินการ ตัวดำเนินการที่ควรทราบในภาษา Python ได้แก่

ตัวดำเนินการคณิตศาสตร์ (Arithmetic Operator)

ตัวดำเนินการคำอธิบายตัวอย่าง
+บวกa = 35 + 4.2   # เก็บค่า 39.2
-ลบb = 1 - 4   # เก็บค่า -3
*คูณc = -12 * 9   # เก็บค่า -108
/หาร (ปกติ)d = 87 / 5   # เก็บค่า 17.4
//หารปัดเศษลงe = 87 // 5   # เก็บค่า 17
%หารเอาเศษ (Modulo)f = 87 % 5   # เก็บค่า 2
**ยกกำลังg = 2 ** 8   # เก็บค่า 256

ถ้าจำนวนเต็มดำเนินการกับจำนวนทศนิยม ผลลัพธ์ที่ได้จะเป็นจำนวนทศนิยม เช่น 23.0 + 4 หรือ 23 + 4.0 จะได้เท่ากับ 27.0 (ไม่ใช่ 27) โปรแกรม Ren'Py เวอร์ชันปัจจุบัน (7.3.2) อ้างอิงภาษา Python 2.7 (Python เวอร์ชันเก่า) ทำให้จำนวนเต็มหารจำนวนเต็ม ได้ผลลัพธ์เป็นจำนวนเต็มที่ปัดเศษลงเสมอ แต่ถึงอย่างนั้นโปรแกรม Ren'Py เองก็รองรับภาษา Python 3 เป็นต้นไปเหมือนกัน

บทความที่น่าสนใจ
[Q&A] ทำไม x = x + 1 | คำถามที่มือใหม่หลายคนสงสัย

ตัวดำเนินการเปรียบเทียบ (Comparison Operator)

ตัวดำเนินการคำอธิบายตัวอย่าง
<น้อยกว่าa = 4 < -6   # เก็บค่า 0
>มากกว่าb = 50.1 > 50   # เก็บค่า 1
==เท่ากับc = 12 == 9   # เก็บค่า 0
!=ไม่เท่ากับd = 12 != 9   # เก็บค่า 1
<=น้อยกว่าหรือเท่ากับe = 0 <= 0.9   # เก็บค่า 0
>=มากกว่าหรือเท่ากับf = 0 >= 0   # เก็บค่า 1

หมายเหตุ : ภาษา Python เก็บค่าตรรกศาสตร์เป็นจำนวนเต็ม โดย 0 คือเท็จ (False) นอกจากนั้นคือจริง (True)

ตัวดำเนินการตรรกศาสตร์ (Logical Operator)

ตัวดำเนินการคำอธิบายตัวอย่าง
andและ
(จริง = จริงทั้งหมด)
a = 1 and 0   # จริงและเท็จ เก็บค่า 0
orหรือ
(จริง = จริงอย่างน้อยหนึ่ง)
b = (-10 > -5) or (2 == 2)   # เก็บค่า 1
notค่าตรงข้าม
(จริงเป็นเท็จ, เท็จเป็นจริง)
c = not 0   # ค่าตรงข้ามของเท็จ เก็บค่า 1
d = not (7.9 < 8)   # เก็บค่า 0

หมายเหตุ : ภาษา Python เก็บค่าตรรกศาสตร์เป็นจำนวนเต็ม โดย 0 คือเท็จ (False) นอกจากนั้นคือจริง (True)

ถ้ามีตัวดำเนินการเปรียบเทียบอยู่แล้ว จะใช้ค่าที่เปรียบเทียบมาดำเนินการตรรกศาสตร์ เช่น (7.9 < 8) and (9 * 3 == 27) ให้แยกเป็น 7.9 < 8 ได้เท่ากับ 1 (จริง), 9 * 3 == 27 ได้เท่ากับ 1 (จริง) จากนั้น 1 and 1 ได้ผลลัพธ์เป็น 1 (จริง)


เขียนโปรแกรม Python ใน Ren'Py

แม้ว่าภาษา Ren'Py จะมีรูปแบบคล้ายกับภาษา Python แต่ก็ถือว่าเป็นคนละภาษากัน ไม่สามารถใส่ภาษา Python ลงในไฟล์สคริปต์โดยตรงได้ เราต้องบอกโปรแกรม Ren'Py ว่านี่คือโค้ด Python ไว้ด้วย วิธีการใส่โค้ด Python มี 2 วิธี

$

วิธีแรกคือการใส่เครื่องหมาย $ นำหน้าบรรทัดที่เป็นโค้ด Python ถ้ามีโค้ด Python หลายบรรทัดต้องใส่เครื่องหมาย $ นำหน้าทุกบรรทัด ตัวอย่างเช่น


python:

วิธีที่สองคือการใส่คำสั่ง python: จากนั้นตามด้วยบล็อกของโค้ด Python จำนวนกี่บรรทัดก็ได้ วิธีนี้สะดวกกว่าวิธีแรกเมื่อโค้ด Python มีหลายบรรทัด ถ้านำตัวอย่างในวิธีแรกมาเขียนใหม่ด้วยวิธีที่สองจะได้ว่า



คำสั่งประมวลผลล่วงหน้า

คำสั่งประมวลผลล่วงหน้า (Preprocessor Directive) คือคำสั่งที่ทำงานก่อนเกมของเราจะทำงานจริง (ทำงานก่อน Compile เสียอีก) ฟังแล้วงง ทำงานก่อนทำงานจริง? อธิบายง่าย ๆ คือคำสั่งประมวลผลล่วงหน้าจะแซงคิวทุกคำสั่งในไฟล์สคริปต์ ปกติเกมจะทำงานจากบรรทัดบนลงบรรทัดล่างทีละบรรทัด แต่คำสั่งประมวลผลล่วงหน้าไม่ว่าจะอยู่ส่วนใดของไฟล์สคริปต์ ก็จะทำงานเป็นลำดับแรกเสมอ
(เชิงเทคนิค : ในทางทฤษฎีคำสั่งประมวลผลล่วงหน้าจะถูกแปลงเป็นคำสั่งธรรมดาก่อนการ Compile คำสั่งนั้นไม่ได้ทำงานก่อนการ Compile จริง ๆ)

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

init python:

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


define

อีกคำสั่งหนึ่งคือคำสั่ง define แล้วตามด้วยการประกาศตัวแปร คำสั่ง define คล้ายกับคำสั่ง init python: แต่คำสั่ง define ใช้ได้เฉพาะการแซงคิวเพื่อประกาศตัวแปรเท่านั้น และต้องใช้ได้ครั้งละบรรทัดเท่านั้น ถ้ามีหลายบรรทัดต้องใส่คำสั่ง define นำหน้าทุกบรรทัด ตัวอย่างเช่น


จากตัวอย่างข้างบนสังเกตว่า คำสั่งที่ประกาศตัวแปร e อยู่ด้านล่างคำสั่งที่ใช้ตัวแปร e ถ้าเราประกาศตัวแปร e ด้วยคำสั่งปกติ (ไม่ใส่คำสั่ง define นำหน้า) เมื่อทดสอบเกมจะแจ้ง Error เพราะตัวแปร e ไม่เคยถูกประกาศมาก่อน แต่ในตัวอย่างข้างบนเราแซงคิวให้การประกาศตัวแปร e แล้ว ทำให้สามารถใช้ตัวแปร e ได้ทุกส่วนในไฟล์สคริปต์ สำหรับการประกาศตัวแปรที่เก็บค่าเริ่มต้น (เช่น ตัวแปรที่เก็บชื่อตัวละคร) ผู้เขียนแนะนำว่าให้แซงคิวทุกครั้ง เพื่อความสะดวกในการแก้ไขสคริปต์


แสดงค่าตัวแปรในกล่องข้อความ

การแสดงค่าของตัวแปรในกล่องข้อความใช้วิธีเดียวกับตัวอักษรพิเศษ (Escape Character) คือใส่ไว้ภายในข้อความนั้น ชื่อของตัวแปรในคำสั่งแสดงกล่องข้อความต้องอยู่ในเครื่องหมาย [ ] ตัวอย่างเช่น

เมื่อนำตัวอย่างข้างบนมาทดสอบ จะแสดงข้อความดังรูปที่ 4.1
รูปที่ 4.1 การแสดงค่าของตัวแปรในกล่องข้อความ


สรุปท้ายบท

จุดประสงค์ของบทนี้คือเพื่อให้ผู้อ่านรู้จักตัวแปรและสามารถใช้ตัวแปรได้ เราใช้ตัวแปรเพื่อเก็บข้อมูลไว้ใช้ในภายหลัง แต่ภาษา Ren'Py ไม่มีตัวแปรในตัวเอง จึงต้องใช้ภาษา Python เพื่อใช้ตัวแปร เนื้อหาในบทนี้เป็นเนื้อหาเชิงทฤษฎี มีการปฏิบัติเล็กน้อยในหัวข้อ "แสดงค่าตัวแปรในกล่องข้อความ" ทฤษฎีในบทนี้จะนำไปลงมือปฏิบัติอย่างจริงจังในบทต่อไป

1 ความคิดเห็น: