Jul 27, 2011
Wednesday, July 27, 2011

เขียนบอทเกมด้วย AutoIt : Bot 5 สร้างบอทยิงเป้าอัตโนมัติ

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

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

Global $gameX1, $gameY1
HotKeySet("{ESC}", "stop")
ShellExecute('http://game.hunsa.com//flashgame.php?gid=2358')


While Sleep(100)
    If WinActive("Rapid Fire2") Then
        FindGame()
    Else
    EndIf
WEnd


Func FindGame()
    $size = WinGetPos("[active]")
    $coord = PixelSearch($size[0], $size[1], $size[2], $size[3], 0x020504)
    If IsArray($coord) Then
        $gameX1 = $coord[0]
        $gameY1 = $coord[1]
        Return 1
    EndIf
EndFunc  


Func stop()
    Exit
EndFunc


#หาพิกัดมุมขวาล่าง เพื่อกำหนดขอบเขตหน้าต่างเกม
    เนื่องจากพิกัดมุมซ้ายบนเราได้เขียนสคริปต์อัปเดทเสร็จแล้ว ตอนนี้ก็เหลือแต่วิธีการหาตำแหน่งพิกัดมุมขวาล่าง เพื่อนำไปใช้เขียนกับคำสั่ง PixelSearch ซึ่งการหาพิกัดมุมขวาล่างไม่จำเป็นต้องเขียนสคริปต์หา เหมือนหามุมซ้ายบน เนื่องจากความกว้างยาวของหน้าต่างเกมมีขนาดที่แน่นอนอยู่แล้ว ดังนั้นการหาพิกัดที่มุมขวาล่าง สิ่งที่เราจะทำคือวัดระยะห่างระหว่างพิกัดแกน X, Y ที่มุมซ้ายบน กับมุมขวาล่างเท่านั้น เพื่อดูว่าพิกัดทั้ง 2 ตำแหน่งมีระยะห่างเท่าไหร่ ตอนเขียนสคริปต์ก็แค่เอาพิกัดมุมซ้ายบนมาบวกกับระห่างก็จะได้ตำแหน่งของพิกัดมุมขวาล่างแล้วครับ วิธีการทำมีดังนี้

1. เปิด AutoIt Window Info ขึ้นมาแล้วลากเป้าที่ Finder Tool ไปวางที่มุมซ้ายบนของหน้าต่างเกม

2. ที่แท็บเม้าส์จดพิกัดเอาไว้ ตัวอย่างนี้คือ 417,158



3. ลากเป้าที่ Finder Tool ไปวางที่มุมขวาล่าง

4. จดพิกัดเอาไว้ ตัวอย่างนี้คือ 836, 537



5. นำเอาตัวเลขแกน X Y ของมุมทั้งสองมาลบกัน ก็จะได้ระหว่างระหว่างพิกัดทั้ง 2 ผลที่ได้คือ

836-417 = 419 (นำไปใช้ในแกน X มุมขวาล่าง)

537-158 = 379 (นำไปใช้ในแกน Y มุมขวาล่าง)

    เมื่อนำมาเขียนคำสั่งกับ PixelSearch ก็จะได้ดังนี้
$coord = PixelSearch( $gameX1,$gameY1, $gameX1+419,$gameY1+379,รหัสสีที่ค้นหา )


หมายเหตุ
    ถ้าหากคุณอ่านมาถึงตรงนี้แล้วยังไม่เข้าใจ ก็นึกเอาง่ายๆ ว่าทุกครั้งที่เราหาพิกัดมุมซ้ายบน เราก็เพียงเอาพิกัดที่ได้นั้นมาบวกตัวเลขที่ได้จากขั้นตอนนี้ ก็จะได้พิกัดที่แน่นอนของมุมขวาล่างแล้ว 


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


if FindGame()=1 Then
;สร้างเงื่อนไข หากฟังก์ชัน FindGame() มีการส่งค่าออกมาเป็น 1 ให้ทำให้คำสั่งถัดไป
playgame()
;เรียกฟังก์ชัน playgame() ขึ้นมาทำงาน
EndIf
;จบเงื่อนไข


เมื่อนำไปเขียนสคริปต์แก้ไขในชุดคำสั่งเดิม ก็จะได้ดังนี้ (ดูสีเขียว)

While Sleep(100)
If WinActive("Rapid Fire2") Then
If FindGame() = 1 Then
playgame()
EndIf

Else
EndIf
WEnd

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



 #สร้างฟังก์ชั่นเพื่อค้นหาเป้า
    ขั้นต่อไปเป็นการสร้างคำสั่งในฟังก์ชัน playgame() โดยจะเขียนสคริปต์สำหรับค้นหาเป้าบิน ซึ่งจะใช้การค้นหาสี 2 ตำแหน่ง เพื่อช่วยยืนยันเป้าหมายที่จะสั่งคลิก วิธีการทำมีขั้นตอนดังนี้

1. เปิด AutoIt Window Info ขึ้นมาลากเม้าส์จาก Finder Tool ไปยังจุดที่มีสีไม่เหมือนพื้นหลัง ตามตัวอย่างนี้ผมลากเม้าส์ไปที่ก้านของเป้าบินตรงส่วนบน เหตุที่ต้องดึงเอาจุดสีตรงส่วนบนของก้านเป้าบิน เนื่องจากคำสั่ง PixelSearch ที่ใช้ค้นหาสีจะหาจากบนลงล่าง ดังนั้นการกำหนดหาสีของก้านต้องหาจุดสีที่อยู่ด้านบนก่อน เพราะจะหาได้เร็วกว่า

2. ที่แท็บ Mouse จดรหัสสีและพิกัดมา ตามตัวอย่างนี้คือ 0xC48600 มีพิกัดที่ 59,178




3. ลากเม้าส์จาก Finder Tool ไปยังจุดกึ่งกลางเป้าสีแดง

4. จดรหัสสีและพิกัดอีกเช่นกัน ตามตัวอย่างนี้คือ 0xFF0000 มีพิกัดที่ 60,213




    ตอนนี้เราก็ได้ข้อมูลที่ต้องการมาครบแล้ว เพื่อกันความสับสนผมจะอธิบายก่อนว่าข้อมูลแต่ละอย่างนั้นเอาไปทำอะไรบ้าง

0xC48600 ใช้เป็นรหัสสีแรกที่จะค้นในหน้าต่างเกม ด้วยคำสั่ง PixelSearch

0xFF0000 ใช้เป็นรหัสสีที่สองสำหรับใช้ตรวจซ้ำด้วยคำสั่ง PixelGetColor  ก่อนสั่งคลิก

พิกัด 59,178 และ 60,213 นำมาหาระยะห่างระหว่างก้านเป้าบิน กับจุดกลางเป้าสีแดง (วิธีการจะเหมือน วิธีหาระยะห่างมุมซ้ายบนกับมุมล่างขวา) ผลที่ได้คือ

60-59 = 1

213-178 = 35


    ขั้นตอนการเขียนสคริปต์ที่จะทำคือ ขั้นตอนสั่งให้หาสี 0xC48600 ซึ่งเป็นสีของก้านเป้าบิน ในหน้าต่างเกมก่อน เมื่อเจอแล้วโปรแกรมจะคืนค่าพิกัด X,Y มาให้ เราก็นำเอาพิกัดดังกล่าวมาบวก +1 กับ +35 เพื่อเลื่อนตำแหน่งจากก้านเป้าบินลงไปยังจุดกึ่งกลางเป้าที่มีสีแดง 0xFF0000 อยู่ โดยผมจะใช้คำสั่ง PixelGetColor ตรวจสีในตำแหน่งนั้นอีกครั้งว่าใช้สี 0xFF0000 หรือไม่ ถ้าปรากฏว่าใช่ ก็สั่งคลิกเพื่อยิงเป้ากึ่งกลางเป้าบินนั้น


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



Func playgame()
$coord = PixelSearch( $gameX1,$gameY1, $gameX1+419,$gameY1+379,0xC48600 )
If IsArray($coord)Then
if PixelGetColor( $coord[0]+1, $coord[1]+35) = 0xFF0000 then
MouseClick("Left",$coord[0]+1, $coord[1]+35,1,0)
EndIf


#สคริปต์ AutoIt บอทเกมยิงเป้าแบบเต็ม

    สคริปต์ด้านล่างนี้คือสคริปต์ AutoIt ที่สามารถนำไป คอมไพล์ใช้งานได้เลย


Global $gameX1, $gameY1

HotKeySet("{ESC}", "stop")
ShellExecute('http://game.hunsa.com//flashgame.php?gid=2358')


While Sleep(10)           
   If WinActive("Rapid Fire2") Then
If FindGame() = 1 Then
playgame()
EndIf
Else
EndIf
WEnd



Func playgame()
$coord = PixelSearch($gameX1, $gameY1, $gameX1 + 419, $gameY1 + 360, 0xc48600)
If IsArray($coord) Then
If PixelGetColor($coord[0] + 1, $coord[1] + 35) = 0xFF0000 Then
MouseClick("Left", $coord[0] + 1, $coord[1] + 35, 1, 0)
Sleep(100)
EndIf
EndIf
EndFunc



Func FindGame()
$size = WinGetPos("[active]")
$coord = PixelSearch($size[0], $size[1], $size[2], $size[3], 0x020504)
If IsArray($coord) Then
$gameX1 = $coord[0]
$gameY1 = $coord[1]
Return 1
EndIf
EndFunc



Func stop()
Exit
EndFunc


ส่งท้ายก้าวแรกเริ่มต้นเขียนบอท
     ก่อนบทความสอนการทำบอทด้วย AutoIt บทแรกจะออกมา ผมมีความลังเลอยู่พอสมควร เนื่องจากอาจมีผู้อ่านบางท่านที่ไม่มีพื้นฐานด้านการเขียนโปรแกรมอะไรเลย ไม่เข้าใจเรื่องที่ผมจะเขียนขึ้น ดังนั้นในบทแรกๆ ผมจึงอธิบายสิ่งที่เป็นพื้นฐานที่สุดสำหรับการทำบอทก็คือ การสั่งกดคีย์และการคลิกเม้าส์ อย่างไรก็ตาม แม้คุณจะอ่านบทความการทำบอทจนครบหมด แต่ในบางคนอาจจะยังไม่สามารถทำอะไรเกินกว่าที่สอนในหน้าบล็อก เนื่องจากยังขาดแนวคิดเพื่อแตกยอดความสามารถให้สูงไปอีก ในหัวข้อนี้จึงเป็นแนะแนวทางปฏิบัติ เพื่อให้การพัฒนาตนเองเกิดขึ้นเองโดยอัตโนมัติ ดังนี้

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

2. อย่ายึดติดกับรูปแบบคำสั่ง คำสั่งใน AutoIt มีหลายคำสั่งที่สามารถทำงานได้เหมือนกัน บางคำสั่งก็เหมาะสำหรับนำมาใช้กับบางกรณี บางคำสั่งก็ไม่เหมาะที่จะนำมาใช้ (แต่ก็ใช้ได้) แล้วคุณจะรู้ได้อย่างไรว่าชุดคำสั่งที่คุณเขียนขึ้นมาดีที่สุดหรือยัง คำตอบคือ คุณต้องลอง ลองไปเรื่อยๆ เมื่อค้นพบสิ่งที่เหมาะที่สุดแล้ว คุณจะรู้เอง ว่ามันใช่

3. นำเอาปัญหาของผู้อื่นมาตอบให้ตนเอง คุณลองเข้าฟอรั่ม AutoIt ในบล็อกนี้หรือยัง >>คลิก<< ถ้ายังก็ลองคลิกเข้าไปอ่านดูครับ ลองไล่ดูคำถามของผู้ใช้คนอื่น ดูว่าข้อไหนที่คุณตอบได้บ้าง ข้อไหนตอบไม่ได้ก็ลองไปค้นหาคำตอบเอง  คุณจะช่วยตอบหรือไม่ ไม่ใช่สิ่งสำคัญ แต่การค้นหาคำตอบของคำถามนั้น จะช่วยการพัฒนาแนวคิดการเขียนโปรแกรมบอทอย่างที่คุณคาดไม่ถึงทีเดียว

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

5. ศึกษาโค้ดของผู้อื่น สคริตป์ AutoIt มีผู้แจกจ่ายอยู่เป็นจำนวนมากในอินเตอร์เน็ต และมีเทคนิควิธีการใช้คำสั่งในสคริปต์หลากหลาย วิธีง่ายๆ เพื่อดูว่าแต่ละคำสั่งมีเทคนิคการใช้งานอย่างไรบ้าง ก็เพียงแค่พิมพ์คำสั่งดังกล่าวลงใน google ตัวอย่างเช่น คำสั่ง PixelGetColor ก็พิมพ์คำค้นหาลงไปว่า autoit pixelgetcolor คุณจะเห็นว่าเทคนิคการใช้คำสั่งนี้มีอยู่เป็นจำนวนมาก ลองสังเกตดูว่าเขาใช้คำสั่งอย่างไร ลองนำมาปรับหรือทดลองรันโค้ดดู เหล่านี้จะช่วยเปิดแนวคิดใหม่ๆ ในการเขียนสคริปต์ได้เป็นอย่างดี

6. ปัญหามีไว้พุ่งชน คุณคงเคยได้ยินจากโฆษณากันบ่อยๆ แต่ในชีวิตจริงหลายคนเลือกที่จะเลี่ยงปัญหา หากคุณยังทำตัวเป็นแบบนั้นอยู่ก็ยากจะประสบความสำเร็จในการเขียนสคริปต์ เพราะเมื่อเริ่มเขียนคุณต้องเจอปัญหาอย่างแน่นอน ไม่มีใครที่เริ่มเขียนแล้วไม่ติดปัญหาหรอกครับ แม้แต่คนที่ชำนาญแล้วก็บางครั้งก็หลงลืมเขียนไวยากรณ์ผิดตัวเดียว หน้าต่าง Error เด้งขึ้นมาเต็มจอ ดังนั้นจงทำใจไว้ก่อนว่าเขียนโค้ดต้องมีปัญหาอย่างแน่นอน หากเจอแล้วก็อย่าเพิ่งท้อ ลองไล่หาทางแก้ไปเรื่อยๆ ก็จะพบทางแก้เอง หรือถ้าไม่ได้จริงๆ ก็ต้องทำใจปล่อยมันไป ก็แค่นั้น

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

6 comments:

  1. ขอบคุณครับท่าน Admin

    ReplyDelete
  2. ขอบคุณมากๆ ครับ

    ReplyDelete
  3. ผมอยากทำ อันนี้เป็นอ่ะครับ... ทำเท่าไหร่ก็ไม่ได้

    ตอนนี้ใช้ อันนี้อยุ่ครับ ไม่ค่อยเจ๋งเลย... แต่ก็ทำงานได้เกือบดี -3-
    http://pssix.blogspot.com/2011/06/autoit-bot-3.html

    ReplyDelete
  4. PixelGetColor จะงานกับหน้าต่างที่ Active ครับ

    ReplyDelete
  5. พอมีวิธีเอาไปใช้กะเกมออนไลน์ป่าวครับ

    ReplyDelete

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


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