Jun 12, 2011
Sunday, June 12, 2011

เขียนบอทเกมด้วย AutoIt : Bot 2 เช็คพิกัดสีเพื่อเขียนคำสั่งควบคุม

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



ข้อควรรู้ก่อนเขียนสคริปต์บอทเกมตรวจแถบสถานะ

- การตรวจสถานะดังกล่าวจะใช้วิธีการดึงเอาข้อมูลสีจากพิกัดที่กำหนดออกมา แล้วเขียนสคริปต์ตั้งเงื่อนไขการกระทำ

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

- การดึงเอาสีออกมาจากจุดที่กำหนดในเกมจะมีโอกาสผิดพลาดได้ในกรณีที่มีการเปิด effect เช่น ภาพเบลอ, เงา, สะท้อนแสง effect ต่างๆ เหล่านี้จะทำให้สีเปลี่ยนไป

- นอกจากนั้น การ์ดจอก็มีผลกับสีในบางเกมที่มีการเล่นเอฟเฟ็กสีด้วย (ไม่ทุกเกม) เช่น Nvidia จะให้สีที่ต่างจาก ATI จึงควรระวังในข้อนี้ หากนำไปใช้ต่างเครื่องที่มีการ์ดจอต่างกัน

- ในเกมออนไลน์ หากมีตัวป้องกันจะไม่สามารถดึงสีในตัวเกมออกมาได้ (เมื่อนำ AutoIt Windows Info ไปตรวจ สีที่ออกมาจะเป็น 0x000000) วิธีหลีกเลี่ยงต้องเปลี่ยนไปใช้วินโดวส์แบบ 64 บิต (ควรใช้ Windows 7  แบบ 64 บิตจะหมดปัญหาดังกล่าว) วิธีการตรวจเช็คว่าวินโดวส์ที่คุณใช้อยู่เป็นแบบกี่บิตใช้คำสั่งดังนี้

MsgBox(0,"วินโดวส์ของคุณ", "เป็นแบบ"& @OSArch)
;"X86" เป็นวินโดวส์แบบ 32 บิต และ "X64" เป็นวินโดวส์แบบ 64บิต


ตั้งค่า AutoIt Window Info เพื่อตรวจสีในเกม
     การตรวจสีในเกมจะใช้โปรแกรม AutoIt Window Info เหมือนในบทที่ผ่านมา แต่จะต่างกันตรงที่การวัดพิกัดสีต้องการความแม่นยำกว่า ดังนั้นจึงต้องมีการตั้งค่าเพื่อขยายภาพเวลาใช้งานด้วยวิธีการดังนี้

1. เปิดโปรแกรม AutoIt Window Info ขึ้นมาแล้วคลิกไปที่เมนู Options > Magnify


2. ลองลากเป้าใน Finder Tool ไปวางบนหน้าต่างเกมจะเห็นว่ามีภาพขยาย ส่วนที่โปรแกรมดึงเอาสีออกมาคือ จุดตัดของเส้น (ดูตรงวงกลมสีส้ม)

3. ที่แท็บ Mouse คุณจะเห็นว่ามีรายละเอียด เพื่อนำไปใช้เขียนสคริปต์อยู่ 2 ส่วนด้วยกันคือ Position เป็นพิกัดแกน X, Y  ตามตัวอย่างนี้คือ พิกัด 730,619 ของตำแหน่งเม้าส์ที่ชี้ขณะนั้น และ Color คือสีที่ดึงออกมาจากตำแหน่งเม้าส์ที่ชี้ขณะนั้น ตามตัวอย่างนี้คือ 0x343434 (สีเทาเข้ม) เป็นสีพื้นหลังของแถบ HP บางท่านอาจสงสัยว่าทำไมไม่ตรวจสีเขียว คำตอบคือในเกมตัวอย่างนี้สีเขียวจะไหลอยู่ตลอดเวลาทำให้ ตำแหน่งพิกัดเดิมสีจะเปลี่ยนไป ผมจึงเลี่ยงไปตรวจสีจากพืันหลังแทน หลักการก็คือ

     ถ้ามีสีเทาเข้มที่พื้นหลักปรากฏตรงพิกัดที่ตรวจ ก็แสดงว่าสีเขียวที่เป็นแถบ HP ลดลงแล้ว ถึงเวลาต้องกดปุ่มเพื่อเติม HP ให้เพิ่มขึ้น การเขียนคำสั่งเพื่อตรวจสอบกรณีดังกล่าวอยู่ในหัวข้อถัดไป



     สำหรับสีที่ดึงออกมาจากจุดเม้าส์ชี้ในเกม จะเป็นค่าสี RGB (R แดง, G เขียว, B น้ำเงิน) โดยแสดงเป็นเลขฐาน 16 จำนวน 2 หลักในแต่ละค่าสี อธิบายให้เข้าใจง่ายก็คือ ค่าสีที่เราดึงออกมานั้นเกิดจากการผสมของแม่สี RGB นี้เอง ตัวอย่างเช่น ถ้าตรวจได้สี 0xFF0000 ก็จะได้สีแดง, 0x00FF00 ก็จะได้สีเขียว หรือ 0xFFFFFF ก็จะได้สีขาว ในทางตรงข้าม  0x000000 จะเป็นสีดำ 

    AutoIt จะมีคำสั่งเกี่ยวกับสีอยู่หลายคำสั่งด้วยกัน แต่คำสั่งที่นิยมใช้กันบ่อยๆ ก็จะเป็นคำสั่ง PixelGetColor และ PixelSearch ในตัวอย่างนี้จะเริ่มกันที่คำสั่ง PixelGetColor ซึ่งเป็นคำสั่งสำหรับดึงเอาค่าสีในตำแหน่งที่กำหนดออกมา
สคริปต์ในตัวอย่างนี้ผมจะอ้างอิงจากตัวอย่างการดึงเอาสีในเกมมาเขียนดังนี้

If PixelGetColor(730, 619) = 0x343434 Then
 ;ดึงสีจากพิกัด 730,619  ถ้าได้สีเท่ากับ  0x343434 จะทำคำสั่งถัดไป
    Send("1")
;สั่งกดปุ่มหมายเลข 1 เมื่อเงื่อนไขตรวจสอบถูกต้อง
EndIf


     คำสั่งด้านบนคือการตั้งเงื่อนไขใช้คำสั่ง PixelGetColor ตรวจสีที่พิกัด 730, 619 หากสีที่ตรวจได้คือ 0x343434 โปรแกรมบอทก็จะกดปุ่ม 1 ทันที (คุณต้องนำขวดยา HP ไปวางไว้ในช่อง 1) ถ้านำไปรวมกับสคริปต์เดิมในบทก่อนหน้านี้ก็จะได้

Global $GameHD

Func _PSsixLoadH($gtitle)
$GameHD = WinGetHandle($gtitle)
If @error Then
MsgBox(4096, "Error", "ไม่พบหน้าต่างเกม")
Else
Return 1
EndIf
EndFunc

If _PSsixLoadH("Zuma Deluxe") Then WinActivate($GameHD)

If PixelGetColor(730, 619) = 0x343434 Then
Send("1")
EndIf


    ถ้าต้องการให้โปรแกรมทำงานอยู่ตลอดเวลา คอยตรวจเช็คดูว่า HP ลดถึงจุดที่กำหนดหรือไม่ ต้องใช้คำสั่ง While เข้าร่วม แต่ควรระวังไว้อย่างหนึ่งก็คือ ใส่คำสั่งหน่วงเวลา sleep ไว้ด้วย เพื่อป้องกันการดึงเอาพลังประมวลผล CPU ออกมามากเกินไป โค้ดแก้ไขแล้วจะได้ดังนี้


Global $GameHD

Func _PSsixLoadH($gtitle)
$GameHD = WinGetHandle($gtitle)
If @error Then
MsgBox(4096, "Error", "ไม่พบหน้าต่างเกม")
Else
Return 1
EndIf
EndFunc

If _PSsixLoadH("Zuma Deluxe") Then WinActivate($GameHD)

While 1
If PixelGetColor(730, 619) = 0x343434 Then
Send("1")
EndIf
Sleep(100)
WEnd


     เทคนิคการเขียนสคริปต์ ที่ใช้ร่วมกับการตรวจค่าสียังมีอีกจำนวนมาก ซึ่งจะนำเสนอให้ทราบในบทต่อไป สำหรับบทนี้จะหยุดแค่นี้ก่อน ถ้ามีเวลาว่างก็ลองใช้ AutoIt Window Info ตรวจหาสีอะไรก็ได้บนหน้าจอเล่นๆ แล้วสังเกตดูนะครับ จะได้เข้าใจยิ่งขึ้น


###จบแล้วครับ###

10 comments:

  1. ขอบคุณคับ อยากทำอย่างนี้มานาน

    ReplyDelete
  2. ขอบคุณมากครับ สุดยอดเลยครับ กำลังหาอ่านอยู่พอดี

    ReplyDelete
  3. โปรแกรมดาวโหลดตรงไหนหรอคับงง

    ReplyDelete
  4. http://pssix.forumotion.com/t536-topic

    ReplyDelete
  5. จากคำสั่งนี้ PixelGetColor(730, 619) = 0x343434
    ถ้าผมต้องการเปลี่ยนเป็นไม่เท่ากับจะต้องใช้เครื่องหมายอะไรแทน = ครับ
    ผมลองเปลี่ยนเป็น ~= แล้วโปรแกรมฟ้อง error
    ขอบคุณครับ :)

    ReplyDelete
  6. ปิดการ Complie script ยังไงคับ ผมปิดมันไม่ได้คับ restart แล้วก็ไม่หายคับ T-T

    ReplyDelete
  7. ControlClick ($GameHD, "", "","left",1,888,000) โค้ดนี้ไม่กดเลยแหะ (ผมใช้win8.1)T^T มีวิธีแก้ไหมนะ

    ReplyDelete
  8. มีใครรู้วิธีทำให้เคอร์เซอร์เมาส์ไม่เลื่อนตามมั้งเวลาจะเอาเมาส์ไปคลิก แบบว่า อยากดูหนังไปด้วยทำอยากอื่นไปด้วย

    ReplyDelete
  9. เราสามารถควบคุมเมาส์โดยไม่ให้เคอร์เซอเมาส์เลื่อนตามได้มั้ยอยากดูหนังหรือทำอย่างอื่นไปด้วยเวลาคุมเมาส์

    ReplyDelete
  10. Global $GameHD

    Func _PSsixLoadH($gtitle)
    $GameHD = WinGetHandle($gtitle)
    If @error Then
    MsgBox(4096, "Error", "ไม่พบหน้าต่างเกม")
    Else
    Return 1
    EndIf
    EndFunc

    If _PSsixLoadH("Genymotion for personal use") Then WinActivate($GameHD)


    If PixelGetColor(332, 83) = 0x0B1C34 Then
    Sleep(1000)
    Else
    ControlClick ($GameHD, "", "","left",1,333, 93)
    Sleep (1000)
    ControlClick ($GameHD, "", "","left",1,454, 227)
    EndIf
    มันเข้ารูป เป็นเท็จหมดเลยอะผิดตรงใหน

    ReplyDelete

    ส่วนนี้สำหรับแสดงความคิดเห็นทั่วไป สอบถามปัญหาตั้งถามได้ที่ฟอรั่ม


>>> [โปรดอ่าน] เนื่องจาก บทความการใช้งานบางโปรแกรมได้โฟสไปนานแล้ว
โปรแกรมอาจมีการอัปเดท วิธีการใช้งาน อาจใช้ไม่ได้ หรือมีวิธีที่ง่ายกว่าในเวอร์ชั่นใหม่
หากคุณพบว่าวิธีการใช้งานไม่ตรงกับบทความในบล็อกนี้ สามารถแนะนำเพิ่มเติมได้ครับ