How to Send Keys to a Game I Am Playing,Using Python

Send Keys to Game Container 2048

Try it:

from selenium.webdriver.common.keys import Keys
import random
import time

moves = [Keys.LEFT, Keys.DOWN, Keys.RIGHT, Keys.UP]
while True:
driver.find_element_by_css_selector('body').send_keys(random.choice(moves))
time.sleep(2)

python: How can I press arrow keys randomly selenium

How to simulate keys in game with pywinauto

We have had a long journey my past self. Though we have much to learn here is what we discovered:

Sending Virtual Keys will be ignored if the game is running on DirectX.
Use sendinput and send the scan_codes instead.

# http://www.gamespp.com/directx/directInputKeyboardScanCodes.html

import ctypes
import time

SendInput = ctypes.windll.user32.SendInput

W = 0x11
A = 0x1E
S = 0x1F
D = 0x20
Z = 0x2C
UP = 0xC8
DOWN = 0xD0
LEFT = 0xCB
RIGHT = 0xCD
ENTER = 0x1C

# C struct redefinitions
PUL = ctypes.POINTER(ctypes.c_ulong)
class KeyBdInput(ctypes.Structure):
_fields_ = [("wVk", ctypes.c_ushort),
("wScan", ctypes.c_ushort),
("dwFlags", ctypes.c_ulong),
("time", ctypes.c_ulong),
("dwExtraInfo", PUL)]

class HardwareInput(ctypes.Structure):
_fields_ = [("uMsg", ctypes.c_ulong),
("wParamL", ctypes.c_short),
("wParamH", ctypes.c_ushort)]

class MouseInput(ctypes.Structure):
_fields_ = [("dx", ctypes.c_long),
("dy", ctypes.c_long),
("mouseData", ctypes.c_ulong),
("dwFlags", ctypes.c_ulong),
("time",ctypes.c_ulong),
("dwExtraInfo", PUL)]

class Input_I(ctypes.Union):
_fields_ = [("ki", KeyBdInput),
("mi", MouseInput),
("hi", HardwareInput)]

class Input(ctypes.Structure):
_fields_ = [("type", ctypes.c_ulong),
("ii", Input_I)]

# Actuals Functions

def pressKey(hexKeyCode):
extra = ctypes.c_ulong(0)
ii_ = Input_I()
ii_.ki = KeyBdInput( 0, hexKeyCode, 0x0008, 0, ctypes.pointer(extra) )
x = Input( ctypes.c_ulong(1), ii_ )
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

def releaseKey(hexKeyCode):
extra = ctypes.c_ulong(0)
ii_ = Input_I()
ii_.ki = KeyBdInput( 0, hexKeyCode, 0x0008 | 0x0002, 0,
ctypes.pointer(extra) )
x = Input( ctypes.c_ulong(1), ii_ )
ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

if __name__ == '__main__':
pressKey(0x11)
time.sleep(1)
releaseKey(0x11)
time.sleep(1)

Source:
Simulate Python keypresses for controlling a game
http://www.gamespp.com/directx/directInputKeyboardScanCodes.html

Thank you Sentdex for awesome tutorials on Machine Learning.
I've been wanting to do this to some of my favorite games but couldn't get the keys across (due to DirectX).

Next step:
Windows Driver Kit to emulate keypresses...

Send key input to HTML5 game using Selenium

Looks like selenium doesn't focus on your app.

Try clicking on the element and chain with sending keys

element = driver.find_element_by_tag_name("canvas")
actions.click(element).key_down(Keys.ARROW_LEFT).perform()

This worked for me

Programatically send keyboard input to graphical application (game) in Windows

It appears that the problem is that while text input generally pulls input from a buffer, realtime games will miss keypresses that come and go as fast as a virtual keyboard can press them. The solution is simply adding a short call to Sleep() between the keypress and the keyup.

Additionally, for anybody working in Python who like me tried the often-suggested SendKeys.py with no success, look for the 'playkeys' function in the code and add time.sleep(pause) after key_down(vk) , this should resolve the problem (it worked for me).

SendKeys using pywin32 to a PC Game

Most Windows games use the DirectX API for reading keystrokes, they simply ignore that kind of key-pressing messages. They interact directly with the hardware. So your code won't work in the 99% of the Windows games out there.

I would achieve this by writing my own driver and send keystrokes like if they are being pressed manually. It's complex, but not impossible.

Also, I think there's a better way to achieve whatever you want to do. In most cases sending keystrokes it's not a clean solution (specially if you are trying to cheat).

Hope it helps.

How to "send keys" to a canvas element for longer duration?

Unfortunately I cannot see a reproducible behaviour for jumps in that game. When i press UP o SPACE, I randomly see short or long jumps, so I cannot be really sure if my approach will work for you.

However, I think that, with a small effort, you could create a suitable event that will fit you needs.
Basically, since Selenium can execute arbitrary javascript, my approach here is to send a keydown event to the canvas element (tested with Firefox 77).

A screenshot is made for each iteration to ensure the dino actually jumps.

Have fun.

from selenium.webdriver.firefox.options import Options as FirefoxOptions
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time

options = FirefoxOptions()
options.add_argument("--headless")
driver = webdriver.Firefox(options=options)
driver.get('https://chromedino.com/')

canvas = driver.find_element_by_css_selector('.runner-canvas')
main_body = driver.find_element_by_xpath("//html")

try:
canvas.click()
except:
main_body.send_keys(Keys.SPACE)

while True:
driver.execute_script('''
var keydownEvt = new KeyboardEvent('keydown', {
altKey:false,
altKey: false,
bubbles: true,
cancelBubble: false,
cancelable: true,
charCode: 0,
code: "Space",
composed: true,
ctrlKey: false,
currentTarget: null,
defaultPrevented: true,
detail: 0,
eventPhase: 0,
isComposing: false,
isTrusted: true,
key: " ",
keyCode: 32,
location: 0,
metaKey: false,
repeat: false,
returnValue: false,
shiftKey: false,
type: "keydown",
which: 32,
});
arguments[0].dispatchEvent(keydownEvt);
''', canvas)
driver.get_screenshot_as_file('proof_%s.png' % int(time.time()))
time.sleep(0.2)

driver.quit()


Related Topics



Leave a reply



Submit