สอนสร้างเกม HTML5 ด้วย Phaser Framework
วันนี้ผมจะพาไปเขียนเกม HTML5 ด้วย PhaserJS กันนะครับ ตัวอย่างเกม เมื่อเขียนเสร็จ จะได้หน้าตาแบบนี้เลย ลองเข้าไปลองเล่นได้
PhaserJS เป็น HTML5 Game Framework ตัวหนึ่ง สร้างโดย Photo Storm ซึ่งสามารถสร้างเกมส์แบบ Cross-Browser ได้ สามารถทำงานร่วมกับ Browser บนมือถือได้ (ที่รองรับ Canvas) และ Browser บน Desktop ได้ จุดเด่นของ PhaserJS คือ มี Module และ Features ให้เลือกใช้มากมาย สามารถประหยัดเวลาในการสร้างเกมๆหนึ่ง
ตัว PhaserJS เขียนด้วย Javascript หากต้องการใช้งาน PhaserJS ควรจะมีความรู้พื้นฐานในส่วน Web Development มาบ้าง ส่วน Features ของมันมีอะไรบ้าง ก็ดูตามรูป หรือเข้าไปดูที่เว็บหลักได้เลยครับ
ก่อนที่จะเริ่มต้นสร้างโปรเจ็ค ก็ขอแนะนำลิงค์ต่างๆ ที่น่าจะมีประโยชน์ เอาไว้อ่านประกอบครับ
Table of Contents
- Step 1 : Prepare & Setup Project
- Step 2 : Download Phaser & Game Assets
- Step 3 : Create Game
- Step 4 : Load Assets
- Step 5 : Create Game World
- Step 6 : Add Player
- Step 7 : Control Player
- Step 8 : Add coins
- Step 9 : Check Overlap
- Step 10 : Add Score
- Bonus Track
Step 1 : Prepare & Setup Project
ขั้นตอนแรกเลย ต้องเตรียมตัวที่จะใช้งาน PhaserJS นั้นจะต้องเตรียมตัวอะไรบ้าง? เริ่มที่
-
Text Editor : หา Text Editor ซักตัว ไม่ว่าจะเป็น Sublime Text 2/3, Notepad++, WebStorm, Brackets, Atom หรืออื่นๆ
-
Browser : อันนี้คาดว่าน่าจะมีทุกคน Chrome หรือ Firefox (ไม่แนะนำ IE)
-
Web Server : จะเป็น Apache หรือ nginx ก็ได้ หรือจะลงผ่าน WAMP, XAMPP, LAMP ก็ตามสะดวก ใครไม่รู้วิธีติดตั้ง ก็ตามนี้ครับ
- ขั้นตอนการติดตั้ง Apache, MySQL, PHP บน Ubuntu ส่วนถ้าเป็น OS อื่นก็ไปหาวิธีทำเองนะครับ ส่วนนี้ไม่ได้อยู่ในบทความ
- หากใช้ PHP เวอร์ชัน 5.4 ขึ้นไป รู้สึกก็จะมี Built-in Web Server อยู่
- หากใช้ Python ก็ใช้ Simple HTTP Server ไ้ด้เลย
สำหรับ Python 2
สำหรับ Python 3
Step 2 : Download Phaser & Game Assets
หลักจากที่เตรียมพร้อมเรียบร้อยแล้ว ต่อมาก็ทำการสร้างไฟล์ index.html
ขึ้นมา 1 ไฟล์ จากนั้นทำการดาวน์โหลดไฟล์ phaser.js เวอร์ชันล่าสุด (2.0.7) เซฟไว้ที่เดียวกันกับ index.html
ต่อมาก็สร้างไฟล์ main.js
ขึ้นมา ไฟล์นี้คือไฟล์ที่เราจะใช้เขียนเกม ตอนนี้ในโปรเจ็คเรา จะมี 3 ไฟล์แล้ว (ผมโหลดตัว phaser.js ไม่ใช้ตัว phaser.min.js เนื่องจากต้องการดูโค๊ด รวมถึง Docs มันด้วย)
ถัดมา ที่ไฟล์ index.html
เพิ่มโค๊ด HTML ลงไป โดย div id="game">
คือส่วนที่เราจะใช้ในการโชว์ตัวเกมเรานะครับ (ผมไม่พูดถึงรายละเอียด HTML นะครับ บทความนี้ assume ว่าทุกคนมีพื้นฐาน Web แล้ว)
ส่วน File Assets ต่างๆ ที่จะใช้ในโปรเจ็คนี้ก็ทำการโหลดตามข้างล่างนี้เลยครับ
- logo.png :
- ground.png :
- coins.png :
- warrior_m.png :
Credit
เมื่อโหลดหมดแล้ว ก็เซฟไว้ที่โฟลเดอร์ assets
สุดท้ายจะได้ตัวโปรเจ็คทั้งหมดเป็นดังนี้
Step 3 : Create Game
ต่อมา ถึงเวลาเริ่มลงมือเขียนโค๊ด เปิดไฟล์ main.js
ขึ้นมา เพิ่มโค๊ดด้านล่างนี้ลงไป
อธิบายโค๊ดด้านบน เริ่มตั้งแต่ mainState
คือ State หลักที่เราจะใช้ในการเขียนเกมนะครับ ภายใน State ก็จะมี ฟังค์ชั่น 3 ฟังค์ชั่น ดังนี้
preload
: ฟังค์ชั่นนี้จะถูก execute เป็นอันดับแรก จะทำหน้าที่ โหลดไฟล์ Game Assets ต่างๆ (images, sound)create
: ฟังค์ชั่นนี้จะถูก execute หลังจากpreload
จะเอาไว้สำหรับให้ Game Assets ต่างๆที่โหลดไว้ มาโชว์บนหน้าจอupdate
: ฟังค์ชั่นนี้เปรียบเสมือน Game Logic (เช่นรับ input จากผู้เล่น, เช็คการชนกันของวัตถุ) มันจะถูกรันประมาณ 60 ครั้งต่อวินาที
ต่อมาดูที่ game
สร้างจากออปเจ็คของ Phaser.Game
โดยมีรายละเอียดดังนี้
800
: คือ Width ความกว้างของเกมส์600
: คือ Height ความสูงของเกมส์Phaser.AUTO
: เป็นโหมดที่ใช้ในการ render มี 3 โหมดคือ Phaser.AUTO, Phaser.CANVAS, Phaser.WEBGLgame
: คือ element ของ HTML ในไฟล์index.html
ที่เราต้องการให้โหลดตัวเกม (เราสร้าง<div id="game"></div>
ไว้ในindex.html
แล้ว)
สุดท้ายทำการ เพิ่ม State
ไปยังอ็อปเจ็ค game
โดยให้ State
ชื่อว่า main จากนั้นก็สั่งให้เริ่ม State
ตัวเกมนี้มีแค่ State เดียว แต่โดยปกติแล้ว State จะเอาไว้แบ่งการทำงานของเกม เช่น State สำหรับ MainMenu, Option หรือ MainGame เป็นต้น
ต่อมาลองเปลี่ยนสี Background ของตัวเกมซักหน่อย โดยเพิ่มลงไปตรงฟังค์ชัน create
เปิด Browser ดู จะเห็นหน้าจอดังภาพ
Step 4 : Load Assets
ผมจะเริ่มทำการโหลดไฟล์ Assets ต่างๆที่จะใช้ในเกม เริ่มด้วย logo.png
เป็นรูปโลโก้ของเว็บนี้แหละครับ ทำการโหลด และเก็บไว้ในชื่อ devahoy
คล้ายๆโหลดไฟล์ logo.png
มาเก็บไว้ในตัวแปร devahoy
และที่ฟังค์ชัน create
ก็ใช้ไฟล์รูปที่โหลดไว้ ด้านบน มาแสดงบนหน้าจอที่ตำแหน่ง x = 0 และ y = 0
Anchor Point
Anchor Point คือจุดที่เราต้องการให้ add.sprite(0, 0, 'devahoy');
แสดงในตำแหน่ง x, y โดยค่า default แล้ว Anchor Point จะเป็น (0, 0) ฉะนั้น จุดที่แสดง sprite x = 0, y = 0 คือนับจากมุมซ้ายของรูปภาพ จากตัวอย่าง จุดที่ เส้นตรงสองเส้นวิ่งมาตัดกัน นั้นคือ Anchor Point
ที่นี้ เมื่อเราไม่ได้กำหนดอะไรเลย ค่า default ของมันคือ 0, 0 ฉะนั้น รูปมันก็จะอ้างอิง Anchor Point โดยใช้ มุมซ้ายบนของรูปภาพ เป็นจุดอ้างอิง เมื่อเปิด Browser จะได้ดังนี้
ส่วนตัวแล้ว เวลาจะคำนวนอะไรหลายๆ อย่าง มันทำให้อาจจะดูงงๆ เพราะฉะนั้นก็เลยปรับ anchor point โดยนับจุด x, y จากกึ่งกลางรูปภาพแทนดังนี้
ทีนี้ เมื่อเวลาเราปรับ Anchor Point เป็น (0.5, 0.5) มันก็จะเริ่มคำนวณ โดยนับจาก กึ่งกลางของรูปภาพแทน เวลาเราสั่่งให้มันแสดงภาพที่ตำแหน่ง x = 0, y = 0 ก็จะนับจากกึ่งกลางของรูปภาพ ดังรูป
ลองทดสอบรัน Browser ใหม่อีกครั้ง คราวนี้รูปมันจะหลุดออกนอกจอเลย เนื่องจากจุด x = 0, y = 0 มันคือจุดกึ่งกลางของรูป
Step 5 : Create Game World
OK หลังจากที่รู้วิธีการ โหลด image การแสดง image ต่อมาก็ถึงขั้นตอนการสร้าง Game World เนื่องจากตัวเกมเดโม่อันนี้ จะทำแบบง่ายๆ ฉะนั้นตัว World ก็จะมีแค่พื้นหญ้า ด้านล่าง มีเกาะ 2 - 3 เกาะ ให้กระโดดขึ้นไปเท่านั้น เริ่มด้วยการ ทำการโหลดรูป ที่จะใช้ก่อน ที่ฟังค์ชัน preload()
ต่อมา ที่ฟังค์ชั่น create()
ก็สั่งให้ Phaser ใช้ Physics.ARCADE
โดยเพิ่มโค๊ดด้านล่างนี้ลงไป ผมจะอธิบายโดยใส่คอมเม้นไว้ในโค๊ดนะครับ
ต่อมาเมื่อเรามี Group ของ Game World แล้ว ต่อมาผมก็ทำการสร้างพื้นหญ้าเขียวๆ ด้านล่างขึ้น
ด้านบน คือการสร้างพื้นหญ้าขึ้นมา โดยระบุตำแหน่ง x, y และชื่อภาพที่เราต้องการ ส่วน scale.setTo(2, 2)
คือการขยายรูปภาพ เนื่องจากตัว ground.png
ที่ผมใช้ มีขนาด 400x32 เมื่อ setScale ก็จะทำใ้ห้มันโหลดรูปมามีขนาด 800x64 ซึ่งเต็มความกว้างของจอพอดีเลย
ทีนี้ เราก็ใช้หลักการเดียวกัน สร้างเกาะ หรือพื้นที่มันลอยฟ้า เพื่อที่จะเอาไว้ให้ผู้เล่นกระโดดขึ้นไปได้
Step 6 : Add Player
การสร้างตัวผู้เล่น เราจะทำการโหลดภาพมาจาก spritesheet ที่ชื่อว่า warrior_m.png
นะครับ เริ่มด้วยการเพิ่มโค๊ดที่ฟังชั่น preload()
ข้างบนเป็นการโหลดรูป spritesheet มาเก็บไว้ในชื่อ player
โดยแต่ละเฟรมมีขนาด 32x36 pixel จากนั้นเมื่อโหลดรูปแล้ว ก็ให้มันแสดง ด้วยการเพิ่มโค๊ดที่ create()
ต่อมา ทำการใส่ animation ให้กับ player
หากใครยังงง เรื่องตำแหน่ง frames ลองดูรูปนี้ประกอบครับ การนับตำแหน่ง จะเริ่มนับที่ 0 ถัดมาเรื่อยๆ
ฉะนั้น animation ของเรา ที่ชื่อ right
ได้ทำการเล่น frame ตำแหน่ง 3, 4, 5 ก็คือ ภาพนี้
เ่ช่นเดียวกัน animation ชื่อ left
เล่น frame ตำแหน่ง 9, 10, 11 ก็คือภาพนี้
ลองทดสอบรันบน Browser จะเห็นตัว Player แล้ว แต่ว่ามันดันทะลุไปอยู่ในพื้น ซะได้
อัพเดท player เมื่อเวลาโดน พื้นแล้วไม่ให้ทะลุ โดยการเพิ่มลงไปในฟังค์ชั่น update()
collide(object, object)
เป็นการเช็คกันของวัตถุสองอัน ส่วนนี้ PhaserJS จะคำนวณให้เราเอง เมื่อเรากำหนดแบบนี้ วัตถุสองชิ้น เมื่อมีการแตะกันเกิดขึ้น ก็จะหยุดทันที ผลลัพธ์ก็เป็นแบบที่เห็นเลยครับ คือตัวผู้เล่นจะไม่ทะลุพื้น ตอนนี้ก็เหมือนผู้เล่น ยืนบนพื้นแล้ว
Step 7 : Control Player
หลักจากที่เราทำการแสดง Player ได้แล้ว ต่อมาก็ถึงเวลาที่เราจะมาควบคุมมันแล้ว สั่งให้ตัวเกมใช้ฟังค์ชันเพื่อรับค่าปุ่ม Curosr คือลูกศร ขึ้น ลง ซ้าย ขวา ในส่วนฟังค์ชัน create()
โดยปกติ ส่วน Logic ของเกม หรือการรับ Input จากผู้เล่น จะทำที่ฟังค์ชั่น update()
นะครับ เพราะมันจะเหมือน Game Loop คือจะ loop ไปเรื่อยๆ 60 ครั้งต่อวินาที จนกว่าจะปิดเกม ฉะนั้นไปที่ฟังค์ชั่น update()
ทำการเช็คว่าผู้เล่น กด Keyboard Right หรือไม่
และเช็คว่าผู้เล่น กด Keyboard Left หรือไม่ด้วย
เมื่อผู้เล่นมีการกดปุ่ม ก็จะให้เลื่อนตำแหน่ง แกน x จะได้ดังนี้
ด้านบนเป็นการ reset ค่าให้ความเร็วแกน x เป็น 0 ก่อน เมื่อเวลาไม่ได้กดปุ่ม มันจะได้อยู่กับที่ ส่วนเมื่อกดปุ่มขวา มันก็จะขยับไปทางขวามือ 200 pixel ต่อวินาที เช่นเดียวกัน เมื่อกดปุ่มลูกศรซ้าย ก็จะขยับไปทางซ้าย 200 pixel ต่อวินาที แล้วจะเห็นว่านอกจากให้ตัว player
ขยับแล้ว เรายังสั่งให้มันเล่น animation จาก spritesheet ที่เราตั้งค่าไว้ ชื่อ right
และ left
ด้วย หากไม่ได้กดปุ่มอะไรเลย มันก็จะหยุดเล่น animation แล้วแสดงผล frame ที่ 6
ต่อมา เพิ่มให้ผู้เล่นสามารถกระโดดได้ด้วย โดยเมื่อผู้เล่นกดปุ่มลูกศรขึ้น ให้ต้ัว player
มันกระโดดได้ ด้วยโค๊ดนี้
ด้านบน เมื่อกดลูกศรขึ้น ตัว plyaer
จะลอยขึ้นไปด้านบน (แกน y ด้านบนสุดคือ 0 ล่างสุดคือความสูงของจอ = 800) และสังเกตว่าตรงเงื่อนไข if มีการเช็ค
ตรงส่วนนี้คือ เมื่อตัว player
มีการแตะกับวัตถุด้านล่าง ฉะนั้น เงื่อนไขนี้จะเป็นจริงได้ ต้องให้ผู้เล่นกดปุ่มลูกศรขึ้น และตัวละคร ต้องยืนอยู่บนฟื้นเท่านั้น
Step 8 : Add coins
ต่อมา เพิ่มไอเท็มเข้าไปในเกมซักหน่อย โดยผมจะทำการเพิ่มเหรียญ เข้ามานะครับ ตัวเหรียญเป็น spritesheet ฉะนั้นจะทำการโหลด ที่ฟังค์ชัน preload()
ดังนี้
ด้านบนเป็นการโหลดรูป coins.png
โดยแต่ละเฟรมมีขนาด 40x44 pixel จำนวน 4 เฟรม
ต่อมาที่ฟังค์ชั่น create()
ทำการสร้าง group ชื่อ coins และสั่งเรียกฟังค์ชัน spawnCoins()
เพื่อให้สุ่มเกิดเหรียญทั้งหมด 10 เหรียญบนหน้าจอ ดังนี้
เพิ่มฟังค์ชัน spawnCoins()
ต่อจากฟังค์ชัน update()
ได้เลย (ระวังเรื่องเครื่องหมายคอมมา (,) )
ฟังค์ชันด้านบนเป็นการวนลูป 10 ครั้งเพื่อสุ่มเกิดเหรียญ 10 เหรียญ ในตำแหน่ง x, y ที่แตกต่างกัน ส่วนแต่ละเหรียญ เราก็จะเพิ่ม animation ให้มัน โดยการโหลดจาก frame 0, 1, 2, 3 มีเฟรมเรตเท่ากับ 5 และวนลูป animation ไปเรื่อยๆ
มีการปรับ scale รูปภาพ เนื่องจากเหรียญมันใหญ่ เลยปรับขนาดให้มันเล็กลง และปรับ gravity ในแกน y = 200 มีค่าการกระทบเท่ากับ 0.5 (คือเมื่อตกลงพื้นมันจะเด้งกับมาเป็นระยะทางครึ่งนึงของระยะทางเดิม)
ลองทดสอบเปิด Browser ดู
จะเห็นว่า เหรียญมันลอย แล้วตกลงไปทะลุพื้นและหายไปจากจอเลย ทำไมหว่า? เพราะว่าเราลืม เช็ค collide
ครับ ไปที่ฟังค์ชัน update()
เพิ่มนี้ลงไป
เพื่อเช็คว่า เมื่อเกิด collide (เกิดการชนกันของวัตถุ 2 ชิ้น) คือเช็คระหว่าง เหรียญ และตัว myWorld
พวกพื้นและเกาะต่างๆ
ทดสอบรัน Browser อีกครั้ง
คราวนี้จะเห็น เหรียญ ตกมาแล้ว หยุดตรงส่วนที่เป็นพื้นแล้ว แต่จะเห็นว่าตัวละคร เดินผ่านเหรียญได้
Step 9 : Check Overlap
ขั้้นตอนต่อมา เราจะทำการเก็บเหรียญ เมื่อผู้เล่นเดินไปทับกับตำแหน่งเหรียญ ด้วยการเช็ค overlap โดย overlap มีการใช้งาน ดังนี้
object1
: คือออปเจ็คตัวแรก ที่เราจะไว้เช็คobject2
: ออปเจ็คตัวที่สอง ที่จะเอาไว้เช็คoverlapCallback
: ฟังค์ชันที่จะเอาไว้ถูกเรียก เมื่อมีการ overlap เกิดขึ้นprocessCallback
: เป็นฟังค์ชันเสริม ที่จะเอาไว้เช็ค จะ return true/false หาก true ก็จะทำการ onOverlapcallbackContext
: คือ Context ส่วนมากจะอ้างถึง this หรือหมายตัวthis.game
ทำการเปิดฟังชัน update()
แล้วเพิ่มนี้ลงไป
จะเห็นว่าเราเช็คว่า ผู้เล่น และ เหรียญ มีการ overlap กันเกิดขึ้นหรือไม่ ถ้าเกิดขึ้น ก็ให้ไปเรียกฟังค์ชัน collectCoin()
ส่วน processCallback ไม่ได้ใช้งาน
สร้างฟังค์ชัน collectCoin()
ขึ้นมา
จะเห็นว่า collectCoin(player, coin)
มีการรับ parameter 2 ตัว ก็คือ 2 อ็อปเจ็คที่เราให้มันเช็ค overlap กันนั่นแหละ เมื่อมีการเรียกฟังค์ชันนี้เกิดขึ้น ก็ทำการ coin.destroy()
เป็นฟังค์ชันของ PhaserJS ที่เอาไว้ลบ sprite ออกครับ
ตอนนี้เราก็สามารถบังคับตัวละคร เดินไปเก็บเหรียญ แล้วเหรียญหายไปได้แล้ว ต่อไป ขั้นตอนสุดท้าย ใส่คะแนนให้กับมัน เวลาที่เก็บเหรียญครับ
Step 10 : Add Score
ขั้นตอนนี้จะทำการโชว์ Text บนหน้าจอภาพ เพื่อแสดงคะแนนที่เราทำได้ Text เราไม่จำเป็นต้องโหลดอะไร ฉะนั้้น ก็เริ่มสร้างได้เลยที่ฟังค์ชัน create()
สร้างตัวแปรขึ้นมาสองตัว ตัวแรก score
เอาไว้เก็บค่าคะแนน ส่วน scoreText
เอาไว้แสดงคะแนนที่หน้าจอของเกม
เราสามารถให้เกมแสดงข้อความได้ ด้วยการใช้ game.add.text(x, y, text, style)
โดยมีพารามิเตอร์คือ
x
: ตำแหน่ง xy
: ตำแหน่ง ytext
: ค่าที่ต้องการแสดงstyle
: รูปแบบที่ต้องการ เช่น ขนาดฟ้อน สีฟ้อน
ทดสอบรันโปรแกรมดูครับ
สุดท้าย เราจะให้มันได้คะแนน เมื่อเราเก็บเหรียญได้ ฉะนั้น ก็แก้ไขฟังค์ชัน collectCoin()
นิดหน่อย เมื่อเก็บเหรียญ ก็ทำการเพิ่ม score
ด้วย ดังนี้
สุดท้าย เกมก็พร้อมเล่นแล้วครับ!
Link Demo: https://phonbopit.github.io/phaser101/
Conclusion
เมื่ออ่านมาถึงตรงนี้ เชื่อว่าทุกคนก็ได้เรียนรู้ PhaserJS ไปพอสมควร ได้รู้จักกับการสร้าง spritesheet, โหลด image รู้เกี่ยวกับ Physics ทั้งการ collision และ overlap รวมถึงรู้จักกับการรับ Input ต่างๆ คาดว่าทั้งหมดนี้ สามารถนำไปประยุกต์และสร้างเกมในแบบฉนับของตนเองได้ รวมถึงหากใครสนใจ ก็นำไปต่อยอด หาทางศึกษาเพิ่มเติมเอาเอง ในระดับ Advanced นะครับ นอกเหนือจากนี้ผมก็คงแนะนำได้เพียงแค่ แหล่งศึกษาเพิ่มเติมครับ ตามนี้เลย
- HTML5 Game Development using Phaser by Lynda - Video สอนของ Lynda อันนี้ผมไม่แน่ใจว่าที่เอาลง Youtube มันแอคเคาท์จริงหรือปลอมนะครับ
- Discover Phaser - เป็นหนังสือเล่มล่าสุด และเล่มเดียวของ PhaserJS
- List of Phaser Tutorials - รวมบทความ Tutorial ่ต่างๆจากเว็บ lessmilk
- Open Source Project on Github - ลองค้นหา Open Source บน Github ดูครับ มีเยอะมากๆ
ตัวโปรเจ็ค อยู่บน Github และ ทดลองเล่นตัวเดโมได้ครับ
Bonus Track
แถมครับ 1 เพลง เอ้ย ไม่ใช่! แถมเพิ่มเติมเกี่ยวกับ การ Cross Platform ไปลง Mobile ครับ พอดีว่าช่วงนี้สนใจ HTML5 แล้วอยากรู้ว่ามันจะ Cross-Platform ไปลง Android, iOS ยังไง ก็เลยไปลอง Ludei CocoonJS มา
ปรากฎว่ามันน่าสนใจเลย ลองเข้าไปในเว็บ แล้วสมัคร และลองเล่นดูครับ ส่วนนี้ผมแค่เอาตัวอย่าง มาให้ดู ไม่ได้เขียนวิธีการให้นะครับ หากมีคนสนใจเยอะอาจจะทำบทความให้ครับ :D
ปัจจุบันผมก็กำลังศึกษาจาก Tutorial นี้อยู่ ส่วน Source Code ก็นี้ ก็เลยนำตัวเกมที่ศึกษาลง Ludei ด้วยเลย ผลก็เป็นแบบภาพครับ เขียนด้วย HTML5/Javascript ก็สามารถทำเกมลง iOS, Android ได้เหมือนกันนะ! ภาพด้านล่าง ผมเปิดตัวเกมเดียวกัน ด้วยมือถือ Android
สุดท้าย หากบทความนี้มีประโยชน์ อย่าลืม ช่วยแชร์ รวมถึงบอกต่อเพื่อนๆ ด้วยนะครับ หรือพบโค๊ดหรือข้อความส่วนไหน พิมพ์ตกหล่น ก็แจ้งเข้ามาได้นะครับ ขอบคุณครับ
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust