Форум программистов, компьютерный форум, киберфорум
C#: API, боты
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.82/50: Рейтинг темы: голосов - 50, средняя оценка - 4.82
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
1

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

14.02.2013, 19:20. Показов 9185. Ответов 42
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Пишу бота для браузерных танчиков.Прицеливание работает по принципу:через BitBlt копируется нужное окно в память, там ищутся группы пикселей определенного цвета(цвет имени врага), и если таковые найдены, нужно жать определенную кнопку(z или x) до тех пор, пока разница по абсциссе между центром имени противника и центром своих жизней(по ним определяется направление пушки), не станет меньше определенного числа(25 пикселей в данном случае). Эмуляцию нажатия клавиш реализую через PostMessage, ибо работать должно в неактивном окне. Все вроде пашет, но загвоздка в том, что пушка нередко "проезжает" цель, и начинается вертеться перед ней туда-сюда, то бишь PostMessage об отпускании клавиши не доходит вовремя. Сам алгоритм определения, когда надо остановиться, в ряд ли может быть неверным, ибо 100 раз проверен и в целом работает(то есть останавливается вовремя в тех случаях, когда пушка вертится медленнее обычного, либо просто удачно повернулась). Сообщения, которые я посылаю, полностью соответствуют аналогичным при реальном нажатии клавиш(через Spy++ проверялось). Кроме того при попытке эмулировать через keybd_event получилось ровно то же самое. Чего только не пробовал-и задержки разные, и сообщения, все то же самое. Скачал виртуальную клавиатуру-при попытке управлять с нее все работает нормально, то есть теоретически такая эмуляция возможна. Сразу скажу, что производительность при обработке изображения тут не причем, FPS достаточный, чтобы несколько кадров попало в положение, когда надо остановиться. На данный момент прога работает с гугл хромом, там проще однозначно достать хэндл нужного окна. Часть кода прилагается, желающим могу скинуть заготовку проги в личку. Жду ваших предположений, как это устранить, я пока что в тупике( но выход ищу. Заранее благодарен. Рабочие способы реализовать такое на других языках и по другим принципам тоже буду рассматривать, ибо делаю чисто ради развлечения и саморазвития, никуда не спешу. Эти куски кода миллион раз переписывались, на мелкие несуразности можете не обращать внимание, главное-указанный выше вопрос.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
        [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();
                    
        }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.02.2013, 19:20
Ответы с готовыми решениями:

Эмуляция нажатия клавиш для SDL
Столкнулся с такой проблемой что на эмуляцию нажатия клавиш, SDL не реагирует. Точнее DOSBox....

Эмуляция нажатия клавиш для неактивного/свёрнутого приложения.
Есть большое желание написать что-то наподобии программы-макроса, которая будет отправлять или...

Эмуляция нажатия клавиш для другого приложения (Win10 Под D3D) не работает
Добрый день! У меня такая трабла возникла. Нужно В игре под директ3Д зажать правую кнопку мышки на...

Перехватчик клавиш + эмуляция нажатия клавиш
Здравствуйте! Срочно нужна помощь! Моя программа работает в фоновом режиме. Мне нужно: 1) чтобы...

42
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
18.02.2013, 13:47  [ТС] 41
Author24 — интернет-сервис помощи студентам
Ну тут я соглашусь, ибо был у меня один код на С, который я 3 раза переписывал и в результате он сократился с 3000 строк до 1200, при этом функциональность только выросла
А понять, что делает сей код, не зная даже близко игры, конечно крайней проблематично Но все равно спасибо, может что из него мне пригодится.
Вопрос в том, что считать мусором. Та часть кода, которую мы обсуждали, по-моему не критична, но в целом, определенно, лишние константы и переменные, которые объявляются не там, где нужно, следует почистить при доводке кода, когда он перестанет менять постоянно глобально менять свою структуру и придет к чему-то определенному. Для форума я оставил ту часть функционала, которая не факт, что работает правильно, методы могу прокомментировать:

t4-отвечает за движение танка вперед(при условии, что врага на экране нет)

t5-отвечает за поворот пушки направо, если справа враг, либо если враг отсутствует на экране.

t6 отвечает за поворот пушки влево, если слева враг, либо если враг отсутствует на экране.

Если враг отсутствует-направление выбирается рандомно.

Mozgi() соответственно определяет, какой из таймеров должен посылать нажатия, при помощи глобальных переменных bool e4 e5 e6. Запущен в бесконечном цикле отдельным потоком. Переменные pravo и minraznica.X описаны в коде, в них определена сторона и расстоние в пикселях от прицела до врага по абсциссе. Если эта разница в пикселях меньше 25ти-считается, что я стреляю туда, куда нужно.
0
Winhttp22
18.02.2013, 13:51
  #42

Не по теме:

EvilFromHell, дайте ссылку на игру

0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
18.02.2013, 13:57  [ТС] 43
Вот
0
18.02.2013, 13:57
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.02.2013, 13:57
Помогаю со студенческими работами здесь

Эмуляция нажатия клавиш.
Программа заключается в том, чтоб был постоянно повторяющийся цикл(по моему так) раз в пол...

Эмуляция нажатия клавиш
здрасте.мне нужно проэмулировать нажатие кнопок мыши и нажатий клавиш в неактивном окне(конкретно в...

Эмуляция нажатия клавиш
Всем привет! Помогите написать простенькую программу. Что должна делать? Вводим число в Edit (в...

Эмуляция нажатия клавиш
помогите с кодом разобраться, не работает( Var PWD, Login : String; procedure...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
43
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru