How can I detect keypresses even when window is running on background? - python

I made this little autofarm bot for GT since I was bored, but problem is, that I don't have any way of stopping it other than Task Manager. So I was thinking, is there a way for my program to detect if any key is pressed down no matter what window is on foreground?
Here is the code I am using right now:
import pyautogui
import sys
from pynput.mouse import Controller
from sys import exit
from time import sleep
from msvcrt import getch
mouse = Controller()
move = int()
move = 0
collections = int()
collections = 0
input("Hover your mouse over FIRST BLOCK and press ENTER.")
b1 = mouse.position
input("Hover your mouse over SECOND BLOCK and press ENTER.")
b2 = mouse.position
input("Hover your mouse over PUNCH and press ENTER.")
p = mouse.position
input("Hover your mouse over COLLECT moving direction and press ENTER.")
c1 = mouse.position
input("Hover your mouse over RETURN moving direction and press ENTER.")
c2 = mouse.position
pt = float(input("Insert punch TIME (ftank 1.0; pepper 1.2; pball 2.6)"))
try:
while True:
pyautogui.click(b1)#Block 1
pyautogui.dragTo(b2, duration = 0.25)#Block 2
pyautogui.mouseDown(p)#Punch
print("Punch Start.")
sleep(pt)
pyautogui.mouseUp()#Stop Punch
move = move + 1 #Count loops
print("Loop ", move, " Complete.")
if move >= 150: #Gem Collection
print("Collecting...")
pyautogui.mouseDown(c1) #Collect Gems
sleep(0.137)
print("Finished.")
pyautogui.mouseDown(c2) #Return to original position
sleep(0.8)
pyautogui.mouseUp()#Stop Moving
move = 0 #Reset Counter
collections = collections + 1
print("Finished ", collections,". Collecting Loop.")
except KeyboardInterrupt:
sys.exit()

Related

How to control the perspective of a unity game using python?

I want to simulate mouse movement through Python, so that the perspective of the Unity game rotates accordingly.
I used pydirectinput.moveTo() to move mouse. Used pydirectinput.keyDown() and pydirectinput.keyUp() to input key.
It can work in 《Borderlands 2》. I can move forward and backward and turn the camera.
But it can't work in 《Aim Hero》, which is a unity game. I can also move forward and backward. The characters in the game move with my control. But the character's perspective doesn't move and shoot.
I execute the command to move the mouse, and the mouse actually does move. However, the mouse will move out of the game's window, and the in-game perspective does not move with it.
Initial suspicion is the difference between Unity games and DirectX games.
This is my code:
import pydirectinput
import pyautogui
import time
def func1():
# ------------this can work in borderlands 2 and Aim Hero(unity)
time.sleep(4)
pydirectinput.keyDown('w')
time.sleep(1)
pydirectinput.keyUp('w')
time.sleep(1)
pydirectinput.keyDown('d')
time.sleep(0.5)
pydirectinput.keyUp('d')
time.sleep(1)
# ------------
# ------------this all can't work in Aim Hero(unity)
pos = pyautogui.position()
pydirectinput.moveTo(pos.x + 100, pos.y) # can't work in borderlands 2
# pos = pyautogui.position()
pydirectinput.moveTo(pos.x + 200, pos.y) # can work in borderlands 2
time.sleep(0.5)
pydirectinput.click()
# -------------
def func2():
time.sleep(4)
# in borderlands 2:
# If the command to move the mouse is executed once, the in-game camera does not move.
# If the command to move the mouse is executed n times, the in-game camera will move n-1 times
# in Aim Hero(Unity Game):
# The mouse keeps moving and eventually moves out of the game window.
# But the in-game perspective has never changed.
for i in range(2):
pos = pyautogui.position()
pydirectinput.moveTo(pos.x + 10, pos.y)
# pydirectinput.click()
print(pos, '\n')
time.sleep(0.1)
if __name__ == '__main__':
print("Start!\n")
func1()
# func2()
print("Done.")
Can you try
# ------------this all can't work in Aim Hero(unity)
pos = pyautogui.position()
pydirectinput.moveTo(900, 600) # estimated center position of screen
time.sleep(1.5) #'cause this code working slow
pydirectinput.click()
pydirectinput.click()
pydirectinput.click()
# -------------
instead of
# ------------this all can't work in Aim Hero(unity)
pos = pyautogui.position()
pydirectinput.moveTo(pos.x + 100, pos.y) # can't work in borderlands 2
# pos = pyautogui.position()
pydirectinput.moveTo(pos.x + 200, pos.y) # can work in borderlands 2
time.sleep(0.5)
pydirectinput.click()
# -------------
EDIT
Okay I found the problem! It's not about Python, it's about Unity. Let me show you a video from my computer.
As far as I understand, if you want to use the pydirectinput.moveTo() method in Unity game, you should not lock your cursor. Be careful about your cursor state and use CursorLockMode.None instead of CursorLockMode.Locked. But it wont be effective for real game :( And I don't know any alternative for now

I am making a macro that needs to move a windowed program

I am using pynput and so far i haven't figured it out i have tried arrow keys and teleporting the mouse relative to its position and to specified coordinates
from pynput.keyboard import Key, Controller as KeyboardController
from pynput.mouse import Button, Controller as MouseController
import time
keyboard = KeyboardController()
mouse = MouseController()
mouse.position = (-1756, 1079)
time.sleep(0.5)
mouse.click(Button.left, 1)
time.sleep(1.5)
mouse.position = (904, 181)
mouse.press(Button.left)
for number in range (80):
keyboard.press(Key.left)
keyboard.release(Key.left)
mouse.release(Button.left)
print("done")

Jump and Move sideways

I can't figure out how to move sideways and jump at the same time, only one or the other.
I have tried asyncio and multithreading/multiprocessing and couldn't get it to work. I am all out of ideas and can't find anymore online. I also have another issue where I can jump and if I reach the apex of the jump and hold a or d I can move side to side floating.
class Player():
def __init__(self,health,boosts,height,width):
self.health = health
self.booosts = boosts
self.height = height
self.width = width
def jump():
global gravtest, press
press.remove("'w'")
gravtest = False
y = player[0].ycor()
for i in range (1, 10):
player[0].sety(y+(i*5))
time.sleep(0.05)
#while player[0]
gravtest = True
# def powers(self, boosts):
import turtle as t
import time, random
from pynput.keyboard import Key, Listener
t.ht()
press = []
gravtest = True
wn = t.Screen()
wn.title("Jump Man")
wn.bgcolor("white")
wn.screensize(250, 250)
wn.setup(width=1.0, height=1.0)
player = [t.Turtle(), Player(100, [], 25, 25)]
player[0].speed(0)
player[0].shapesize(0.5)
player[0].shape("square")
player[0].color("black")
player[0].up()
player[0].goto(0, 0)
floor = t.Turtle()
floor.speed(0)
floor.shape("square")
floor.shapesize(100)
floor.color("black")
floor.up()
floor.goto(0, -1150)
def gravity():
global gravtest
if gravtest == True:
grav = 0
while player[0].distance(floor) > 1007:
y = player[0].ycor()
player[0].sety(y + grav)
if grav > -5:
grav -= 1
player[0].sety(y + grav)
gravtest = False
if player[0].distance(floor) < 1045:
player[0].sety(-145)
def show(key):
global press
if not(format(key) in press):
press.append(format(key))
print(key)
def rem(key):
global press
if format(key) in press:
press.remove(format(key))
def move():
global press
while "'a'" in press:
player[0].setx(player[0].xcor()-2)
while "'d'" in press:
player[0].setx(player[0].xcor()+2)
if press == '\'s\'':
print()
gravity()
if "'w'" in press:
jump()
with Listener(on_press = show, on_release = rem) as listener:
while 1:
move()
Your problem with moving and jumping is that you have separate loops for each that try to handle one kind of movement of the movement in one place. That won't work properly if other stuff (like jumping while moving, or moving while falling under gravity) are supposed to be possible.
Instead, you need to have just one main loop. On each run of that loop, you should do one frame worth of movement of whatever kinds is appropriate (e.g. moving horizontally, falling or jumping). This may require some bookkeeping to keep track of how long the vertical acceleration from a jump lasts.
I'd make the main loop something like this:
on_the_ground = True
jumping = False
while True:
horizontal_movement() # this is always possible if the buttons are pressed
if on_the_ground or jumping:
jump() # can start or continue a jump if a button is pressed
else:
gravity() # fall, if you're not grounded or accelerating in a jump
handle_collisions_etc()
time.sleep(1/FRAMERATE)
Note, I've made some assumptions about the game logic you want. If you don't want to be able to move horizontally while in the air (as you can in many platformer games), you'll need to change this a little bit.
The jump function will need to keep track of how long you've been jumping for, since you probably want the player to be limited in how high they can go. I'm not exactly sure I understand the logic of your current code, so I'll leave it up to you to figure out exactly what to track.
A final suggestion is to move some of the global variables into the Player class. Even the turtle object you're using to draw things could be stored as an attribute on the instance you create.

Monitoring mouse coordinate while a key is pressed

I am trying to make a windows analog of the Chat-wheel from Dota 2 or Battlefield with some fast commands like this.
How it should be:
While the G-key is pressed - the wheel with some sections appears at the centre of the screen, with the mouse centered on it and if I move the mouse to side_1 and then release the G-key -> func_1 executes.
If it was on side_2 -> func_2.
If I release the G-key at the centre -> wheel disappears and nothing happens.
So to monitor the X Y coordinates of the mouse I use following code:
from pynput import mouse
def on_move(x, y):
print(x, y)
# Collect events until released
with mouse.Listener(on_move=on_move) as listener:
listener.join()
It is spamming coordinates when I move the mouse.
But I am stuck in the part where i need:
to start the listener from another .py file and take these coordinates for the visual part of the program (like highlight the side of the wheel with command descriptions),
to close the listener from another .py file and take the last coordinates of the mouse when the G-key is released to compare with tge range of coordinates prescribed for functions.
You want something like this:
from pynput import mouse, keyboard
import time
def on_press(key):
print("pressed {}".format(key))
def on_release(key):
print("released {}".format(key))
def on_move(x,y):
print((x,y))
mouse_listener = mouse.Listener(
on_move=on_move)
mouse_listener.start()
key_listener = keyboard.Listener(
on_press=on_press,
on_release=on_release)
key_listener.start()
# prevent the script from exiting immediately
time.sleep(10)
import time
import keyboard
from pynput.mouse import Controller
def get_xy():
mouse = Controller()
mouse_coord = str(mouse.position)
mouse_coord = mouse_coord.replace("(", "")
mouse_coord = mouse_coord.replace(")", "")
mouse_coord = mouse_coord.replace(",", "")
mouse_coord = mouse_coord.split(" ")
mouse_x = int(mouse_coord[0])
mouse_y = int(mouse_coord[1])
print(mouse_x, mouse_y)
while True:
if keyboard.is_pressed('b'):
get_xy()
time.sleep(0.01)
Output example: 654 326

Does turtle have an onkeyhold method

In a program I am writing, turtle's onkey() method doesn't do exactly what I need. I know there are also onkeypress and onkeyrelease but neither do what I need. Is there a method for continuously running a function while a key is held? Such as
import turtle
num = 0
def add():
global num
num += 1
print(num)
turtle.onkey(add, "Up")
turtle.listen()
turtle.mainloop()
If you did something like this, for taking the keyboard input, onkey only responds once, and it only responds on the release of the key. Is there a method that would continuously run the function while it is being held down?
Below's a rough example that does what you describe using onkeypress() and onkeyrelease() in combination. Once you press 'Up' it will start counting whole seconds until you release that key. Then it will write to the screen the number of whole seconds the key was held:
from turtle import Turtle, Screen
FONT = ('Arial', 36, 'normal')
def add_start():
global seconds
print('pressed')
if seconds < 0:
turtle.undo() # remove previous time
seconds = 0
screen.ontimer(add, 1000)
def add():
global seconds
if seconds >= 0:
seconds += 1
screen.ontimer(add, 1000)
def add_stop():
global seconds
print('released')
turtle.write(seconds, align='center', font=FONT)
seconds = -1
screen = Screen()
turtle = Turtle(visible=False)
turtle.write(0, align='center', font=FONT)
seconds = -1
screen.onkeypress(add_start, 'Up')
screen.onkeyrelease(add_stop, 'Up')
screen.listen()
screen.mainloop()
Here's the catch: you need to turn off key repeat at the operating system level on your system. For example, On my Mac, in System Preferences / Keyboard, I'd do:
Otherwise the system will generate press and release events as part of standard key repeat.

Categories

Resources