Click on every circle on screen with python - python

So i'm trying to create a python script that takes a screenshot a few time in a second and locates the orange circles then clicks on them. I'm using for the website https://mouseaccuracy.com to automatically click on every circle very fast. Here is the code i have so far:
import pyautogui
from time import *
color = (235, 133, 0)
while True:
s = pyautogui.screenshot("screenshottest.png",region=(0,160, 1366, 768))
for x in range(s.width):
for y in range(s.height):
if s.getpixel((x, y)) == color:
pyautogui.click(x, y+160)
The problem with this is that it clicks on literally every pixel when i only want to click on every circle instead of every pixel of the circle.
Here is what the circles that it needs to click on look like:
So how do i make it click on every orange circle instead of every orange pixel? thank you in advance

Related

I'm trying to make a bot with pyautogui that shoots targets based on their pixel color but the cursor gets stuck once the bot finds that pixel

I'm attempting to scan through screenshots and find a specific pixel color location where the bot must move the cursor to and then click it, however, it seems like as soon as the bot finds the pixel the cursor gets stuck in a loop where it keeps moving a very short distance up and down. The site I'm using for this bot is aimtrainer.io.
import pyautogui
import keyboard
import win32api, win32con
import time
# defining a function that moves the mouse to a specific 'x, y' position and then performs a click
def win_click(x_axis, y_axis):
win32api.SetCursorPos((x_axis, y_axis))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)
time.sleep(0.2)
target_rgb = (255, 87, 34) # this is the color that the bot will look for
x_fourth = 1366 / 4
y_fourth = 768 / 4
scr_shot_size = ((x_fourth, 3 * x_fourth), (y_fourth, 3 * y_fourth)) # this is cutting the screen such that it's 1/4 of
# distance from the border on all its sides
last_pixel = None # this is just a placeholder
while not keyboard.is_pressed('q'):
scr_shot = pyautogui.screenshot()
# these 2 for loops will scan the cut screen with a pace of 5 pixels
# such that for each 'x', it will look for its 'y's
for x in range(int(scr_shot_size[0][0]), int(scr_shot_size[0][1]), 5):
for y in range(int(scr_shot_size[1][0]), int(scr_shot_size[1][1]), 5):
curr_pixel_rgb = scr_shot.getpixel((x, y)) # gets the pixel in the current 'x, y' coordinate
if curr_pixel_rgb == target_rgb:
# the below if statements tries to prevent the bot from clicking twice on the same position
if (x, y) != last_pixel:
win_click(x, y)
else:
time.sleep(0.1)
last_pixel = (x, y) # stores the value of the current pixel that will later be compared with the value
# of the current pixel
First I would recommend, you add a Keypress check inside the nested loop, so you don't need to wait for the whole loop to terminate before you can exit.
The problem with the stuck moving cursor is that you jump each 5 pixels.
Let's imagine you have a Rectangle of the size 150x300px with its top left corner positioned at (100,100) and with the correct color.
As you can see, your cursor would repeatedly jump column by column inside of the rectangle.
(I'm sorry for this awful drawing)
You can try to fix this by checking the whole color area and place the cursor centered inside of it once.
Let me know, if you need help with that!

Check color value of pixel on screen

I'm making a bot that automatically clicks if the mouse is not over a specific color. I have everything from positioning to clicking, but I do not know how I can check if the pixel the mouse is over is a specific color. I currently use mouse and keyboard, and google hasn't given me the results fitting for my situation.
It is also not an image, but live on the screen.
It should look something like this:
colorUnderMouse = getColorUnderMouse()
if colorUnderMouse == "FF00FF":
mouse.click('left')
else:
mouse.move(10, 0, absolute=False, duration=0)
You can use pyautogui:
import pyautogui
def getColorUnderMouse():
x, y= pyautogui.position()
pixel = pyautogui.screenshot(
region=(
x, y, 1, 1
)
)
return pixel.getcolors()

Windows: Draw rectangle on camera preview

Similar questions have been asked a lot for Android, but so far I haven´t been able to find resources related to Windows OS. So basically, as the topic suggests, I would like to draw a rectangle on my camera preview. Some work has been done, but there´s still some problem in my program. Due to some limits, I would like to avoid using opencv as much as possible. Following is my approach:
Open Window´s built-in camera app
Run Python code that draws rectangle on screen, pixel by pixel (see below)
Click on screen with mouse to move rectangle with its upper-left corner
As you can see in the code, I´m not actually drawing on the camera preview but rather drawing on my screen, where the camer preview runs on one layer lower.
Here´s the python code:
import win32gui, win32ui, win32api, win32con
from win32api import GetSystemMetrics
dc = win32gui.GetDC(0)
dcObj = win32ui.CreateDCFromHandle(dc)
hwnd = win32gui.WindowFromPoint((0,0))
monitor = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1))
red = win32api.RGB(255, 0, 0) # Red
past_coordinates = monitor
rec_x = 200 # width of rectangle
rec_y = 100 # height of rectangle
m = (100, 100) # initialize start coordinate
def is_mouse_down():
key_code = win32con.VK_LBUTTON
state = win32api.GetAsyncKeyState(key_code)
return state != 0
while True:
if(is_mouse_down() == True):
m = win32gui.GetCursorPos()
for x in range(rec_x):
win32gui.SetPixel(dc, m[0]+x, m[1], red)
win32gui.SetPixel(dc, m[0]+x, m[1]+rec_y, red)
for y in range(rec_y):
win32gui.SetPixel(dc, m[0], m[1]+y, red)
win32gui.SetPixel(dc, m[0]+rec_x, m[1]+y, red)
As a result, I´m able to draw a red rectangle. However, because the screen is constantly being refreshed, the two horizontal lines of my rectangle (see gif below) are shown as running dots that go from left to right. I can´t find or think of a way to improve this, whilst keeping the possibility to move the rectangle around per ckick.
PS. Ignore white rectangle. It´s a built-in thing of the camera app when you click anywhere on the preview.
Here are the references I used to get to this step:
How to draw an empty rectangle on screen with Python
https://python-forum.io/Thread-How-to-trigger-a-function-by-clicking-the-left-mouse-click

8 Queens (pyglet-python)

I'm trying to make 8 queens game on pyglet. I have succesfully generated board.png on window. Now when I paste queen.png image on it, I want it to show only queen on it not the white part. I removed white part using photoshop, but as I call it on board.png in pyglet it again shows that white part please help.
import pyglet
from pyglet.window import Window, mouse, gl
# Display an image in the application window
image = pyglet.image.Texture.create(800,800)
board = pyglet.image.load('resources/Board.png')
queen = pyglet.image.load('resources/QUEEN.png')
image.blit_into(board,0,0,0)
image.blit_into(queen,128,0,0)
# creating a window
width = board.width
height = board.height
mygame = Window(width, height,
resizable=False,
caption="8 Queens",
config=pyglet.gl.Config(double_buffer=True),
vsync=False)
# Making list of tiles
print("Height: ", board.height, "\nWidth: ", board.width)
#mygame.event
def on_draw():
mygame.clear()
image.blit(0, 0)
def updated(dt):
on_draw()
pyglet.clock.schedule_interval(updated, 1 / 60)
# Launch the application
pyglet.app.run()
These are the images:
queen.png
board.png
Your image is a rectangle. So necessarily, you will have a white space around your queen whatever you do.
I would recommend a bit of hacking (it's not very beautiful) and create two queen versions: queen_yellow and queen_black. Whenever the queen is standing on a yellow tile, display queen_yellow, and otherwise display queen_black.
To find out whether a tile is a yellow tile (using a matrix with x and y coordinates, where the top value for y is 0 and the very left value for x is 0):
if tile_y%2=0: #is it an even row?
if tile_x%2=0: #is it an even column?
queentype = queen_yellow
else:
queentype = queen_black
else: #is it an uneven row?
if tile_x%2!=0: #is it an uneven column?
queentype = queen_yellow
else: queentype = queen_black
Hope that helped,
Narusan
First of all, please verify that there is no background (you can use GIMP for that). Once that is done go ahead with this:
Since it is a PNG image, you can't just put it there on the window as it will lose its transparency. You need to import the PNGImageDecoder from pyglet like
from pyglet.image.codecs.png import PNGImageDecoder
then use it for loading the PNG image like
kitten = pyglet.image.load('kitten.png', decoder=PNGImageDecoder())
and finally draw it on the window by using
kitten.draw(), after specifying the x and y coordinates where you would like to have them.
The document for the above can be found here.
Hope this helps!

How can I make my circles fly off the screen in pygame?

I am a begginner at python and I'm trying to make a circle game. So far it draws a circle at your mouse with a random color and radius when you click.
Next, I would like the circle to fly off the screen in a random direction. How would I go about doing this? This is the main chunk of my code so far:
check1 = None
check2 = None
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit
if event.type == MOUSEBUTTONDOWN:
last_mouse_pos = pygame.mouse.get_pos()
if last_mouse_pos:
global check
color1 = random.randint(0,255)
color2 = random.randint(0,255)
color3 = random.randint(0,255)
color = (color1,color2,color3)
radius = random.randint (5,40)
posx,posy = last_mouse_pos
if posx != check1 and posy != check2:
global check1, check2
screen.lock()
pygame.draw.circle(screen, color, (posx,posy), radius)
screen.unlock()
check1,check2 = posx,posy
pygame.display.update()
Again, I want the circle to fly off the screen in a random direction.
I have made a few attempts but no successes yet.
Also, thanks to jdi who helped me s
When you create the circle (on click), generate 2 random numbers. These will be your (x,y) components for a two dimensional Euclidean velocity vector:
# interval -1.0 to 1.0, adjust as necessary
vx, vy = ( (random.random()*2) -1, (random.random()*2) - 1 )
Then after the ball has been created, on each iteration of the game loop, increment your ball's position by the velocity vector:
posx, posy = posx + vx, posy + vy
Note that the overall speed might be variable. If you want to always have a speed of 1.0 per seconds, normalize the vector:
To normalize the vector, you divide it by its magnitude:
So in your case:
And hence:
So in Python, after importing math with import math:
mag = math.sqrt(vx*vx + vy*vy)
v_norm = vx/mag, vy/mag
# use v_norm instead of your (vx, vy) tuple
Then you can multiply this with some speed variable, to get reliable velocity.
Once you progress to having multiple objects moving around and potentially off screen, it is useful to remove the offscreen objects which have no chance of coming back, and have nothing to do with your program anymore. Otherwise, if you keep tracking all those offscreen objects while creating more, you get essentially a memory leak, and will run out of memory given enough time/actions.
While what you are doing right now is quite simple, assuming you haven't already, learning some basic vector math will pay itself off very soon. Eventually you may need to foray into some matrix math to do certain transformations. If you are new to it, its not as hard as it first looks. You can probably get away with not studying it, but you will save yourself effort later if you start attempting to do more ambitious things.
Right now, you are doing the following (drastically simplifying your code)...
while True:
if the mouse was clicked:
draw a circle on the screen where the mouse was clicked
Let's make things a little easier, and build up gradually.
Start with the circle without the user clicking
To keep things simple, let's make the circle near the top left of the screen, that way we can always assume there will be a circle (making some of the logic easier)
circle_x, circle_y = 10,10
while True:
draw the circle at circle_x, circle_y
pygame.display.update()
Animate the circle
Before going into too much about "random directions", let's just make it easy and go in one direction (let's say, always down and to the right).
circle_x, circle_y = 0,0
while True:
# Update
circle_x += 0.1
circle_y += 0.1
# Draw
draw the circle at circle_x, circle_y
update the display
Now, every time through the loop, the center of the circle moves a bit, and then you draw it in its new position. Note that you might need to reduce the values that you add to circle_x and y (in my code, 0.1) in case the circle moves too fast.
However, you'll notice that your screen is now filling up with circles! Rather than one circle that is "moving", you're just drawing the circle many times! To fix this, we're going to "clear" the screen before each draw...
screen = ....
BLACK = (0,0,0) # Defines the "black" color
circle_x, circle_y = 0,0
while True:
# Update
circle_x += 0.1
circle_y += 0.1
# Draw
screen.fill(BLACK)
draw the circle at circle_x, circle_y
update the display
Notice that we are "clearing" the screen by painting the entire thing black right before we draw our circle.
Now, you can start work the rest of what you want back into your code.
Keep track of multiple circles
You can do this by using a list of circles, rather than two circle variables
circles = [...list of circle positions...]
while True:
# Update
for circle in circles:
... Update the circle position...
# Draw
screen.fill(BLACK)
for circle in circles:
draw the circle at circle position # This will occur once for each circle
update the display
One thing to note is that if you keep track of the circle positions in a tuple, you won't be able to change their values. If you're familiar with Object Oriented Programming, you could create a Circle class, and use that to keep track of the data relating to your circles. Otherwise, you can every loop create a list of updated coordinates for each circle.
Add circle when the user clicks
circles = []
while True:
# event handling
for event in pygame.event.get():
if event.type == MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
circles.append( pos ) # Add a new circle to the list
# Update all the circles
# ....
# Draw
clear the screen
for circle_position in circles:
draw the circle at circle_position # This will occur once for each circle
update the display
Have the circle move in a random direction
This is where a good helping of math comes into play. Basically, you'll need a way to determine what to update the x and y coordinate of the circle by each loop. Keep in mind it's completely possible to just say that you want it to move somewhere between -1 and 1 for each axis (X, y), but that isn't necessarily right. It's possible that you get both X and Y to be zero, in which case the circle won't move at all! The next Circle could be 1 and 1, which will go faster than the other circles.
I'm not sure what your math background is, so you might have a bit of learning to do in order to understand some math behind how to store a "direction" (sometimes referred to as a "vector") in a program. You can try Preet's answer to see if that helps. True understanding is easier with a background in geometry and trigonometry (although you might be able to get by without it if you find a good resource).
Some other thoughts
Some other things you'll want to keep in mind:
Right now, the code that we're playing with "frame rate dependent". That is, the speed in which the circles move across the screen is entirely dependent on how fast the computer can run; a slower computer will see the circles move like snails, while a faster computer will barely see the circles before they fly off the screen! There are ways of fixing this, which you can look up on your own (do a search for "frame rate dependence" or other terms in your favorite search engine).
Right now, you have screen.lock() and screen.unlock(). You don't need these. You only need to lock/unlock the screen's surface if the surface requires it (some surfaces do not) and if you are going to manually access the pixel data. Doing things like drawing circles to the screen, pygame in lock/unlock the surfaces for you automatically. In short, you don't need to deal with lock/unlock right now.

Categories

Resources