如何检测鼠标和精灵之间的碰撞/鼠标悬停?

时间:2016-12-27 17:37:14

标签: python-3.x pygame

目标:了解何时使用鼠标点击/激活精灵

使用:Python 3.2 64bit,Pygame 1.92 64bit,windows 7 64bit

我花了6个小时无济于事......我已经尝试过了:

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())

我也尝试将鼠标位置转换为精灵,我真的不想这样做,就像其他帖子中提到的其他人一样,进入一个精灵,然后碰撞出相同的结果;(< / p>

我能够成功地与图像发生碰撞,但是一旦我将图像转换为精灵类,它就变成了一场噩梦......精灵课有什么问题?或者我是否在浪费时间尝试使用精灵来获得漂亮的碰撞功能,而只是使用直接碰撞的图像?

继续获取AttributeError:&#39; Sheldon&#39;对象没有属性&#39; Rect&#39; (s.Rect.collidepoint) 或AttributeError:&#39;元组&#39;对象没有属性&#39; collidepoint&#39; (s.collidepoint) 或者属性错误:&#39; Rake&#39;对象没有属性&#39; sprite&#39; (s.sprite.collidepoint)

由于我是python / pygame的新手,我应该将这个检测放在sprite类本身的Update / Render方法中,还是我使用错误的事件轮询???

我还没有想过要重新编码mousedown / up / dragging,因为我甚至无法让鼠标移动工作

希望这次帖子得到一个有效的回应...其他人没有;(

感谢您的帮助。

代码:

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()

3 个答案:

答案 0 :(得分:0)

您的代码有很多事情要发生。编码起初可能很难,但要坚持下去!只要你继续努力并且不放弃,你就会变得更好!您的错误正在发生,因为在循环之上,您正在设置各种精灵&#39;将变量转换为元组而不是rects 。 Rect不是元组,它们有一堆变量,元组不具备,而collide_rect需要其中的一些变量。我在下面的代码中对您的其他问题提出了一些意见。

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()

我还建议您浏览pygame tutorial以及查看其他人的pygame代码并尝试逐行理解。这些提示都帮助了我。祝你好运。

答案 1 :(得分:0)

感谢alanxoc3和新的一天,代码正常运行 发布在这里,因为我确定另一个新手想要做这种类型的鼠标点击

# 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()

答案 2 :(得分:0)

您不需要Sprite_Mouse_Location

BTW:设置你需要的位置

rake.rect.topleft = (400, 250)

# or 

rake.rect.x = 400
rake.rect.y = 250

不是

rake.rect = (400, 250)

因为它将pygame.Rect()替换为tuple

示例代码:

我使用Surface代替image.load(),因此每个人都可以在没有图片的情况下运行它。

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()