Godot Devlog#1 - ความแตกต่างจากการเขียนโปรแกรมธรรมดา | muitsfriday.dev

web-logo-doge muitsfriday.dev

Godot Devlog#1 - ความแตกต่างจากการเขียนโปรแกรมธรรมดา

ประสบการณ์แรกกับการเขียนเกมจากคนที่ไม่เคยลองมาก่อน

Tue Oct 17 2023

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

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

ทำไมเลือก Godot

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

  • Game maker studio
  • Unity
  • Godot

ในตอนแรกผมเลือก Game maker studio มาเนื่องจากเป็น engine ที่ดูง่าย เหมาะกับมือใหม่(ตอนนั้นในความรู้สึกผมนะครับ) ผมลองได้อยุู่สักพักก็ต้องเลิกไปเพราะผมไม่อยากจ่ายเงินเช่ารายเดือนรายปี ให้เอนจิ้นที่ผมยังไม่รู้เลยว่าจะใช้จนทำเกมออกมาได้ไหมน่ะครับ แถมช่วงแรกๆก็ยังเป็นช่วยหัดๆทำอยู่ด้วย ทำไปก็เละรู้สึกทำยังไงก็ไม่ดีสักที(ฮาๆ) แล้วผมก็พักเรื่องทำเกมไปครับ

กลับมาอีกทีผมเหลือตัวเลือกอยู่สองตัวคือ Unity และ Godot (ก่อนหน้านั้น Unity ยังไม่มีข่าวฉาวเรื่องจะเก็บเงินราย install นะครับ) ผมได้ลองทั้ง 2 engine แล้วสรุปได้ว่าสุดท้ายผมเลือก Godot ไม่ใช่เพราะมันดีกว่า Unity แต่เพราะว่า

  1. Free license เรื่องนี้จริงๆ Unity ในตอนนั้นก็ฟรีนะครับถ้าทำเล่นๆ ไม่ได้ขายจนมีรายได้เยอะๆ แต่ Godot คือฟรีตลอดเพราะเป็น open-source
  2. UI ที่ ตรงไปตรงมา ง่ายและตรงประเด็นมากกว่า อันนี้เป็นความรู้สึกผมเองนะครับว่า Godot หน้าตามันน้อยกว่ามือใหม่เห็นแล้วใจสู้กว่าครับ 555
  3. Flow การ develop ที่ Godot จะมองสิ่งต่างๆในเกมเป็น node นึงแล้วเอามาประกอบทำงานเข้าด้วยกัน ใช่เลยครับ ข้อนี้แหละที่ทำให้ผมเลือก Godot เพราะผมมาจากการทำเว็บเป็นอาชีพ ดังนั้นจึงมีความเข้าใจในการทำอะไรแบบ component-based เป็นอย่างดี พอ Godot ถูกออกแบบมาแนวๆนี้ก็ค่อนข้างเข้าทางผมเลยครับ

แต่ไม่ใช่ว่า Godot จะมีแต่ข้อดีนะครับ ข้อเสียใหญ่ๆก็มีเยอะเหมือนกัน เช่น

  1. Tutorial น้อยกว่า Unity ด้วยความที่ความนิยมมันน้อยกว่าด้วยครับ
  2. Doc บางทีไม่ครบบ้าง อัปเดตช้าบ้าง เพราะมันเป็น open-source ครับแต่เรื่องนี้ไม่ค่อยเจอ

สุดท้ายผมก็มาทาง Godot ตอนนั้น engine เป็นเวอชัน 3.x ครับ แล้วมีข่าวแว่วๆช่วงนั้นมาว่าเดี๋ยว version 4 มีการปรับปรุงเยอะมากโดยเฉพาะเรื่อง tilemap(แผนที่ตารางแบบ2d) ผมเลยพักการทำเกมไปก่อนแล้วรอ

Gogot engine version 4 arrived

ในที่สุดก็มาถึงวันนี้ครับ Godot4 ออกอย่างเป็นทางการแล้วจริงๆตอนที่เขียน devlog นี้ก็ 4.2 จะออกแล้วด้วยซ้ำครับมีการปรับปรุงอะไรหลายๆอย่างขึ้นมามากโดยรวมแล้วดีขึ้นมากครับ การลองในครั้งนี้ผมเลยคิดที่จะลองใช้ C# ในการทำด้วยครับ (Godot เลือกได้ระหว่าง GDscript ที่เป็นภาษาของ engine เองกับ C# ครับ) ผมเปลี่ยนมาเลือก C# เพราะผมรู้สึกชอบภาษาที่เป็น statically typed มากกว่าครับ

การเขียนเกมแตกต่างกับการเขียนโปรแกรมอื่นยังไงบ้าง

โปรแกรมที่รันบนเครื่องทั่วๆไป หรือ webapp มักจะมีโฟลวการทำงานประมาณนี้้

Web app workflow

โดนรวมคือถ้าเป็นเว็บไซต์ เราจะรับ request เข้ามาประมวลตาม logic ที่เราเขียนเอาไว้เสร็จแล้วก็จะคืนหน้าเว็บ หรือข้อมูลคำตอบออกไป

หรือถ้าเป็น app ในคอมก็จะเป็นประมาณนี้เช่นกันคือ user กดอะไรสักอย่างในโปรแกรมเรา เราให้ program ทำตาม logic ดังกล่าวแล้วคืนออกไปเป็น feedback ไม่ว่าจะอัปเดตหน้าจอ หน้าตาโปรแกรม หรือเขียนข้อมูลลงไฟล์ db เป็นต้น

นั่นคือ โปรแกรมที่เราเขียนจะถูกเรียกเมื่อมี event(เหตุการณ์) บางอย่างเกิดขึ้นมา

การเขียนเกมแตกต่างออกไปจากนั้น

เกมนั้นการทำงานจะเป้นการ render ภาพเร็วๆ โดยตัว engine เป็นจำนวนมากๆในช่วงเวลานึง ซึ่งจำนวนภาพที่ render ได้ในวินาทีนึงเราจะเรียกว่า frame per second(fps)

เกมจะถือ state เอาไว้ แล้วจะคอยถามเราว่า “เอาล่ะ แล้ว frame ต่อไปจะ render อะไรดีจาก state เหล่านี้” หน้าที่ของเราก็คือเขียน script เพื่ออัปเดต state เหล่านั้นให้ engine เอาไป render เป็นภาพต่อครับ

เทียบแล้วความแตกต่างคือ

  1. logic ที่เราจะเขียนจะถูกเรียกโดยตัว engine และจะมี logic บางส่วน(โดยเฉพาะที่เกี่ยวกับภาพและฟิสิกส์) ถูกเรียกรัวๆในทุกๆ frame ดังนั้นถ้าเราเขียนไม่ดีอาจจะทำให้เกมรันช้าและกระตุกได้
  2. state มักจะเป็น global ตัวเกมจะถือ state เต็มไปหมดเพื่อใช้ render ภาพตามเงื่อนไขขณะนั้น

Game loop

logic จะถูกวนอยู่เพียงเท่านี้ เรามีหน้าที่ update state ให้ตรงความต้องการและใช้ tool ของ engine ให้เป็น

Game loop example

ยกตัวอย่างจากภาพ สมมติเรามี player อยู่ในเกม engine จะส่งสัญญาณมาให้เราบอกว่า “เฮ้ ฉันต้องการจะ render frame ต่อไปแล้วมีอะไรจะอัปเดตไหม” ตรงนี้เราจะมาเขียน script เพื่อสร้าง logic ได้เช่นถ้า user กด input บางอย่างให้อัปเดต position ของ player นะ แล้ว engine เอาไปจัดการเรื่องตำแหน่งในการ render ให้ทีใน frame หน้า เราก็จะเห็นว่าตัวละครเราขยับได้

Building Block ของ Godot

Godot มี building block (ส่วนย่อยเล็กๆที่ประกอบกันเพื่อให้โปรแกรมเราทำงานได้ตามต้องการ) อยู่สองอันหลักๆคือ Node และ Scene

Node

Node เป็นส่วนย่อยๆที่ใช้แสดงถึงพฤติกรรมจำเพาะบางอย่างของเกม node มีหลายชนิดมากใน Godot ถูกออกแบบมาเหมือนเป็นชิ้นส่วนเลโก้ที่ให้นักพัฒนาเอาไปประกอบร่างเป็นพฤติกรรมที่ต้องการ

ตัวอย่างของ node

Collision2D node ที่ใช้แสดงถึงพฤติกรรมการ ชน เราสามารถตรวจจับการชนกันของสิ่งต่างๆ ได้ด้วย node นี้

Sprite2D node ที่ใช้ในการแสดงภาพ เวลาเราจะแสดงรูปภาพขึ้นมาเราจะใช้ node นี้

Area2D node ที่ใช้ตรวจจับการซ้อนทับกันของพื้นที่ node นี้จะบอกเราได้ว่าเมื่อไหร่ที่มีพื้นที่ซ้อนกันอยู่

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

AnimationPlayer node ที่ใช้ในการแสดงภาพเคลื่อนไหว เราสามารถคีย์การเคลื่อนไหวของ node อื่นๆผ่าน AnimationPlayer ได้

และยังมี node อื่นๆอีกเพียบที่ engine เตรียมไว้ให้เราใช้ เช่น node แผนที่, เล่นเสียง, แสดง ui

ตัวอย่างของ node ที่มีมาให้ใน godot

Scene

Scene คือ collection ของ node และ scene ที่ถูกเซฟรวมเป็นก้อนเพื่อทำงานร่วมกันบางอย่างให้เกิดความหมายขึ้น

เกมทั้งเกมคือ scene ใหญ่ๆอันนึงที่ประกอบขึ้นมาจาก node และ scene สื่อสารกันผ่าน logic ที่เราสร้างขึ้นมา เราผู้ที่เป็นนักพัฒนามีหน้าที่ร้อยเรียง scene ย่อยต่างๆเข้าด้วยกันเพื่อให้มัน function ในแบบที่เราต้องการ

Example: scene Player

example godot scene

Player เป็น scene ที่แสดงถึงตัวละครในเกมที่เราจะเล่นประกอบไปด้วย node ดังนี้

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

เราสามารถบันทึก scene Player นี้ไปใช้เป็นส่วนประกอบใน scene อื่นๆได้ ถ้าเทียบกับการทำเว็บก็จะเหมือนพวก component ของ ui framework