一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

用JAVA和adb實(shí)現(xiàn)微信跳一跳全自動(dòng)完成

 一本正經(jīng)地胡鬧 2019-04-15

最近很火的微信小程序跳一跳,玩了幾次分?jǐn)?shù)都低的可憐,所以作為碼農(nóng)的我就想著怎么通過程序去實(shí)現(xiàn)自動(dòng)跳啊跳啊跳啊跳。。。

下面簡單講講個(gè)人實(shí)現(xiàn)方法及過程,請(qǐng)連上android手機(jī),讓程序飛起來吧!


一、基本思路

微信跳一跳原理就是小人和目標(biāo)物體上表面中心點(diǎn)的直線距離,然后根據(jù)按住屏幕時(shí)間長短跳到相應(yīng)的位置,

擊中目標(biāo)物體上表面區(qū)域中心點(diǎn)附近即可得分。

  • 我們可以看到微信跳一跳背景顏色是接近單調(diào)色,所以很容易就過濾掉背景色;

  • 小人顏色也是固定的,所以也很容易定位小人所在的位置;

  • 目標(biāo)物體顏色跟背景色區(qū)別比較大,也很容易定位;

  • 采用adb shell 可以很簡單的控制Android手機(jī);

二、實(shí)現(xiàn)過程

軟硬件環(huán)境: adb、java、MAC、android手機(jī)一臺(tái)(1080*1920)

  1. MAC連接android手機(jī),手機(jī)端打開usb調(diào)試開關(guān);

  2. 首先是要獲取手機(jī)屏幕截圖,代碼如下:
    注意:獲取屏幕截圖要等屏幕圖片穩(wěn)定下來,即跳完后3秒左右,不然一些彈出的圖像會(huì)干擾到計(jì)算點(diǎn)位

    1. private static void getScreenshot() {
    2. try {
    3. // 獲取手機(jī)截圖
    4. Runtime.getRuntime()
    5. .exec("/Users/gavin/adt-bundle-mac/sdk/platform-tools/adb shell /system/bin/screencap -p /sdcard/screenshot.png");
    6. Thread.sleep(1000);

    7. // 上傳手機(jī)截圖到電腦
    8. Runtime.getRuntime()
    9. .exec("/Users/gavin/adt-bundle-mac/sdk/platform-tools/adb pull /sdcard/screenshot.png /Users/gavin/Downloads/screenshot.png");
    10. Thread.sleep(1000);
    11. System.out.print("Get screenshot success!\n");
    12. } catch (Exception e) {
    13. e.printStackTrace();
    14. }

    15. }
  3. 通過截圖獲取小人和目標(biāo)物體的坐標(biāo),然后計(jì)算直線距離,最后乘以1.35ms,得到的就是長按的時(shí)間;


    得到的測試圖片如下:
     

    1. public static void getPosition() throws Exception {
    2. int[] rgb = new int[3];
    3. File file = new File(IMAGE_PATH);
    4. BufferedImage bi = null;
    5. try {
    6. bi = ImageIO.read(file);
    7. } catch (Exception e) {
    8. e.printStackTrace();
    9. }

    10. // 只搜索屏幕中間矩形區(qū)域,可根據(jù)分辨率配置高度
    11. int width = bi.getWidth();
    12. int height = mEndY;
    13. int minx = bi.getMinX();
    14. int miny = mStartY;

    15. int personStartX = 0;
    16. int personStartY = 0;
    17. int personEndX = 0;
    18. int personEndY = 0;

    19. int targetStartX = 0;
    20. int targetStartY = 0;
    21. int targetEndX = 0;
    22. int targetEndY = 0;
    23. int targetR = 0;
    24. int targetG = 0;
    25. int targetB = 0;

    26. // 獲取背景色值,這里直接選取坐標(biāo)(500, 500)這個(gè)點(diǎn)的顏色值,不同分辨率手機(jī)要依據(jù)實(shí)際情況修改
    27. int pixel = bi.getRGB(500, 500);
    28. mBasicR = (pixel & 0xff0000) >> 16;
    29. mBasicG = (pixel & 0xff00) >> 8;
    30. mBasicB = (pixel & 0xff);
    31. System.out.println("mBasicR = " + mBasicR + ", mBasicG = " + mBasicG + ", mBasicB = " + mBasicB);

    32. // 獲取小人區(qū)域和中心點(diǎn)
    33. for (int j = miny; j < height; j++) {
    34. for (int i = minx; i < width; i++) {
    35. pixel = bi.getRGB(i, j);
    36. rgb[0] = (pixel & 0xff0000) >> 16;
    37. rgb[1] = (pixel & 0xff00) >> 8;
    38. rgb[2] = (pixel & 0xff);

    39. // 背景顏色跳過
    40. if (getColorOffset(mBasicR, mBasicG, mBasicB, rgb[0], rgb[1], rgb[2]) < mColorOffset){
    41. continue;
    42. }

    43. // 小人顏色接近點(diǎn),用取色器取到的小人底部中心點(diǎn)顏色大致為R:55, G:55, B:93,所以可以搜索目標(biāo)區(qū)域的該顏色相近的區(qū)域
    44. // 然后取X, Y坐標(biāo)最小和最大的兩個(gè)值
    45. // 最后計(jì)算最大最小值的中間值
    46. if (rgb[0] >= 50 && rgb[0] <= 60 && rgb[1] >= 50 && rgb[1] <= 60 && rgb[2] >= 90 && rgb[2] <= 95 ){
    47. if (personStartX == 0){
    48. personStartX = i;
    49. personStartY = j;
    50. personEndX = i;
    51. personEndY = j;
    52. }

    53. if (i <= personStartX){
    54. personStartX = i;
    55. }
    56. if (j <= personStartY){
    57. personStartY = j;
    58. }

    59. if (i >= personEndX){
    60. personEndX = i;
    61. }
    62. if (j >= personEndY){
    63. personEndY = j;
    64. }
    65. }
    66. }
    67. }

    68. mPersonX = personStartX + ((personEndX - personStartX) / 2) - 15;
    69. mPersonY = personEndY - 20;



    70. // 獲取下一個(gè)物體位置
    71. for (int j = miny; j < height; j++) {
    72. for (int i = minx; i < width; i++) {
    73. pixel = bi.getRGB(i, j);
    74. rgb[0] = (pixel & 0xff0000) >> 16;
    75. rgb[1] = (pixel & 0xff00) >> 8;
    76. rgb[2] = (pixel & 0xff);

    77. // 背景顏色跳過
    78. if (getColorOffset(mBasicR, mBasicG, mBasicB, rgb[0], rgb[1], rgb[2]) < mColorOffset){
    79. continue;
    80. }

    81. // 過濾小人干擾,通過調(diào)試發(fā)現(xiàn)有時(shí)候小人會(huì)干擾判斷所以要過濾小人所在的縱向區(qū)域
    82. if (Math.abs(i - mPersonX) < 50){
    83. continue;
    84. }

    85. // 從上至下橫向便利每個(gè)點(diǎn)(排除上面的背景色和小人縱向區(qū)域),獲取到的第一個(gè)其他顏色點(diǎn)即為物體上邊緣點(diǎn)
    86. if (targetStartX == 0){
    87. targetStartX = i;
    88. targetStartY = j + 10; // 加點(diǎn)偏移量,使其定位到物體較大面積區(qū)域的顏色
    89. pixel = bi.getRGB(targetStartX, targetStartY);
    90. rgb[0] = (pixel & 0xff0000) >> 16;
    91. rgb[1] = (pixel & 0xff00) >> 8;
    92. rgb[2] = (pixel & 0xff);
    93. targetR = rgb[0];
    94. targetG = rgb[1];
    95. targetB = rgb[2];
    96. }

    97. // 根據(jù)上面取到的上邊緣點(diǎn),縱向向下搜索相同顏色的點(diǎn)中Y坐標(biāo)最大的點(diǎn),注意要根據(jù)跳躍的進(jìn)度修改縱向搜索區(qū)域
    98. // 這里的mTargetHeight 默認(rèn)值設(shè)為250,即搜索縱向250個(gè)像素點(diǎn),然后在主函數(shù)那個(gè)每10次遞減10直到最小值為20
    99. // 可根據(jù)調(diào)試結(jié)果修改
    100. if (targetStartX != 0 &&targetStartY != 0){
    101. if (i >= targetStartX - 25 && i < targetStartX + 25 && j < targetStartY + mTargetHeight && getColorOffset(targetR, targetG, targetB, rgb[0], rgb[1], rgb[2]) <= 3){
    102. targetEndX = i;
    103. targetEndY = j;
    104. }
    105. }
    106. }
    107. }

    108. mTargetX = targetStartX;
    109. mTargetY = targetStartY + ((targetEndY - targetStartY) / 2) - 10;

    110. System.out.println("mPersonX = " + mPersonX + ", mPsersonY = " + mPersonY + ", mTargetX = " + mTargetX + ", mTargetY = " + mTargetY);

    111. // 將處理完后的圖片,如小人位置,物體上下邊緣點(diǎn)和中心點(diǎn)、搜索矩形區(qū)域繪制好后保存,以便調(diào)試調(diào)整參數(shù)
    112. drawPoint(IMAGE_PATH, Color.green, mPersonX, mPersonY);
    113. drawPoint(mImageOutPath, Color.red, targetStartX, targetStartY);
    114. drawPoint(mImageOutPath, Color.red, targetEndX, targetEndY);
    115. drawPoint(mImageOutPath, Color.red, mTargetX, mTargetY);
    116. drawRect(mImageOutPath, 0, mStartY, width, mEndY - mStartY);

    117. }
  4. adb shell沒有長按,所以我用swipe替換,結(jié)果是一樣的。

    根據(jù)第三步中獲取的位置計(jì)算滑動(dòng)時(shí)間,每個(gè)像素點(diǎn)1.35ms,我的測試機(jī)是1080*1920,不同分辨率不一樣可以自行調(diào)整匹配。

    1. private static void swipeTime(long ms) {
    2. try {
    3. Runtime.getRuntime()
    4. .exec("/Users/gavin/adt-bundle-mac/sdk/platform-tools/adb shell input swipe 400 400 600 600 " + ms);
    5. } catch (Exception e) {
    6. e.printStackTrace();
    7. }

    8. }
  5. 運(yùn)行日志如下:



三、源碼下載:

 https://github.com/zjc3909/tiaotiao


四、運(yùn)行

 游戲打開,點(diǎn)擊開始游戲后
 terminal 運(yùn)行:
  1. javac -d . Tiaotiao.java
  2. java Tiaotiao

 有什么問題歡迎交流。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    91国内视频一区二区三区| 不卡中文字幕在线免费看| 搡老熟女老女人一区二区| 精品人妻一区二区三区四在线| 欧美日韩视频中文字幕| 人妻少妇久久中文字幕久久| 成人精品欧美一级乱黄| 成年午夜在线免费视频| 亚洲一区二区精品免费| 欧美日韩视频中文字幕| 在线日韩中文字幕一区| 国内精品一区二区欧美| 中文字幕乱码亚洲三区| 最新69国产精品视频| 亚洲综合伊人五月天中文| 香港国产三级久久精品三级| 国产又大又黄又粗的黄色| 青青久久亚洲婷婷中文网| 久久国内午夜福利直播| 日韩一区二区三区久久| 国产永久免费高清在线精品| 日本在线高清精品人妻| 一级片二级片欧美日韩| 欧美精品二区中文乱码字幕高清| 欧美日韩精品一区免费| 午夜国产精品国自产拍av| 日韩一区中文免费视频| 一区二区三区免费公开| 懂色一区二区三区四区| 日韩亚洲精品国产第二页| 精品人妻一区二区三区四区久久| 日本熟妇五十一区二区三区| 办公室丝袜高跟秘书国产| 日本91在线观看视频| 国产一级不卡视频在线观看| 亚洲熟女乱色一区二区三区| 日本人妻精品中文字幕不卡乱码| 欧美精品久久一二三区| 亚洲一区二区三区精选| 99久久精品午夜一区| 亚洲熟妇中文字幕五十路|