How to create a brush with pygame? - pygame

I'm trying to create a brush on pygame. It should draw rectangles while the left mouse button is down.
Below is what I tried:
while not game_exit:
if event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0]:
while pygame.mouse.get_pressed()[0]:
pygame.draw.rect(gameDisplay, red, [pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1], 10, 10])
But it is now working. Where is the problem?

If you need to draw rectangle when mouse button is pressed (and mouse is moving) then use
import pygame
RED = (255,0,0)
BLACK = (0,0,0)
gameDisplay = pygame.display.set_mode((600,400))
brush = None
game_exit = False
while not game_exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # left button pressed
brush = event.pos
elif event.type == pygame.MOUSEBUTTONUP:
if event.button == 1: # left button released
brush = None
elif event.type == pygame.MOUSEMOTION:
if brush: # left button still pressed
brush = event.pos
# clear bufor
gameDisplay.fill(BLACK)
# draw brush in bufor
if brush:
pygame.draw.rect(gameDisplay, RED, [brush[0], brush[1], 10, 10])
# send bufor on the screen
pygame.display.flip()

Here is a stable loop that fills, flips and receives events:
while True:
for event in pregame.event.get():
if event.type == pregame.QUIT:
pregame.quit()
window.fill((0,0,0))
#####Render here
pygame.display.flip()
pygame.time.Clock().tick(30)
Hope it helps :D

Related

pygame does not receive scroll event after re-init

I'm making a game for school project, and there's scrolling stuffs in my game. I need to reinit pygame to make sure every is reset. But somehow, scrolling stops working after reinit pygame.
I made a simple script to test if that really was the case, and it was.
import pygame
def main():
while True:
pygame.init()
screen = pygame.display.set_mode([1280, 720])
pygame.display.set_caption("PYGAME DOES NOT RECEIVE SCROLL EVENT AFTER RE-INIT?")
frame = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
print("left click")
elif event.button == 4:
print("scroll up")
elif event.button == 5:
print("scroll down")
if event.type == pygame.QUIT:
running = False
frame.tick(30)
pygame.quit()
if __name__ == "__main__":
main()
It gets left click event but not the scrolling ones.
Is there any way to fix this?
don't use pygame.MOUSEBUTTONDOWN for scroll.
I have found another way for you to map scrollling using pygame.MOUSEWHEEL.
Here is the revised code:
import pygame
def main():
while True:
pygame.init()
screen = pygame.display.set_mode([1280, 720])
pygame.display.set_caption("PYGAME DOES NOT RECEIVE SCROLL EVENT AFTER RE-INIT?")
frame = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
print("left click")
if event.button == 3:
print("right click")
if event.type == pygame.MOUSEWHEEL:
if event.y == 1:
print("scroll up")
if event.y == -1:
print("scroll down")
if event.type == pygame.QUIT:
running = False
frame.tick(60)
pygame.quit()
if __name__ == "__main__":
main()
btw, happy new year and good luck mate~

How to stop cursor lag in Pygame?

I have created a shooting game using Pygame in which one's cursor turns into a cross-hair and moves around shooting static images. However, the lag on the cross-hair is simply unbearable as the image is continually redrawn and a new background imposed over it every clock tick.
My code is as below:
import pygame, sys, random
class Crosshair(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("ch.png").convert_alpha()
self.rect = self.image.get_rect()
self.gunshot = pygame.mixer.Sound("gs.wav")
def shoot(self):
self.gunshot.play()
pygame.sprite.spritecollide(crosshair, target_group, True)
def update(self):
self.rect.center = pygame.mouse.get_pos()
class Target(pygame.sprite.Sprite):
def __init__(self, pos_x, pos_y):
super().__init__()
self.image = pygame.image.load("al.png").convert_alpha()
self.rect = self.image.get_rect()
self.rect.center = [pos_x, pos_y]
pygame.init()
clock = pygame.time.Clock()
screen_width = 1920
screen_height = 1080
screen = pygame.display.set_mode((screen_width, screen_height))
background = pygame.image.load("hoc.png").convert_alpha()
pygame.mouse.set_visible(False)
crosshair = Crosshair()
crosshair_group = pygame.sprite.Group()
crosshair_group.add(crosshair)
target_group = pygame.sprite.Group()
for target in range(20):
new_target = Target(random.randrange(0, screen_width), random.randrange(0, screen_height))
target_group.add(new_target)
Running = True
while Running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
crosshair.shoot()
pygame.display.flip()
screen.blit(background, (0, 0))
target_group.draw(screen)
crosshair_group.draw(screen)
crosshair_group.update()
clock.tick(60)
Is there any way to make the cross-hair motion smoother? Most of the code is taken almost directly from a Youtube tutorial, but for some reason I am experiencing this problem when others are not.
It is a matter of indentation. You must update and draw the scene in the application loop rather than the event loop. The application loop is executed once per frame, but the event loop is only executed when an event occurse. Actually the call of clock.tick(60) slows down your application after each event instead of each frame:
while Running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
crosshair.shoot()
# INDENTATION
#<--|
pygame.display.flip()
screen.blit(background, (0, 0))
target_group.draw(screen)
crosshair_group.draw(screen)
crosshair_group.update()
clock.tick(60)

In pygame key read is delayed

import sys
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif (event.type == pygame.KEYDOWN):
if (event.key == pygame.K_LEFT):
print('LEFT')
if (event.key == pygame.K_DOWN):
print('DOWN')
if (event.key == pygame.K_RIGHT):
print('RIGHT')
if (event.key == pygame.K_UP):
print('UP')
print('FRAME')
pygame.display.update()
clock.tick(1)
If you press arrow key just after 'FRAME' is printed, sometimes 'FRAME' is printed for second time before keypressed arrow is printed. Is as if pygame.event.get() is delayed. Example:
FRAME
FRAME
<---- UP pressed here
FRAME
UP
FRAME
FRAME
<---- UP pressed here
FRAME
UP
How could I correct this behaviour?
You are using clock.tick(1), so this is telling pygame that you want 1 fps. This will make everything slower, and pretty much pause your code for a tiny bit. Try changing the 1 to something like 60 or 30.

Pygame: Creating bullets - 'Bullet' object is not callable

I am trying to have pygame create a new Bullet object every time the mouse is pressed. It works on the first bullet, but on the second Bullet I am getting a "'Bullet' object is not callable' error.
class Bullet(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((20,40))
self.image.fill(black)
self.rect = self.image.get_rect()
self.rect.x = player_1.rect.x
self.rect.y = player_1.rect.y
#self.image = pygame.image.load("C:/Users/Thomas/Desktop/rocket.png")
self.width = self.image.get_width()
self.height = self.image.get_height()
self.speed = 20
self.damage_radius = 0
self.damage = 0
self.angle = 0
def draw(self):
self.image.fill(black)
screen.blit(self.image, (self.rect.x, self.rect.y))
def delete(self):
pass
def fire(self, mouse):
"""Determine agnle of which rocket is fired"""
pass
def update(self):
self.rect.y -= self.speed
def game_intro():
intro = True
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill(intro_bg_color)
large_text = pygame.font.Font("C:/Users/Thomas/Desktop/Python Sketches/Fonts/Quesat Black Demo.OTF", 100)
player_1 = Player((100,100), 20, blue)
while True:
pygame.display.update()
clock.tick(FPS)
mouse = pygame.mouse.get_pos()
gameEvent = pygame.event.get()
"""Draw"""
"""This wil be for advancing bullets in playing field"""
screen.fill(bg_color)
player_1.draw(mouse)
for Bullet in bullet_list:
Bullet.update()
if Bullet.rect.y < 0:
bullet_list.remove(Bullet)
Bullet.draw()
for event in gameEvent:
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.MOUSEBUTTONDOWN and pygame.mouse.get_pressed()[0]:
mouse_is_pressed = True # Used to determine if the mouse is held or not
print("Mouse pressed")
"""Generate new bullet"""
bullet = Bullet()
all_sprites_list.add(bullet)
bullet_list.add(bullet)
bullet.rect.x = player_1.rect.x
bullet.rect.y = player_1.rect.y
elif event.type == pygame.MOUSEBUTTONUP and pygame.mouse.get_rel()[0]:
mouse_is_pressed = False
print("Mouse button released")
When mouse is pressed, generate new Bullet, add it to bullet_list. This is down how an example I looked at is done and I just can't solve the issues. Help is greatly appreciated!
I took this block of code:
for Bullet in bullet_list:
Bullet.update()
Bullet.draw()
and change the "Bullet" to "bullet" and the code finally started working.
for bullet in bullet_list:
bullet.update()
bullet.draw()

Pygame making a selection like in stategy games

So I made this in order to select an area like in strategy games, however
the screen keeps blinking, is there a way to solve this?
import pygame
from pygame.locals import *
WHITE = (255,255,255)
BLUE = (0,0,255)
pygame.init()
window = pygame.display.set_mode((640, 480))
window.fill(WHITE)
pygame.display.flip()
LEFT_CLIC = 1
mouse_tracking = False
draw_area = False
while True:
for event in pygame.event.get():
if event.type == QUIT:
continuer = 0
if event.type == MOUSEBUTTONDOWN:
if event.button == LEFT_CLIC:
x_start, y_start = event.pos
x_end, y_end = event.pos
mouse_tracking = True
draw_area = True
if event.type == MOUSEMOTION and mouse_tracking:
x_end, y_end = event.pos
if event.type == MOUSEBUTTONUP:
if event.button == LEFT_CLIC:
x_end, y_end = event.pos
mouse_tracking = True
draw_area = False
if draw_area:
width = x_end-x_start
height = y_end-y_start
pygame.draw.rect(window, BLUE, (x_start, y_start, width, height))
pygame.display.flip()
window.fill(WHITE)
pygame.display.flip()
So it's pretty simple, record coordinates when there is a clic, then follow the mouse until the clic is done.
Thanks.
There should be only one pygame.display.flip() call per frame, otherwise you get this flickering, so remove one of them. Also, fill the screen before you draw the rect.
window.fill(WHITE)
if draw_area:
width = x_end-x_start
height = y_end-y_start
pygame.draw.rect(window, BLUE, (x_start, y_start, width, height))
pygame.display.flip()