How to draw a continuous line in Pygame? - python

I want to draw a line when mouse clicked and moving in Pygame framework, it will be a line if I move the mouse very slowly. However, if I move the mouse quickly, it's just incontinuous dots. The question is how to draw a continuous line when mouse move? Thanks in advance.
import pygame, sys
from pygame.locals import *
def main():
pygame.init()
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
mouse_position = (0, 0)
drawing = False
screen = pygame.display.set_mode((600, 800), 0, 32)
screen.fill(WHITE)
pygame.display.set_caption("ScratchBoard")
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
if (drawing):
mouse_position = pygame.mouse.get_pos()
pygame.draw.line(screen, BLACK, mouse_position, mouse_position, 1)
elif event.type == MOUSEBUTTONUP:
mouse_position = (0, 0)
drawing = False
elif event.type == MOUSEBUTTONDOWN:
drawing = True
pygame.display.update()
if __name__ == "__main__":
main()

By calling pygame.draw.line with the same argument (mouse_position) twice, you're not drawing a line, you're drawing a single pixel, because start_pos and end_pos are the same.
To get a contiguous line, you need to save the last position and draw a line between it and the next position, like this (changes are the lines with last_pos):
import pygame, sys
from pygame.locals import *
def main():
pygame.init()
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
mouse_position = (0, 0)
drawing = False
screen = pygame.display.set_mode((600, 800), 0, 32)
screen.fill(WHITE)
pygame.display.set_caption("ScratchBoard")
last_pos = None
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEMOTION:
if (drawing):
mouse_position = pygame.mouse.get_pos()
if last_pos is not None:
pygame.draw.line(screen, BLACK, last_pos, mouse_position, 1)
last_pos = mouse_position
elif event.type == MOUSEBUTTONUP:
mouse_position = (0, 0)
drawing = False
elif event.type == MOUSEBUTTONDOWN:
drawing = True
pygame.display.update()
if __name__ == "__main__":
main()

vgel is right, you need to pass the previous position and the current position to pygame.draw.line. You can also calculate the previous position by subtracting the event.rel attribute of the event from the event.pos attribute.
It's also possible get rid of the drawing variable by using the event.buttons attribute. If event.buttons[0] is True then the left mouse button is being pressed.
import pygame
def main():
pygame.init()
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
screen = pygame.display.set_mode((600, 800), 0, 32)
screen.fill(WHITE)
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return
elif event.type == pygame.MOUSEMOTION:
if event.buttons[0]: # Left mouse button down.
last = (event.pos[0]-event.rel[0], event.pos[1]-event.rel[1])
pygame.draw.line(screen, BLACK, last, event.pos, 1)
pygame.display.update()
clock.tick(30) # Limit the frame rate to 30 FPS.
if __name__ == "__main__":
main()

Related

how to remove square after 2 seconds

I have this code and I don't know how to make the red cube disappear after 2 seconds.
import pygame
import sys
from pygame.locals import *
pygame.init()
a=0
#display
prozor = pygame.display.set_mode((800,800))
FPS = pygame.time.Clock()
FPS.tick(60)
#boje
green=pygame.Color(0 ,255 , 0)
red=pygame.Color(255, 0, 0)
yellow=pygame.Color(255, 255, 0)
blue=pygame.Color(0, 0, 255)
black=pygame.Color(0, 0, 0)
white=pygame.Color(255, 255, 255)
#class
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
def draw(self):
pygame.draw.rect(prozor, (255, 0, 0), self.square)
cube = Cube()
drawing_cube = False
#objekt
for j in range(16):
for i in range(800):
if i%50 == 0:
pygame.draw.rect(prozor, green, ((0+i, a), (50, 50),),1)
a=a+50
#gameloop
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit
if event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
if drawing_cube:
cube.draw()
pygame.display.flip()
pygame.display.update()
Adding it to the draw class will just freeze the game and shut it.
def draw(self):
pygame.draw.rect(prozor, red, self.square)
time.sleep(3)
pygame.draw.rect(prozor, black, self.square
I tried making another class called delete which would delete the cube after 3 seconds using the time module.
def delete(self):
time.sleep(3)
pygame.draw.rect(prozor, black, self.square)
and added it here
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit
if event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
if drawing_cube:
cube.draw()
pygame.display.flip()
**cube.delete**
pygame.display.flip()
pygame.display.update()
but the cube is not disappearing.
Use pygame.time.get_ticks to measure the time in milliseconds. Calculate the time when the cube must disappear again and hide the cube if the current time is greater than the calculated time. You also need to clear the display (prozor.fill(0)) and redraw the scene in each frame:
drawing_cube = False
hide_cube_time = 0
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
hide_cube_time = current_time + 2000 # 2000 milliseconds == 2 sconds
if current_time > hide_cube_time:
drawing_cube = False
prozor.fill(0)
a=0
for j in range(16):
for i in range(800):
if i%50 == 0:
pygame.draw.rect(prozor, green, (0+i, a, 50, 50), 1)
a=a+50
if drawing_cube:
cube.draw()
pygame.display.update()
pygame.quit()
sys.exit()
Note, the typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()

why this code is not letting me draw using the rectangle but just moving the rectangle?

import pygame
pygame.init()
win = pygame.display.set_mode((800, 600))
Listing all pixels in pygame window in an array
pts = pygame.PixelArray(win)
Creating some color constants
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREY = (128, 128, 128)
clicked = False
clock = pygame.time.Clock()
# GAME LOOP
while True:
win.fill(BLACK)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
Checking if left mousebutton if clicked and held
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
clicked = True
Checking if mousebutton released
elif event.type == pygame.MOUSEBUTTONUP:
clicked = False
I don't know if something is wrong down here.
if clicked:
mouse_X, mouse_Y = pygame.mouse.get_pos()
for a in range(mouse_X, mouse_X + 79):
pts[a][mouse_Y:mouse_Y + 60] = GREEN
pygame.display.update()
clock.tick(250)
This is a problem of your logic. The rectangle is not drawn permanently.
pts[a][mouse_Y:mouse_Y + 60] = GREEN changes a pixel in the win Surface.
However win.fill(BLACK) turns all the pixel in win into BLACK.
Copy the "win" surface as soon as a rectangle has been placed on a permanant_win Surface. blit the Surface as the background of the window at the beginning of the application loop:
import pygame
pygame.init()
win = pygame.display.set_mode((800, 600))
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
clicked = False
clock = pygame.time.Clock()
permanant_win = win.copy()
while True:
win.blit(permanant_win, (0, 0))
make_permanent = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
clicked = True
elif event.type == pygame.MOUSEBUTTONUP:
make_permanent = True
if clicked:
mouse_X, mouse_Y = pygame.mouse.get_pos()
pts = pygame.PixelArray(win)
for a in range(mouse_X, mouse_X + 79):
pts[a][mouse_Y:mouse_Y + 60] = GREEN
pts = None
if make_permanent:
permanant_win = win.copy()
pygame.display.update()
clock.tick(250)

key event triggers and moving objects on screen

So I am making a game with the pygame module in python. The game is Breakout. One of the mechanics of the game is move the player left and right. How am I doing this is when the user presses the left or right arrow key, the player brick moves the left or right depending on what key is pressed, but the catch is that it if the player presses and holds the left or right button; the player brick will not continue to move... My question is how do I make the player brick continue to move instead of moving once when the key button is held down?!
here is my code
import pygame
pygame.init()
#colors
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
#the Brick
class goodbrick:
def __init__ (self, color):
self.color_scheme=color
##################X, Y L F
self.cordinates= [20, 450, 100, 0]
def move (self, x):
self.cordinates[0]+=x
def draw (self):
pygame.draw.rect(screen, self.color_scheme, self.cordinates, 0)
#class enemyBrick:
#the ball
#pygame stuff
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("BREAKOUT")
done= False
clock = pygame.time.Clock()
#init stuff
player1= goodbrick(GREEN)
#main loop
while not done:
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT:
done=True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
player1.move(-1)
if event.key == pygame.K_RIGHT:
player1.move(1)
elif event.type ==pygame.KEYUP:
if event.key == pygame.K_LEFT:
player1.move(-1)
print("yup")
if event.key == pygame.K_RIGHT:
player1.move(1)
#art
screen.fill(BLACK)
player1.draw()
#screent
pygame.display.flip()
clock.tick(60)
pygame.quit()
import pygame
pygame.init()
#colors
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
#the Brick
class goodbrick:
def __init__ (self, color):
self.color_scheme=color
##################X, Y L F
self.cordinates= [20, 450, 100, 0]
def move (self, x):
self.cordinates[0]+=x
def draw (self):
pygame.draw.rect(screen, self.color_scheme, self.cordinates, 0)
#class enemyBrick:
#the ball
#pygame stuff
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("BREAKOUT")
done= False
clock = pygame.time.Clock()
#init stuff
player1= goodbrick(GREEN)
#main loop
change = 0
while not done:
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT:
done=True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
change = -1
if event.key == pygame.K_RIGHT:
change = 1
elif event.type ==pygame.KEYUP:
if event.key == pygame.K_LEFT:
change = 0
print("yup")
if event.key == pygame.K_RIGHT:
change = 0
player1.move(change)
#art
screen.fill(BLACK)
player1.draw()
#screent
pygame.display.flip()
clock.tick(60)
pygame.quit()

How do I check to see if a mouse click is within a circle in pygame?

import pygame
pygame.init()
white = 255,255,255
cyan = 0,255,255
gameDisplay = pygame.display.set_mode((800,600))
pygame.display.set_caption('Circle Click Test')
stop = False
while not stop:
gameDisplay.fill(white)
pygame.draw.circle(gameDisplay,cyan,(400,300),(100))
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
####################################################
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
Here I have a circle on the screen, and I would like to check to see if the user
clicked within the circle. I know how to do this with a rectangle, I would assume it would be similar. Thanks for any help, I am quite new to pygame.
here is what I have for rectangles:
import pygame
pygame.init()
white = 255,255,255
cyan = 0,255,255
gameDisplay = pygame.display.set_mode((800,600))
pygame.display.set_caption('Circle Click Test')
rectangle = pygame.Rect(400,300,200,200)
stop = False
while not stop:
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, cyan,rectangle,4)
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
click = rectangle.collidepoint(pygame.mouse.get_pos())
if click == 1:
print 'CLICKED!'
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
pygame.display.update()
Use the distance formula:
################################################################################
# Imports ######################################################################
################################################################################
from pygame.locals import *
import pygame, sys, math
################################################################################
# Screen Setup #################################################################
################################################################################
pygame.init()
scr = pygame.display.set_mode((640, 480))
pygame.display.set_caption('Box Test')
################################################################################
# Game Loop ####################################################################
################################################################################
while True:
pygame.display.update(); scr.fill((200, 200, 255))
pygame.draw.circle(scr, (0, 0, 0), (400, 300), 100)
x = pygame.mouse.get_pos()[0]
y = pygame.mouse.get_pos()[1]
sqx = (x - 400)**2
sqy = (y - 300)**2
if math.sqrt(sqx + sqy) < 100:
print 'inside'
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
################################################################################
################################################################################
################################################################################
you could sample the pixel like this
detect click on shape pygame
otherwise use pythagoras to get the distance from the centre.
As Malik shows, pythagoras works well for circles, but for general solid colour shapes you can do:
if event.type == pygame.MOUSEBUTTONDOWN:
click = gameDisplay.get_at(pygame.mouse.get_pos()) == cyan
if click == 1:
print 'CLICKED!'

my click's counter program wont work

After importing the modules and declaring the variables here is how my code starts:
while True:
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
dibujarCirculo()
cont += 1
contador = texto.render("Clicks: " + str(cont), 1, green)
ventana.blit(contador, CONT_POS)
pygame.display.update()
When i run it i get the screen fill with black, and some text "Clicks :0" and when i click the mouse, instead of turning "Clicks: 1" the 1 stacks over the zero and it becomes a mess.
My intention is simply: when you click somewhere in the window it adds 1 to a click's counter. Also it actually draw a circle but that's not important.
i will post the whole code if you want to give it a look.
import sys
import pygame
from pygame.constants import *
pygame.init()
ventana = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Basics")
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
darkBlue = (0, 0, 128)
white = (255, 255, 255)
black = (0, 0, 0)
pink = (255, 200, 200)
cont = 0
CONT_POS = (50, 100)
texto = pygame.font.SysFont("monospace", 15)
def dibujarCirculo():
pos = pygame.mouse.get_pos()
radius = 10
pygame.draw.circle(ventana, white, pos, radius)
cont = 0
while True:
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
dibujarCirculo()
cont += 1
contador = texto.render("Clicks: " + str(cont), 1, green)
ventana.blit(contador, CONT_POS)
pygame.display.update()
note: it is the second time i am posting these because people is voting down for no reason and also tagging the post as off-topic when i try to explain my problem the best way i know...
You need to clear the screen to avoid drawing on top of the old text
while True:
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
dibujarCirculo()
cont += 1
ventana.fill((0,0,0)) # clear the screen
contador = texto.render("Clicks: " + str(cont), 0, green)
ventana.blit(contador, CONT_POS)
pygame.display.update()
You can add the blit using black in your first function to just overwrite the blit each time.
def dibujarCirculo():
pos = pygame.mouse.get_pos()
radius = 10
pygame.draw.circle(ventana, white, pos, radius)
contador = texto.render("Clicks: " + str(cont), 0, black) # set background to black
ventana.blit(contador, CONT_POS)
while True:
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == MOUSEBUTTONDOWN:
dibujarCirculo()
cont += 1
contador = texto.render("Clicks: " + str(cont), 1, green)
ventana.blit(contador, CONT_POS)
pygame.display.update()

Categories