Быстрая эмуляция нажатия клавиш в боте для браузерки - C#

Узнай цену своей работы

Формулировка задачи:

Пишу бота для браузерных танчиков.Прицеливание работает по принципу:через BitBlt копируется нужное окно в память, там ищутся группы пикселей определенного цвета(цвет имени врага), и если таковые найдены, нужно жать определенную кнопку(z или x) до тех пор, пока разница по абсциссе между центром имени противника и центром своих жизней(по ним определяется направление пушки), не станет меньше определенного числа(25 пикселей в данном случае). Эмуляцию нажатия клавиш реализую через PostMessage, ибо работать должно в неактивном окне. Все вроде пашет, но загвоздка в том, что пушка нередко "проезжает" цель, и начинается вертеться перед ней туда-сюда, то бишь PostMessage об отпускании клавиши не доходит вовремя. Сам алгоритм определения, когда надо остановиться, в ряд ли может быть неверным, ибо 100 раз проверен и в целом работает(то есть останавливается вовремя в тех случаях, когда пушка вертится медленнее обычного, либо просто удачно повернулась). Сообщения, которые я посылаю, полностью соответствуют аналогичным при реальном нажатии клавиш(через Spy++ проверялось). Кроме того при попытке эмулировать через keybd_event получилось ровно то же самое. Чего только не пробовал-и задержки разные, и сообщения, все то же самое. Скачал виртуальную клавиатуру-при попытке управлять с нее все работает нормально, то есть теоретически такая эмуляция возможна. Сразу скажу, что производительность при обработке изображения тут не причем, FPS достаточный, чтобы несколько кадров попало в положение, когда надо остановиться. На данный момент прога работает с гугл хромом, там проще однозначно достать хэндл нужного окна. Часть кода прилагается, желающим могу скинуть заготовку проги в личку. Жду ваших предположений, как это устранить, я пока что в тупике( но выход ищу. Заранее благодарен. Рабочие способы реализовать такое на других языках и по другим принципам тоже буду рассматривать, ибо делаю чисто ради развлечения и саморазвития, никуда не спешу. Эти куски кода миллион раз переписывались, на мелкие несуразности можете не обращать внимание, главное-указанный выше вопрос.
Листинг программы
  1. [DllImport("USER32.DLL", EntryPoint = "PostMessageW", SetLastError = true,
  2. CharSet = CharSet.Unicode, ExactSpelling = true,
  3. CallingConvention = CallingConvention.StdCall)]
  4. public static extern bool PostMessage(int hwnd, int Msg, int wParam, int lParam);
  5. public static bool e5 = false;
  6. public static bool e6 = false;
  7. public static bool e4 = false;
  8. public static bool in5 = true;
  9. public static bool in6 = true;
  10. public static bool in4 = true;
  11. public static System.Timers.Timer t4 = new System.Timers.Timer(60);
  12. public static System.Timers.Timer t5 = new System.Timers.Timer(60);
  13. public static System.Timers.Timer t6 = new System.Timers.Timer(60);
  14. public static void t4_Tick(object source, ElapsedEventArgs e)
  15. {
  16. try
  17. {
  18. if (e4)
  19. {
  20. if (!in4)
  21. {
  22. int virtual_code = MapVirtualKey(0x11, 1);
  23. int lp = 0x11 << 16 | 1;
  24. PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
  25. in4 = true;
  26. }
  27. else
  28. {
  29. int virtual_code = MapVirtualKey(0x11, 1);
  30. int lp = 0x11 << 16 | 1 << 30 | 1;
  31. PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
  32. }
  33.  
  34. }
  35. else
  36. {
  37. if (in4)
  38. {
  39. int virtual_code = MapVirtualKey(0x11, 1);
  40. int lp = 1 << 31 | 1 << 30 | 0x11 << 16 | 1;
  41. PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
  42. in4 = false;
  43. }
  44. }
  45. }
  46. catch { }
  47. }
  48. public static void t5_Tick(object source, ElapsedEventArgs e)
  49. { try
  50. {
  51. if (e5)
  52. {
  53. if (!in5)
  54. {
  55. int virtual_code = MapVirtualKey(0x2D, 1);
  56. int lp = 0x2D << 16 | 1;
  57. PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
  58. in5 = true;
  59. }
  60. else
  61. {
  62. int virtual_code = MapVirtualKey(0x2D, 1);
  63. int lp = 0x2D << 16 | 1 << 30 | 1;
  64. PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
  65. }
  66. }
  67. else
  68. {
  69. if (in5)
  70. {
  71. int virtual_code = MapVirtualKey(0x2D, 1);
  72. int lp = 1 << 31 | 1 << 30 | 0x2D << 16 | 1;
  73. PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
  74. in5 = false;
  75. }
  76. }
  77. }
  78. catch { }
  79. }
  80. public static void t6_Tick(object source, ElapsedEventArgs e)
  81. { try
  82. {
  83. if (e6)
  84. {
  85. if (!in6)
  86. {
  87. int virtual_code = MapVirtualKey(0x2C, 1);
  88. int lp = 0x2C << 16 | 1;
  89. PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
  90. in6 = true;
  91. }
  92. else
  93. {
  94. int virtual_code = MapVirtualKey(0x2C, 1);
  95. int lp = 0x2C << 16 | 1 << 30 | 1;
  96. PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
  97. }
  98. }
  99. else
  100. {
  101. if (in6)
  102. {
  103. int virtual_code = MapVirtualKey(0x2C, 1);
  104. int lp = 1 << 31 | 1 << 30 | 0x2C << 16 | 1;
  105. PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
  106. in6 = false;
  107. }
  108. }
  109. }
  110. catch { }
  111. }
  112.  
  113. private void threader() {
  114. t4.Elapsed += new ElapsedEventHandler(t4_Tick);
  115. t5.Elapsed += new ElapsedEventHandler(t5_Tick);
  116. t6.Elapsed += new ElapsedEventHandler(t6_Tick);
  117. t4.Interval = 100;
  118. t5.Interval = 100;
  119. t6.Interval = 100;
  120. t4.Enabled = true;
  121. t5.Enabled = true;
  122. t6.Enabled = true;
  123. while (true)
  124. {
  125. try
  126. {
  127. mozgi();
  128. }
  129. catch { }
  130. }
  131. }
  132. private void mozgi()
  133. {
  134. //тут делается снимок окна и находится minraznica.X = модуль разницы абсциссы между
  135. //центром имени врага и центром своей пушки. Корректно, проверено. А так же
  136. //переменная pravo, определяющая сторону, с которой находится враг.
  137. //enemynamesectorREAL это массив точек цвета имени врага.
  138. if (enemynamesectorREAL.Count > 0 && e4)
  139. {
  140. e4 = false;
  141. }
  142. if (enemynamesectorREAL.Count > 0 && minraznica.X > 25 && (!(e5 || e6)))
  143. {
  144. if (pravo)
  145. {
  146. e5 = true;
  147. }
  148. else
  149. {
  150. e6 = true;
  151. }
  152. }
  153. if ((pravo && e5) || (!pravo && e6) || enemynamesectorREAL.Count == 0 || minraznica.X <= 25)
  154. {
  155. bull = false;
  156. }
  157. else { bull = true; }
  158. if ((minraznica.X <= 25 || bull) && (e5 || e6) && enemynamesectorREAL.Count != 0)
  159. {
  160. if (e5)
  161. {
  162. e5 = false;
  163. int virtual_code = MapVirtualKey(0x2D, 1);
  164. int lp = 1 << 31 | 0 << 30 | 0x2D << 16 | 1;
  165. PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
  166. {
  167. notbuisy = false;
  168. }
  169. }
  170. if (e6)
  171. {
  172. e6 = false;
  173. int virtual_code = MapVirtualKey(0x2C, 1);
  174. int lp = 1 << 31 | 1 << 30 | 0x2C << 16 | 1;
  175. PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
  176. {
  177. notbuisy = false;
  178. }
  179. }
  180. }
  181. }
  182. else { }
  183. if ((enemynamesectorREAL.Count == 0 && !notbuisy) || (mls == 0 && !notbuisy))
  184. {
  185. if (e5 || e6)
  186. {
  187. notbuisy = true;
  188. }
  189. else
  190. {
  191. Random rand = new Random();
  192. switch (rand.Next(1))
  193. {
  194. case 0:
  195. e5 = true;
  196. notbuisy = true;
  197. break;
  198. case 1:
  199. e6 = true;
  200. notbuisy = true;
  201. break;
  202. }
  203. }
  204. }
  205. if ((enemynamesectorREAL.Count == 0 && !e4) || (mls == 0 && !e4))
  206. {
  207. e4 = true;
  208. }
  209. //тут можно вывести обрабатываемый битмап на экран с пометками, что удобно при отладке.
  210. mem.Dispose();
  211. }

Решение задачи: «Быстрая эмуляция нажатия клавиш в боте для браузерки»

textual
Листинг программы
  1.   BitmapData bmpData = mem.LockBits(new Rectangle(0, 0, mem.Width, mem.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
  2.                     byte[] bitmapBuffer = new byte[bmpData.Stride * bmpData.Height];
  3.                     Marshal.Copy(bmpData.Scan0, bitmapBuffer, 0, bitmapBuffer.Length);
  4.                     for (int j = 0; j < (int)ypos; j++)
  5.                     {
  6.                         int strideY = bmpData.Stride * j;
  7.                         for (int i = 0; i < (int)xpos; i++)
  8.                         {
  9.                             int index = strideY + i * byteLen;
  10.                             RGBcolor x = new RGBcolor();
  11.                             x.B = bitmapBuffer[index + 0];
  12.                             x.G = bitmapBuffer[index + 1];
  13.                             x.R = bitmapBuffer[index + 2];
  14.                             if (x.R == mylife.R && x.G == mylife.G && x.B == mylife.B)
  15.                             {
  16.                                 Coords coord;
  17.                                 coord.X = i;
  18.                                 coord.Y = j;
  19.                                 if (lifeminx > i) { lifeminx = i; }
  20.                                 if (lifemaxx < i) { lifemaxx = i; }
  21.                                 if (lifeminy > j) { lifeminy = j; }
  22.                                 if (lifemaxy < j) { lifemaxy = j; }
  23.                                 mylifesector.Add(coord);
  24.                                 mls++;
  25.                             }
  26.                             if ((Math.Abs(x.R - enemyname.R) < 20) && (Math.Abs(x.G - enemyname.G) < 30) && (Math.Abs(x.B - enemyname.B) < 20))
  27.                             {
  28.                                 Coords coord;
  29.                                 coord.X = i;
  30.                                 coord.Y = j;
  31.                                 enemynamesector.Add(coord);
  32.                                 ens++;
  33.                             }
  34.                             if ((Math.Abs(x.R - colorpuli.R) < 20) && (Math.Abs(x.G - colorpuli.G) < 25) && (Math.Abs(x.B - colorpuli.B) < 15))
  35.                             {
  36.                                 Coords coord;
  37.                                 coord.X = i;
  38.                                 coord.Y = j;
  39.                                 colorpulisector.Add(coord);
  40.                                 cps++;
  41.                             }
  42.                         }
  43.                     }
  44.                     mem.UnlockBits(bmpData);

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

5   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут