Reputation: 70
I'm sorry if this question is a duplicate, but I've followed numerous pages on this site trying to find an answer, and I haven't been able to get one to work yet. Some of the pages I've used are:
Pygame mouse clicking detection
how does collide.rect work in pygame
It may be my lack of coding comprehension, and I apologize if that's the case. However, I found the most "helpful" page to be the first link. Using Sloth's first answer, it seemed very simple and something I would be able to do. Once his method did not work, I tried searching around even more for on YouTube and other sites. I also couldn't find an answer.
All I want to do is simply print "clicked" when a sprite is clicked. Here is my code.
import pygame
size = (700,500)
screen = pygame.display.set_mode(size)
done = False
clock = pygame.time.Clock()
itunes = pygame.image.load('itunes.png')
screen.blit(itunes,(200,200))
sprites = [itunes]
while not done:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
clicked_sprites = [s for s in sprites if s.rect.collidepoint(pos)]
for i in clicked_sprites:
print('clicked sprite')
pygame.display.flip()
clock.tick(60)
I've learned very little of the Python language, but I found myself getting bored making the same text-based programs and would like to move on.
EDIT: I'm sorry, I should have stated what error I was getting. I'm getting: AttributeError: 'pygame.Surface' object has no attribute 'rect'
EDIT: Having trouble drawing the image on the screen
import pygame
size = (700,500)
screen = pygame.display.set_mode(size)
done = False
clock = pygame.time.Clock()
white = (0,0,0)
image = 'itunes.png'
class Thing(pygame.sprite.Sprite):
def __init__(self, image, x, y):
self.image = pygame.image.load('itunes.png')
self.x = x
self.y = y
@property
def rect(self):
return self.image.get_rect(topleft=(self.x, self.y))
itunes = Thing(image,200,200)
SpriteGroup = pygame.sprite.Group()
SpriteGroup.add(itunes)
while not done:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
clicked_sprites = [s for s in SpriteGroup if s.rect.collidepoint(pos)]
for i in clicked_sprites:
print('clicked sprite')
screen.fill((0, 0, 0))
SpriteGroup.draw(screen)
pygame.display.flip()
clock.tick(60)
Upvotes: 0
Views: 865
Reputation:
Images are pygame.Surface
objects, and they don't have a rect
as an attribute. You can get one for that Surface object, however, by calling SurfaceObject.get_rect()
. This will create a pygame.Rect
object that represents the dimensions of the Surface, if not its position.
Depending on how often your object would create a new rect
or modify it based on its position in the window, you might subclass pygame.sprite.Sprite
and use a property to retrieve the Rect at its correct position. For example:
class Thing(pygame.sprite.Sprite):
def __init__(self, image, x, y):
super(Thing, self).__init__() #don't forget to do this!! (like I did :D, haha)
self.image = pygame.image.load(image)
self.x = x
self.y = y
@property
def rect(self):
return self.image.get_rect(topleft=(self.x, self.y))
The surface.get_rect()
call takes keyword arguments that allow you to set attributes of the object as it's being created. In this way, it's basically a one-liner for:
new_rect = self.image.get_rect()
new_rect.x = self.x
new_rect.y = self.y
return new_rect
This whole process returns a rect which is in the correct position in the window, such that it can be used for collision detection or just to see if it's the object that was clicked as in your example.
Another upshot of this approach (using a property for the rect
) is that it makes the object work well with the pygame.sprite.Group.draw()
method, which draws all Sprite
objects in that Group
object by blitting their obj.image
and obj.rect
attributes.
So you take advantage of this by turning sprites
from a list
to a sprite.Group object, and making the following changes to your code:
SpriteGroup = pygame.sprite.Group() #use these for working with Sprite objects
SpriteGroup.add(itunes) #add itunes to sprites Group
while not done:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
clicked_sprites = [s for s in sprites if s.rect.collidepoint(pos)]
for i in clicked_sprites:
print('clicked sprite')
screen.fill((0, 0, 0)) #wipes the screen
SpriteGroup.draw(screen) #draws every Sprite object in this Group
pygame.display.flip()
clock.tick(60)
Upvotes: 1
Reputation: 11170
Let's take a look at what you code does.
Now how do we know the position of the objects that are in the sprite list? The answer is that we don't. There is no information about the position of the object in the surface itself.
To solve this you can make your own Sprite class that will include a rect
and a surface, or more preferably use pygame.sprite.Sprite
which already includes rect.
Upvotes: 0