File "<ipython-input-6-b985bbbd8c62>", line 21
cv2.rectangle(img,(ix,iy),(x,y),(255,0,0),-1)
^
IndentationError: expected an indented block
my code
import cv2
import numpy as np
#variables
#True while mouse button down, False while mouse button up
drawing = False
ix,iy = -1
#Function
def draw_rectangle(event,x,y,param,flags):
global ix,iy,drawing
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
cv2.rectangle(img,(ix,iy),(x,y),(255,0,0),-1)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
cv2.rectangle(img,(ix,iy),(x,y),(255,0,0),-1)
#Showing images with opencv
#black
img = np.zeros((612,612,3))
cv2.namedwindow(winname='draw_painting')
cv2.setMouseCallback('draw_painting',draw_rectangle)
while True:
cv2.imshow('draw_painting',img)
cv2.waitkey(20) & 0xFF = 27:
break
cv2.destryAllWindows()
You need to give indentation for the line after the if statement
if drawing == True:
cv2.rectangle(img,(ix,iy),(x,y),(255,0,0),-1)
This is your current code:
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
cv2.rectangle(img,(ix,iy),(x,y),(255,0,0),-1)
Note that, after the if statement, you need to indent your code:
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
cv2.rectangle(img,(ix,iy),(x,y),(255,0,0),-1)
Other errors:
Also, it seems that you intend your final if statement to be inside an if block and remember to use == rather than = to check for equality.
Related
I have an endless loop in MAIN and ive looked at it so many times.
def click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,0,0)
time.sleep(0.05)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,0,0)
def click_x_box(Box_x_axis, X_axis, Y_Axis_top, Y_Axis_bottom):
#[Check if pixel is RED from top]
while pyautogui.pixel(X_axis, Y_Axis_top)[0] == 255 and pyautogui.pixel(X_axis, Y_Axis_top)[1] != 255:
# click function has no loops
click(Box_x_axis, Y_Axis_top)
Y_Axis_top += 19
print("finished top-down loop")
#[Check if pixel is RED from bottom]
while pyautogui.pixel(X_axis, Y_Axis_bottom)[0] == 255 and pyautogui.pixel(X_axis, Y_Axis_bottom)[1] != 255:
click(Box_x_axis, Y_Axis_bottom)
Y_Axis_bottom -= 19
print("finished bottom-up loop")
After I press 'q' once the "keyboard.is_pressed" line will keep re-going through, I dont know why it keeps getting through if 'q' is not being held down?
def main():
# Continue unticking boxes while 'q' is held
print("Hold 'q' to start clearing out the page of red")
while True:
if keyboard.is_pressed("q") == True:
print("q is pressed")
click_x_box(Box_x_axis, X_axis, Y_Axis_top, Y_Axis_bottom)
if __name__ == "__main__":
main()
EDIT
Ive figured out that when for whatever reason the click function is still engaging despite there being no 255,0,0 (red) on screen...
so i'm using opencv and i want to make a sort of selection tool but the problem is can't make the rectangle transparent. here's the code:
import numpy as np
import cv2 as cv
drawing = False
def draw_rec(event,x,y,flags,param):
global ix,iy,drawing
if event == cv.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv.EVENT_LBUTTONUP:
drawing = False
cv.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)
elif event == cv.EVENT_MOUSEMOVE:
if drawing == True:
cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 5)
img = cv.imread('baboon.jpg', -1)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_rec)
while(1):
cv.imshow('image',img)
k = cv.waitKey(1) & 0xFF
if k == 27:
break
cv.destroyAllWindows()
The first mistake in the code is:
elif event == cv.EVENT_LBUTTONUP:
drawing = False
cv.rectangle(img,(ix,iy),(x,y),(0,0,0),-1)
The -1 parameter means to fill the rectangle. source If we change -1 to 1:
From my point of view, the result is not satisfactory. The multiple rectangle display is caused by the mouse_movement.
elif event == cv.EVENT_MOUSEMOVE:
if drawing == True:
cv.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 5)
Each time the mouse moves, the rectangle will be drawn. I think it is better if we draw when the mouse movement finishes:
Code:
import numpy as np
import cv2 as cv
drawing = False
def draw_rec(event,x,y,flags,param):
global ix,iy,drawing
if event == cv.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv.EVENT_LBUTTONUP:
drawing = False
cv.rectangle(img,(ix,iy),(x,y),(0,255,0),5)
img = cv.imread('27BR1.jpg', -1)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_rec)
while(1):
cv.imshow('image',img)
k = cv.waitKey(1) & 0xFF
if k == 27:
break
cv.destroyAllWindows()
I'm currently trying to use Python's pyautogui library to move my mouse around the screen. I'm having some issues, whenever I leave the mouse in a static position it doesn't seem to update, but if I nudge my real mouse then it updates its position. I've tried using multiple libraries to no avail. I also haven't been able to find any similar questions about this. Does pyautogui not work properly for games?
from directinput import PressKey, ReleaseKey
from PIL import ImageGrab, ImageOps
from time import sleep as s
from sys import exit
import numpy as np
import pyautogui
readout_box = (965, 970, 1016, 1010)
up = 419748
down = 419735
left = 420259
right = 420092
left_right = 397608
up_down = 399616
space = 448674
click = 385930
def main():
print(get_sum())
if get_sum() == left or get_sum() == 428588:
Press(0x1E)
print("Left")
elif get_sum() == right or get_sum() == 425290:
Press(0x20)
print("Right")
elif get_sum() == down or get_sum() == 431363:
Press(0x1F)
print("Down")
elif get_sum() == up:
Press(0xC8)
print("Up")
elif get_sum() == space:
keySpam(0x39)
print("Spamming Space")
elif get_sum() == click:
clickSpam()
print("Spamming Click")
elif get_sum() == left_right:
leftRight()
print("Left Right")
elif get_sum() == up_down:
upDown()
print("Up Down")
elif get_sum() == 345939:
print("Day Complete!")
exit()
def get_sum():
img = ImageGrab.grab(readout_box)
gray = ImageOps.grayscale(img)
sum = np.array(gray).sum()
return sum
def Press(keyCode):
PressKey(keyCode)
s(0.1)
ReleaseKey(keyCode)
def keySpam(keyCode):
for i in range(15):
Press(keyCode)
def clickSpam():
for i in range(10):
pyautogui.leftClick()
def leftRight():
pyautogui.moveTo(1600, 515)
for i in range(3):
pyautogui.moveTo(350, 560, 1)
pyautogui.moveTo(1600, 515, 1)
def upDown():
pyautogui.moveTo(900, 160)
for i in range(3):
pyautogui.moveTo(900, 900, 1)
pyautogui.moveTo(900, 160, 1)
s(1)
while True:
main()
s(0.5)
I am developing a small game for learning purposes. I have created a simple animation for the title screen. Since there is also a function for full screen in the code, I wanted to create a title screen that:
Displayed the animation
Turned into full screen when the key was activated
Continued the animation at the point it was before activating full screen
In order to do this, I resorted to threading. However, this is the first time I tried to do any multi-threading, and I donĀ“t know what did I do wrong. The result is an undetermined error.
The code for the title screen is this:
try:
GameAnimation = threading.Thread(target=GameTitleAnimation, (Window, WindowDimensions, FontDictionary, CurrentVersion))
GameAnimation.start()
except:
print "There was an error while loading the screen. Press one key to exit the program."
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Quit()
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
Quit()
elif event.key == K_f:
Fullscreen(Window, WindowDimensions)
else:
return
The code for the animation is:
TitleWhite = [255, 255, 255, 0]
Black = BASE_BLACK
TitleLetters = ("R", "O", "G", "U", "E", " ", "H", "U", "N", "T", "E", "R")
Title = FontDictionary["TitleFont"][1].render("ROGUE HUNTER", False, TitleWhite)
TextWidth = Title.get_width()
TextHeight = Title.get_height()
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
TitleYPosition = (WindowDimensions[1] / 2) - (TextHeight / 2)
for letter in TitleLetters:
if letter == " ":
TitleXPosition += CurrentLetterWidth
else:
while TitleWhite[3] < 100:
TitleWhite[3] += 1
CurrentLetter = FontDictionary["TitleFont"][1].render(letter, False, TitleWhite)
CurrentLetter.set_alpha(TitleWhite[3])
Window.blit(CurrentLetter, (TitleXPosition, TitleYPosition))
time.sleep(0.008)
try:
pygame.display.update()
except Exception:
traceback.print_exception
TitleWhite[3] = 0
CurrentLetterWidth = CurrentLetter.get_width()
TitleXPosition += CurrentLetterWidth
FadeInSurface = pygame.Surface((WindowDimensions[0], WindowDimensions[1]))
FadeInSurface.fill(TitleWhite)
OpacityRounds = 1
while TitleWhite[3] < 100.0:
TitleWhite[3] = 1.1 ** OpacityRounds
FadeInSurface.set_alpha(TitleWhite[3])
Window.blit(FadeInSurface, (0, 0))
OpacityRounds += 1
pygame.display.update()
time.sleep (0.015)
time.sleep(0.7)
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
Version = FontDictionary["BodyFont"][1].render(CURRENT_VERSION, False, TitleWhite)
VersionHeight = Version.get_height()
VersionWidth = Version.get_width()
VersionXPosition = (WindowDimensions[0] - VersionWidth) / 2
VersionYPosition = TitleYPosition + TextHeight
while True:
pygame.draw.rect(Window, Black, (0, 0, WindowDimensions[0], WindowDimensions[1]), 0)
Window.blit(Title, (TitleXPosition, TitleYPosition))
Window.blit(Version, (VersionXPosition, VersionYPosition))
pygame.display.update()
I'd be very grateful if anyone could help me with this. I am going crazy.
There's no reason to use threading in your code. It will only make your code harder to read, harder to debug and error prone.
Usually you want to have some kind of state in your game that you use to determinate what should happen in a frame. You can find a class based example here.
Another way to handle this, which is a bit similar to your code, is to use coroutines.
Look at your animation code and instead of calling pygame.display.update(), give the control back to the main loop. The main loop will handle events, frame limiting and drawing, then give control back to the coroutine (which keeps track of it's own state).
Here's a simple hacky example:
import pygame
import pygame.freetype
pygame.init()
size = (640, 480)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
def game_state(surf):
rect = pygame.Rect(200, 200, 32, 32)
while True:
events = yield
pressed = pygame.key.get_pressed()
x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0
rect.move_ip(x*5, 0)
pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)
yield
def title_state(surf):
text = 'Awesome Game'
colors = [[255, 255, 255, 20] for letter in text]
font = pygame.freetype.SysFont(None, 22)
font.origin = True
while True:
for color in colors:
color[3] += 33
if color[3] > 255: color[3] = 0
x = 200
for (letter, c) in zip(text, colors):
bounds = font.get_rect(letter)
font.render_to(surf, (x, 100), letter, c)
x += bounds.width + 1
font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))
events = yield
yield
def main():
title = title_state(screen)
game = game_state(screen)
state = title
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_ESCAPE:
return
if e.key == pygame.K_SPACE:
state = game if state == title else title
if e.key == pygame.K_f:
if screen.get_flags() & pygame.FULLSCREEN:
pygame.display.set_mode(size)
else:
pygame.display.set_mode(size, pygame.FULLSCREEN)
screen.fill(pygame.Color('grey12'))
next(state)
state.send(events)
pygame.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
See how the main loop is clean and simple, and all of the game state is handled in the coroutines. The title screen part of the code does not care about fullscreen or not or how to switch to fullscreen, and the main loop does not care of what the title screen coroutine does. And we don't need threading.
In practice it's not that different from the class based example I linked above, but using coroutines makes it easy to implement the title screen animation.
Basically you have an endless loop, you mutate some state (like the color of a letter), and then say "now draw this!" by just calling yield.
This is a large chunk of code to debug.
I'm not familiar with pygame or python threading, but it seems to me that you need to include some debug lines to determine exactly where the error occurs during your game animation thread (if it's even occuring there at all).
Something like this pattern should help determine the source of the problem:
import logging
logging.info("start animation initialization")
...
logging.info("begin animation loop")
...
logging.info("end animation loop")
https://docs.python.org/2/howto/logging.html
I need to kb input onto a pygame screen
at the moment it appears on the idle shell
any advice would be appreciated.
This code is extracted from a larger program
mostly screen based but i need to input some
data (numeric) from the kb at times
import sys
import pygame
from pygame.locals import *
pygame.init()
N= ''
screen = pygame.display.set_mode((600,600))
font= pygame.font.Font(None,40)
screen.fill((255,255,255))
pygame.display.flip
pygame.display.update()
def score(C,y):
SetWnd = font.render( C,True,(0,0,255))
screen.blit(SetWnd, (15, 100+y))
pygame.display.update()
def start():
while True:
name=''
for evt in pygame.event.get():
if evt.type == KEYDOWN:
if evt.unicode.isalnum(): # unicode
name+=evt.unicode
print name,
elif evt.key == K_BACKSPACE:
name = name[:-1]
print name,
elif evt.key == K_RETURN:
return N
elif evt.type == QUIT:
pygame.quit()
sys.exit()
def Pchange(c,y):
block = font.render(N, True, (0,0,0))
rect = block.get_rect()
rect.move_ip(75,100 + y)
screen.blit(block,rect)
pygame.display.flip()
score('wind', 0)
score('elev',20)
N = start()
Pchange(N,0)
Pchange(N,20)
Firstly you draw the score twice, which i assume works well.
The problem lies in you start function.
You are not calling any draw or update function in your while loop.
In your event foreach, you add a digit to name, and exit the while loop when enter is pressed. Then you draw twice with Pchange, but you are the function does not use the right parameters. You have:
def Pchange(c,y):
block = font.render(N, True, (0,0,0))
you are using the global N which is ''. So to fix that, you need to change N to c.
The next problem is that the game quits right after pressing enter. Since you pasted only a part of the program, this might not be the case. If it is, make another while loop, and just wait for the ESC key to call pygame.quit() and sys.exit()