สร้าง Online Game ด้วย Scratch และ NETPIE ตอนที่ 2

ในตอนที่ 1 ได้กล่าวถึงกระบวนการสร้างเกมส์ไปแล้ว มาตอนนี้จะกล่าวถึงกระบวนการสื่อสารระหว่างผู้เล่นสองฝ่ายกันบ้าง ครับ  และก่อนจะไปกันต่อ ท่านอาจต้องทำความเข้าใจสองเรื่องนี้ก่อนคือ Remote Sensor Protocol ของ Scratch 1.4  และ การใช้งาน NETPIE ส่งภาพนิ่ง นะครับ เพราะเราจะใช้พื้นฐานจากทั้งสองเรื่องนี้มาประกอบกัน


Dialog ระหว่างผู้เล่น

ในขณะที่เล่น ผู้เล่นทั้งสองฝ่ายจะมองไม่เห็นหน้าจอของฝ่ายตรงข้าม  แต่ซอฟต์แวร์จำเป็นต้องทราบตำแหน่งและทิศทางของ Pong Ball ที่ผู้เล่นฝ่ายตรงข้ามตีส่งมาให้ ดังนั้นข้อมูลหลักที่ต้องส่งไปมาระหว่างกันคือ ตำแหน่งและทิศทางของ Pong Ball นั่นเอง นอกจากนี้ก็อาจจะมีข้อมูลอื่น เช่น  สถานะของเกมส์ จำนวนชีวิตของผู้เล่น เป็นต้น



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

ทำไมถึงใช้ NETPIE

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

ขั้นตอนการทำงาน

เมื่อทราบว่าจะต้องส่งอะไร และต้องส่งผ่านใครแล้ว ต่อไปก็มาทำการเชื่อมองค์ประกอบเข้าหากัน

1. เชื่อม Scatch  กับ Python ผ่าน ScratchPy.py ดูตัวอย่างได้จากเรื่อง Remote Sensor Protocol ของ Scratch 1.4


2. เชื่อม  NETPIE  ดูตัวอย่างการใช้ Python กับ NETPIE ได้จากเรื่อง การใช้งาน NETPIE ส่งภาพนิ่ง


3. Python สำหรับส่งข้อมูลระหว่างผู้เล่น

# -*- coding: utf-8 -*-
import threading
import microgear.client as netpie
from ScratchPy import *
# ---------------------------------------------
_key = '[Your NETPIE KEY]'
_secret = '[Your NETPIE SECRET]'
_app = '[Your NETPIE APPLICATION NAME]'

_gear_name = '[Your Alias Name]' 
_other_gear_names = ['[Your Opposit Alias Name]']
_stop_flag = False
_topic = '/pong_game'

#-- Event Handler
def on_disconnect():
 pass
   
def on_connect():
 print('Connected ')
 #netpie.subscribe(_topic)
 pass
 
def on_message(topic, msg):
 global psc, _stop_flag, mos_client, _ips, y_pos, _dir,_topic
 
 msg = msg.replace("b'",'').replace("'",'')
 data = ''
 if msg == 'new start' :
  psc.sensorupdate({'game_state','ready'})
 elif msg == 'opposit lose':
  psc.broadcast('opposit lose')
 else :
  data = msg.split(":")
 
 if len(data) > 0 and data[0] == 'ball':
  _ypos = data[1]
  _dir = data[2]
  if _stop_flag == True:
   send_to_opposit("ball:"+str(y_pos)+":"+str(_dir))
  else :
   # -- forward message to Scrath 
   psc.sensorupdate({"y_pos":_ypos})
   psc.sensorupdate({"dir":_dir}) 
   psc.broadcast('activate')

def on_present(gearkey):
 #print("{0} is online".format(gearkey))
 pass
 
def on_absent(gearkey):
 #print("{} is out".format(gearkey))
 pass
 
def on_error(msg):
 pass
  
  
def parse_data(data):
 tmp = ['you_lose','send_pong_data','let_move','game_state','new_start']
 global _dir,y_pos, _stop_flag 

 if data[0] == 'broadcast' :
  if data[1] == 'quit':
   _stop_flag = True
   return -1
  elif data[1] == 'sendout': 
   return 1
  elif data[1] == 'new_start':
   send_to_opposit('new start')
   return 0
  elif data[1] == 'i_lose':
   send_to_opposit('opposit lose')
   return 0
  elif not data[1] in tmp : # filter out unused broadcasting   
   if data[2] is None :   
    temp = data[1].split(':')
    k = temp[0]
    v = temp[1]
   else :
    k = data[1].replace(':','')
    v = data[2]
   if k == 'direction' :  
    _dir = v
   elif k == 'ypos':
    y_pos = v
   return 0 

def send_to_opposit(data):
 target = random.choice(_other_gear_names) 
 netpie.chat(target,data)
 

def run():
 global psc,_ips,_dir,y_pos, _stop_flag
 _dir = y_pos = 0
 psc = Py2Scratch14()
 psc.connect() 
 
 netpie.create(_key,_secret,_app)
 netpie.on_connect = on_connect
 netpie.on_message = on_message
 netpie.on_present = on_present
 netpie.on_absent = on_absent
 netpie.setalias(_gear_name)
 netpie.connect(False)
 
 while True :
  res = parse_data(psc.receive())
  if res == 1  and _stop_flag == False:
   send_to_opposit("ball:"+str(y_pos)+":"+str(_dir))
      
 psc.end() 
# ---------------------------------------------

if __name__ == "__main__":
 t = threading.Thread(target=run)
 t.start()
 



การติดตั้งและใช้งาน

1. ดาวน์โหลด ScratchPy.py 
2. ดาวน์โหลด PongGame.py
3. ดาวน์โหลด Scratch Script ของ PongGame
4. นำไฟล์ทั้งหมดไปวางใน Folder เดียวกัน
5. เปิดโปรแกรม Scratch เพื่อเรียกใช้ pong_game.sb
6. ใช้คำสั่ง python3 PongGame.py เพื่อเปิดการเชื่อมต่อระหว่าง Scratch กับ Python และ NETPIE ก่อนจะเรียกใช้งานต้องกำหนดค่าตัวแปรเหล่านี้เสียก่อน

_key = '[Your NETPIE KEY]'
_secret = '[Your NETPIE SECRET]'
_app = '[Your NETPIE APPLICATION NAME]'

_gear_name = '[Your Alias Name]' 
_other_gear_names = ['[Your Opposit Alias Name]']

โดย _key, _secret,_app จะได้จาก NETPIE และ _gear_name และ _other_gear_names ผู้ใช้งานเป็นผู้กำหนดเอง เช่น หากต้องการให้ตัวเราใช้ชื่อ player1 และฝ่ายตรงข้ามชื่อ player2 ก็จะกำหนดได้ตามนี้

_gear_name = 'player1' 
_other_gear_names = ['player2']

7. เคาะ Space Bar เพื่อเริ่มเล่น
8. การทดสอบต้องใช้ผู้เล่นหรือเครื่องคอมพิวเตอร์สองเครื่อง อาจอยู่ LAN เดียวกันหรือต่างกันก็ได้ และต้องเชื่อมต่อกับอินเตอร์เน็ตทั้งสองเครื่องเพราะต้องเชื่อมกับ NETPIE


ภาพวิดีโอตัวอย่างการใช้งาน





ปล.

 โดยสรุปแล้วบทความสองตอนนี้ได้กล่าวถึงการสร้างเกมส์ online แบบง่าย ๆ โดยนำองค์ประกอบสามส่วนมาประกอบกัน ได้แก่ Scratch 1.4 เพื่อสร้างเกมส์ อย่างที่สองคือ NETPIE เพื่อใช้ในการสื่อสาระหว่างผู้เล่นผ่านข่ายงานอินเตอร์เน็ต และสุดท้ายคือ Python  Script ใช้ในการสื่อสารระหว่างองค์ประกอบต่าง ๆ เข้าหากัน Script ทั้งหลายถูกเขียนขึ้นมาเพื่อใช้เป็นตัวอย่างในการทำงานเท่านั้น ไม่ได้มีความสมบูรณ์ครบถ้วนและยังมีข้อผิดพลาดอยู่ ท่านผู้ที่สนใจสามารถนำไปปรับปรุงให้ดีขึ้นได้ตามความต้องการและจินตนาการของแต่ละท่านเอง


Previous
Next Post »