Clicking overlapping rects in pygame [duplicate] - python

This question already has answers here:
How do I detect collision in pygame?
(5 answers)
How to detect when a rectangular object, image or sprite is clicked
(1 answer)
Pygame mouse clicking detection
(4 answers)
Closed 1 year ago.
I am trying to make a simple game with pygame, and I am running into the following general issue.
Suppose we have two sprites, call them sprite1 and sprite2, each with their corresponding rect and image attributes. These sprites are "clickable", in the sense that when the user clicks on them something should happen. I usually implement this by adding the following into the game loop:
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
if spritex.collidepoint(mouse_pos):
(whatever clicking on spritex triggers)
In my game sprite1 and sprite2 can occasionally overlap, and let's suppose that I always want to draw sprite2 on top of sprite1. I understand that I can achieve this by having screen.blit(sprite1.image, sprite1.rect) before screen.blit(sprite2.image, sprite2.rect). However, I would like that whenever sprite1 and sprite2 are overlapping, and the user clicks on a point that is both above sprite1.rect and sprite2.rect only the action of sprite2 should trigger.
In this simple example, I understand that one could do this with
if event.type == pygame.MOUSEBUTTONDOWN:
mouse_pos = pygame.mouse.get_pos()
if sprite2.collidepoint(mouse_pos):
(whatever clicking on spritex triggers)
elif sprite1.collidepoint(mouse_pos):
(whatever clicking on sprite1 triggers)
but this solution does not generalize easily to more complicated situations (more sprites, more types of sprites, pygame_gui elements, etc.).
I wonder: is there a more simple and elegant solution to get around problems like these?

You can create a list of all sprites in order of z-index/how far front they are, starting with closer sprites.
sprites = [sprite2, sprite1]
Then iterate until you find the first match:
def find_clicked(mouse_pos):
for sprite in sprites:
if sprite.collidepoint(mouse_pos):
return sprite
You still have to process based on the sprite that is clicked. That will still require some sort of if tree unless you have a clever implementation, such as a dictionary of function references (which only works if you never recreate the sprite objects!). However, this is much more robust than having a hardcoded if tree in the order of sprite position, because you can easily reorder the list and everything will work fine.

Related

How do I delete the previous possible moves when I click on a different sprite in my Pygame chess game? [duplicate]

Hi i want to ask a question which has been answered a lot of times on this site but i never found an appreciable answer.How to remove the images in Pygame if there is already a background image in game window.
In most of the answers,they say to use screen.fill(color) but it makes the area black.It works fine if there is no background image but with background image,it looks odd when only a certain region is colored black.How can i get rid of it?Is there an alternative way to remove the image in this particular situation.By the way I'm not adding any specific code here because i deal with this issue a lot of time while building games.
You can not remove an image. You have to redraw the entire scene (including the background) in the application loop. Note the images are just a buch of pixel drawn on top of the background. The background "under" the images is overwritten and the imformation is lost:
The main application loop has to:
handle the events by 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 either pygame.display.update() or pygame.display.flip()
A minimum application is
import pygame
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
# main application loop
run = True
while run:
clock.tick(60)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update game states and move objects
# [...]
# clear the display
window.fill(0) # or `blit` the back ground image instead
# draw the scene - draw all the objects
# [...]
# update the display
pygame.display.flip()

Python 3.9.6: How to unblit images after timer reaches 0 [duplicate]

Hi i want to ask a question which has been answered a lot of times on this site but i never found an appreciable answer.How to remove the images in Pygame if there is already a background image in game window.
In most of the answers,they say to use screen.fill(color) but it makes the area black.It works fine if there is no background image but with background image,it looks odd when only a certain region is colored black.How can i get rid of it?Is there an alternative way to remove the image in this particular situation.By the way I'm not adding any specific code here because i deal with this issue a lot of time while building games.
You can not remove an image. You have to redraw the entire scene (including the background) in the application loop. Note the images are just a buch of pixel drawn on top of the background. The background "under" the images is overwritten and the imformation is lost:
The main application loop has to:
handle the events by 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 either pygame.display.update() or pygame.display.flip()
A minimum application is
import pygame
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
# main application loop
run = True
while run:
clock.tick(60)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update game states and move objects
# [...]
# clear the display
window.fill(0) # or `blit` the back ground image instead
# draw the scene - draw all the objects
# [...]
# update the display
pygame.display.flip()

How can I make an image disappear on pygame? [duplicate]

Hi i want to ask a question which has been answered a lot of times on this site but i never found an appreciable answer.How to remove the images in Pygame if there is already a background image in game window.
In most of the answers,they say to use screen.fill(color) but it makes the area black.It works fine if there is no background image but with background image,it looks odd when only a certain region is colored black.How can i get rid of it?Is there an alternative way to remove the image in this particular situation.By the way I'm not adding any specific code here because i deal with this issue a lot of time while building games.
You can not remove an image. You have to redraw the entire scene (including the background) in the application loop. Note the images are just a buch of pixel drawn on top of the background. The background "under" the images is overwritten and the imformation is lost:
The main application loop has to:
handle the events by 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 either pygame.display.update() or pygame.display.flip()
A minimum application is
import pygame
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
# main application loop
run = True
while run:
clock.tick(60)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update game states and move objects
# [...]
# clear the display
window.fill(0) # or `blit` the back ground image instead
# draw the scene - draw all the objects
# [...]
# update the display
pygame.display.flip()

How to remove a previous rectangle created with pygame.draw.rect and having a picture as background [duplicate]

Hi i want to ask a question which has been answered a lot of times on this site but i never found an appreciable answer.How to remove the images in Pygame if there is already a background image in game window.
In most of the answers,they say to use screen.fill(color) but it makes the area black.It works fine if there is no background image but with background image,it looks odd when only a certain region is colored black.How can i get rid of it?Is there an alternative way to remove the image in this particular situation.By the way I'm not adding any specific code here because i deal with this issue a lot of time while building games.
You can not remove an image. You have to redraw the entire scene (including the background) in the application loop. Note the images are just a buch of pixel drawn on top of the background. The background "under" the images is overwritten and the imformation is lost:
The main application loop has to:
handle the events by 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 either pygame.display.update() or pygame.display.flip()
A minimum application is
import pygame
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
# main application loop
run = True
while run:
clock.tick(60)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# update game states and move objects
# [...]
# clear the display
window.fill(0) # or `blit` the back ground image instead
# draw the scene - draw all the objects
# [...]
# update the display
pygame.display.flip()

Display a sprite with no image - PyGame

I am working on a game project meant for learning and I was thinking if I create a sprite without a set image. I need this because I have an ideea to keep the value of the rect tiles that need collision in a sprite group. Is it possible?
Create a list of sprites excluding the invisible sprite(s):
all_sprites_list.draw(screen)
Then for collision just make a barrier list and put your invisible sprites that need collision in it.

Categories