Reputation: 23
Goal: to know when a sprite is clicked / active with the mouse
Using: Python 3.2 64bit, Pygame 1.92 64bit, windows 7 64bit
I spend 6 hours to no avail...I've tried :
s.rect.collidepoint(pygame.mouse.get_pos())
s.collidepoint(pygame.mouse.get_pos())
s.sprite.spritecollide(pygame.mouse.get_pos())
s.spritecollide(pygame.mouse.get_pos())
s.sprite.collide_rect(pygame.mouse.get_pos())
s.collide_rect(pygame.mouse.get_pos())
I've also tried turning the mouse location, which I really don't want to do, like someone else mentioned here on another post, into a sprite and collide like that with the same results ;(
I'm able to successfully mouse-collide with an image, but as soon as I turn the image into a sprite class, it becomes a nightmare...what's wrong with the sprite class? Or am I wasting time trying to use sprites for the nice collision features and just use images with rect collision instead?
Keep on getting the AttributeError: 'Sheldon' object has no attribute 'Rect' (s.Rect.collidepoint) or AttributeError: 'tuple' object has no attribute 'collidepoint' (s.collidepoint) or AttributeError: 'Rake' object has no attribute 'sprite' (s.sprite.collidepoint)
Since I'm new to python/pygame, should I be putting this detection in an Update/Render method in the sprite class itself, or am I using the wrong event polling???
I haven't bothered trying to recode the mousedown/up/dragging since I can't even get the mouse-over to work
Hopefully this time the post gets a working response...the others didn't ;(
Thanks for your help.
Code:
import pygame
from pygame import *
from pygame.locals import *
from pygame.sprite import *
class Sheldon(Sprite):
def __init__(self):
Sprite.__init__(self)
self.image = transform.scale(image.load('sheldon.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
class Rake(Sprite):
def __init__(self):
Sprite.__init__(self)
self.image = transform.scale(image.load('rake.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
class Sprite_Mouse_Location(Sprite):
def __init__(self,x,y):
Sprite.__init__(self)
self.rect = pygame.Rect(x,y,1,1)
print(self.rect)
pygame.init()
window = display.set_mode( (800,600) )
sheldon = Sheldon()
sheldon.rect = (10,10)
all_sprites = Group(sheldon)
rake = Rake()
rake.rect = (400,250)
all_sprites.add(rake)
x,y = pygame.mouse.get_pos()
mouse_sprite = Sprite_Mouse_Location(x,y)
running = True
while running == True:
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYUP and event.key == K_ESCAPE :
pygame.quit()
elif event.type == MOUSEMOTION :
for s in all_sprites :
if pygame.sprite.collide_rect(s,mouse_sprite):
print("hit")
window.fill( (0,0,0) )
all_sprites.update()
all_sprites.draw(window)
display.update()
Upvotes: 1
Views: 11771
Reputation: 143197
You don't need Sprite_Mouse_Location
.
BTW: to set position you need
rake.rect.topleft = (400, 250)
# or
rake.rect.x = 400
rake.rect.y = 250
not
rake.rect = (400, 250)
because it replace pygame.Rect()
with tuple
Example code:
I use Surface
instead of image.load()
so everyone can run it without images.
import pygame
# --- constants --- (UPPER_CASE names)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
# --- classes --- (CamelCase names)
class Sheldon(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((230, 310))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def check_click(self, mouse):
if self.rect.collidepoint(mouse):
print("hit RED")
class Rake(pygame.sprite.Sprite):
def __init__(self, x, y):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((230, 310))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
def check_click(self, mouse):
if self.rect.collidepoint(mouse):
print("hit GREEN")
# --- main --- (lower_case names)
# - init -
pygame.init()
window = pygame.display.set_mode((800,600))
# - objects -
sheldon = Sheldon(10, 10)
#sheldon.rect.topleft = (10, 10)
rake = Rake(400, 250)
#rake.rect.topleft = (400, 250)
all_sprites = pygame.sprite.Group()
all_sprites.add(sheldon, rake)
# - mainloop -
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT or \
(event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
for s in all_sprites:
s.check_click(event.pos)
window.fill(BLACK)
all_sprites.update()
all_sprites.draw(window)
pygame.display.update()
# - end -
pygame.quit()
Upvotes: 2
Reputation: 23
thanks to alanxoc3 and a new day, code working posting here because I'm sure another newbie is going to want to do this type of mouse click
# to create a group of sprites and use the mouse over them individually
import pygame
from pygame import *
from pygame.locals import *
from pygame.sprite import *
class Sheldon(Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self,self.groups) #have to have groups here, not documented well
self.image = transform.scale(image.load('sheldon.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
def clickCheck(self,smouse):
if pygame.sprite.collide_rect(smouse, self): #could not use sritecollison because it would flag whole group
print('hit sheldon') # this if the check mouse that its working
#------------------------------------------
class Rake(Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self,self.groups)
self.image = transform.scale(image.load('rake.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
def clickCheck(self,smouse):
if pygame.sprite.collide_rect( smouse, self ):
print('hit rake')
#-------------------------------------------
class Sprite_Mouse_Location(Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect = pygame.Rect( 0 , 0 , 1 , 1 ) # no updating needed here
#--------------------------------------------
pygame.init()
window = display.set_mode( (800,600) )
mouse_sprite = Sprite_Mouse_Location() # had to create a mouse as sprite to use the sprite collision feature
all_sprites = pygame.sprite.Group() # have to declare first, no well documented
Sheldon.groups = all_sprites # better than all_sprites = Group(sheldon), and can be assigned before instantiation of sheldon!!!
sheldon = Sheldon()
sheldon.rect = (10,10,230,310)
Rake.groups = all_sprites
rake = Rake()
rake.rect = (400,250,230,310)
running = True
while running == True:
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYUP and event.key == K_ESCAPE :
pygame.quit()
elif event.type == MOUSEBUTTONDOWN:
if event.button == 1:
mouse_sprite.rect.x , mouse_sprite.rect.y = pygame.mouse.get_pos() # have to have this to update mouse here or get wrong location
for s in all_sprites: #can't have outside the event or it will continuously check
s.clickCheck(mouse_sprite)
window.fill( (0,0,0) )
all_sprites.update() # have to have this for group sprites
all_sprites.draw(window) # have to have this for sprites
display.flip()
Upvotes: 0
Reputation:
There are a lot of things that are going on with your code. Coding can be hard at first, but keep sticking to! You'll better as long as you keep trying and don't give up! Your error is occurring because above the loop, you are setting your various sprites' rect variables to tuples instead of rects. Rects are not tuples, they have a bunch of variables that tuples don't have and collide_rect needs some of those variables. I put a couple comments in the code below about your other questions.
import pygame
from pygame import *
from pygame.locals import *
from pygame.sprite import *
class Sheldon(Sprite):
def __init__(self):
Sprite.__init__(self)
self.image = transform.scale(image.load('sheldon.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
class Rake(Sprite):
def __init__(self):
Sprite.__init__(self)
self.image = transform.scale(image.load('rake.jpg').convert(),(230,310))
self.rect = self.image.get_rect()
class Sprite_Mouse_Location(Sprite):
def __init__(self,x,y):
Sprite.__init__(self)
self.rect = pygame.Rect(x,y,1,1)
print(self.rect)
pygame.init()
window = display.set_mode( (800,600) )
sheldon = Sheldon()
sheldon.rect = (10,10) # (10,10) is not a rect!
# pygame.Rect(0,0,10,10) is a rect!
all_sprites = Group(sheldon)
rake = Rake()
rake.rect = (400,250) # Same as above comment.
all_sprites.add(rake)
x,y = pygame.mouse.get_pos() # If you are going to make the mouse
mouse_sprite = Sprite_Mouse_Location(x,y) # a sprite, then update your mouse position in the loop.
running = True
while running == True:
for event in pygame.event.get():
if event.type == QUIT or event.type == KEYUP and event.key == K_ESCAPE :
pygame.quit()
elif event.type == MOUSEMOTION :
# You could have this instead.
# mouse_sprite.rect.x, mouse_sprite.rect.y = pygame.mouse.get_pos()
# Then move the for loop below to be out of the event loop.
for s in all_sprites :
if pygame.sprite.collide_rect(s,mouse_sprite):
print("hit")
window.fill( (0,0,0) )
all_sprites.update()
all_sprites.draw(window)
display.update()
I'd also recommend going through a pygame tutorial as well as looking at other people's pygame code and trying to understand it line by line. Both those tips helped me out. Good luck.
Upvotes: 0