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

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

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

Пишу бота для браузерных танчиков.Прицеливание работает по принципу:через BitBlt копируется нужное окно в память, там ищутся группы пикселей определенного цвета(цвет имени врага), и если таковые найдены, нужно жать определенную кнопку(z или x) до тех пор, пока разница по абсциссе между центром имени противника и центром своих жизней(по ним определяется направление пушки), не станет меньше определенного числа(25 пикселей в данном случае). Эмуляцию нажатия клавиш реализую через PostMessage, ибо работать должно в неактивном окне. Все вроде пашет, но загвоздка в том, что пушка нередко "проезжает" цель, и начинается вертеться перед ней туда-сюда, то бишь PostMessage об отпускании клавиши не доходит вовремя. Сам алгоритм определения, когда надо остановиться, в ряд ли может быть неверным, ибо 100 раз проверен и в целом работает(то есть останавливается вовремя в тех случаях, когда пушка вертится медленнее обычного, либо просто удачно повернулась). Сообщения, которые я посылаю, полностью соответствуют аналогичным при реальном нажатии клавиш(через Spy++ проверялось). Кроме того при попытке эмулировать через keybd_event получилось ровно то же самое. Чего только не пробовал-и задержки разные, и сообщения, все то же самое. Скачал виртуальную клавиатуру-при попытке управлять с нее все работает нормально, то есть теоретически такая эмуляция возможна. Сразу скажу, что производительность при обработке изображения тут не причем, FPS достаточный, чтобы несколько кадров попало в положение, когда надо остановиться. На данный момент прога работает с гугл хромом, там проще однозначно достать хэндл нужного окна. Часть кода прилагается, желающим могу скинуть заготовку проги в личку. Жду ваших предположений, как это устранить, я пока что в тупике( но выход ищу. Заранее благодарен. Рабочие способы реализовать такое на других языках и по другим принципам тоже буду рассматривать, ибо делаю чисто ради развлечения и саморазвития, никуда не спешу. Эти куски кода миллион раз переписывались, на мелкие несуразности можете не обращать внимание, главное-указанный выше вопрос.
        [DllImport("USER32.DLL", EntryPoint = "PostMessageW", SetLastError = true,
                     CharSet = CharSet.Unicode, ExactSpelling = true,
                     CallingConvention = CallingConvention.StdCall)]
        public static extern bool PostMessage(int hwnd, int Msg, int wParam, int lParam);
 
        public static bool e5 = false;
        public static bool e6 = false;
        public static bool e4 = false;
        public static bool in5 = true;
        public static bool in6 = true;
        public static bool in4 = true;
        public static System.Timers.Timer t4 = new System.Timers.Timer(60);
        public static System.Timers.Timer t5 = new System.Timers.Timer(60);
        public static System.Timers.Timer t6 = new System.Timers.Timer(60);
 public static  void t4_Tick(object source, ElapsedEventArgs e)
{
   try
        {
    if (e4)
    {
            if (!in4)
            {
                int virtual_code = MapVirtualKey(0x11, 1);
                int lp = 0x11 << 16 | 1;
                PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
                in4 = true;
            }
            else
            {
                int virtual_code = MapVirtualKey(0x11, 1);
                int lp = 0x11 << 16 | 1 << 30 | 1;
                PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
            }

    }
    else
    {
        if (in4)
        {
            int virtual_code = MapVirtualKey(0x11, 1);
            int lp = 1 << 31 | 1 << 30 | 0x11 << 16 | 1;
            PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
            in4 = false;
        }
    }
        }
             catch { }
}
 
public static void t5_Tick(object source, ElapsedEventArgs e)
{        try
        {
    if (e5)
    {
 
            if (!in5)
            {
                int virtual_code = MapVirtualKey(0x2D, 1);
                int lp = 0x2D << 16 | 1;
                PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
                in5 = true;
            }
            else
            {
                int virtual_code = MapVirtualKey(0x2D, 1);
                int lp = 0x2D << 16 | 1 << 30 | 1;
                PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
            }
        }
    else
    {
        if (in5)
        {
            int virtual_code = MapVirtualKey(0x2D, 1);
            int lp = 1 << 31 | 1 << 30 | 0x2D << 16 | 1;
            PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
            in5 = false;
        }
    }
        }
catch { }
}
 
public static void t6_Tick(object source, ElapsedEventArgs e)
{        try
        {
    if (e6)
    {
 
            if (!in6)
            {
                int virtual_code = MapVirtualKey(0x2C, 1);
                int lp = 0x2C << 16 | 1;
                PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
                in6 = true;
            }
            else
            {
                int virtual_code = MapVirtualKey(0x2C, 1);
                int lp = 0x2C << 16 | 1 << 30 | 1;
                PostMessage((int)win3, WM_KEYDOWN, virtual_code, lp);
            }
        }
    else
    {
        if (in6)
        {
            int virtual_code = MapVirtualKey(0x2C, 1);
            int lp = 1 << 31 | 1 << 30 | 0x2C << 16 | 1;
            PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
            in6 = false;
        }
    }
        }
catch { }
}

   private void threader() {
            t4.Elapsed += new ElapsedEventHandler(t4_Tick);
            t5.Elapsed += new ElapsedEventHandler(t5_Tick);
            t6.Elapsed += new ElapsedEventHandler(t6_Tick);
            t4.Interval = 100;
            t5.Interval = 100;
            t6.Interval = 100;
            t4.Enabled = true;
            t5.Enabled = true;
            t6.Enabled = true;
        while (true)
        {
            try
            {
                mozgi();
            }
            catch { }
        }
        }
 
        private void mozgi()
        {
//тут делается снимок окна и находится minraznica.X = модуль разницы абсциссы между 
//центром имени врага и центром своей пушки. Корректно, проверено. А так же
//переменная pravo, определяющая сторону, с которой находится враг.
//enemynamesectorREAL это массив точек цвета имени врага.
                        if (enemynamesectorREAL.Count > 0 && e4)
                        {
                            e4 = false;
                        }
 
                        if (enemynamesectorREAL.Count > 0 && minraznica.X > 25 && (!(e5 || e6)))
                        {
                            if (pravo)
                            {
                                e5 = true;
                            }
 
                            else
                            {
                                e6 = true;
                            }
                        }
 
                        if ((pravo && e5) || (!pravo && e6) || enemynamesectorREAL.Count == 0 || minraznica.X <= 25)
                        {
                            bull = false;
                        }
                        else { bull = true; }
 
                        if ((minraznica.X <= 25 || bull) && (e5 || e6) && enemynamesectorREAL.Count != 0)
                        {
                            if (e5)
                            {
                                e5 = false;
                                int virtual_code = MapVirtualKey(0x2D, 1);
                                int lp = 1 << 31 | 0 << 30 | 0x2D << 16 | 1;
                                PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
                                {
                                    notbuisy = false;
                                }
                            }
                            if (e6)
                            {
                                e6 = false;
                                int virtual_code = MapVirtualKey(0x2C, 1);
                                int lp = 1 << 31 | 1 << 30 | 0x2C << 16 | 1;
                                PostMessage((int)win3, WM_KEYUP, virtual_code, lp);
                                {
                                    notbuisy = false;
                                }
                            }
                        }
                    }
                    else { }
 
                        if ((enemynamesectorREAL.Count == 0 && !notbuisy) || (mls == 0 && !notbuisy))
                        {
                            if (e5 || e6)
                            {
                                notbuisy = true;
                            }
                            else
                            {
                                Random rand = new Random();
                                switch (rand.Next(1))
                                {
                                    case 0: 
                                        e5 = true;
                                        notbuisy = true;
                                        break;
                                    case 1: 
                                        e6 = true;
                                        notbuisy = true;
                                        break;
                                }
                            }
                        }
                        if ((enemynamesectorREAL.Count == 0 && !e4) || (mls == 0 && !e4))
                        {
                            e4 = true;
                        }
 
//тут можно вывести обрабатываемый битмап на экран с пометками, что удобно при отладке.
 
                    mem.Dispose();
                    
        }

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

textual
Листинг программы
  BitmapData bmpData = mem.LockBits(new Rectangle(0, 0, mem.Width, mem.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                    byte[] bitmapBuffer = new byte[bmpData.Stride * bmpData.Height];
                    Marshal.Copy(bmpData.Scan0, bitmapBuffer, 0, bitmapBuffer.Length);
                    for (int j = 0; j < (int)ypos; j++)
                    {
                        int strideY = bmpData.Stride * j;
                        for (int i = 0; i < (int)xpos; i++)
                        {
                            int index = strideY + i * byteLen;
                            RGBcolor x = new RGBcolor();
                            x.B = bitmapBuffer[index + 0];
                            x.G = bitmapBuffer[index + 1];
                            x.R = bitmapBuffer[index + 2];
                            if (x.R == mylife.R && x.G == mylife.G && x.B == mylife.B)
                            {
                                Coords coord;
                                coord.X = i;
                                coord.Y = j;
                                if (lifeminx > i) { lifeminx = i; }
                                if (lifemaxx < i) { lifemaxx = i; }
                                if (lifeminy > j) { lifeminy = j; }
                                if (lifemaxy < j) { lifemaxy = j; }
                                mylifesector.Add(coord);
                                mls++;
                            }
                            if ((Math.Abs(x.R - enemyname.R) < 20) && (Math.Abs(x.G - enemyname.G) < 30) && (Math.Abs(x.B - enemyname.B) < 20))
                            {
                                Coords coord;
                                coord.X = i;
                                coord.Y = j;
                                enemynamesector.Add(coord);
                                ens++;
                            }
                            if ((Math.Abs(x.R - colorpuli.R) < 20) && (Math.Abs(x.G - colorpuli.G) < 25) && (Math.Abs(x.B - colorpuli.B) < 15))
                            {
                                Coords coord;
                                coord.X = i;
                                coord.Y = j;
                                colorpulisector.Add(coord);
                                cps++;
                            }
                        }
                    }
                    mem.UnlockBits(bmpData);

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


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

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

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