Python pygame检测鼠标是否位于曲面的不透明部分上

Python pygame检测鼠标是否位于曲面的不透明部分上,python,opengl,python-2.7,pygame,Python,Opengl,Python 2.7,Pygame,我正在尝试为我的游戏制作一个UI,UI上有一些曲线。现在我可以检测两个曲面之间的碰撞。我可以通过像素在两个精灵之间进行检测,但似乎通过像素检测鼠标暗指我。基本上,我想检测鼠标何时在UI上,然后在获取UI时忽略鼠标下方的所有内容 这是一张到目前为止我所拥有的照片。如果您注意到粉红色的方块,则鼠标位于GUI上方,而黄色的选择器框位于平铺上方。黄色选择器是瓷砖上方的框框 我在openGL中使用pygame,但目前我正在寻找解决方案。我可以很容易地适应,因为我对编程并不陌生,而且我也在寻找解决方案。 我

我正在尝试为我的游戏制作一个UI,UI上有一些曲线。现在我可以检测两个曲面之间的碰撞。我可以通过像素在两个精灵之间进行检测,但似乎通过像素检测鼠标暗指我。基本上,我想检测鼠标何时在UI上,然后在获取UI时忽略鼠标下方的所有内容

这是一张到目前为止我所拥有的照片。如果您注意到粉红色的方块,则鼠标位于GUI上方,而黄色的选择器框位于平铺上方。黄色选择器是瓷砖上方的框框

我在openGL中使用pygame,但目前我正在寻找解决方案。我可以很容易地适应,因为我对编程并不陌生,而且我也在寻找解决方案。 我也会发布代码,但要发布的代码太多,所以如果需要特定的东西,请让我知道


需要注意的一点是,GUI是可伸缩的,因为左上角区域将滑入滑出。此外,白色只是占位符,因此不使用最终颜色,很难检查。按z顺序单击时,是否可以在鼠标下获取曲面元素

纹理

import pygame
from OpenGL.GL import *
from OpenGL.GLU import *

class Texture(object):
    image = None
    rect = None
    src = ''
    x = 0
    y = 0
    '''
    zOrder Layers
    0  - background
    1  - 
    2  - 
    3  - Tile Selector
    s  - Tiles
    5  - 
    6  - 
    7  - Panels
    8  - Main Menu
    9  - GUI Buttons
    10 - 

    '''

    def __init__(self, src):
        self.src = src
        self.image = pygame.image.load(src)
        self.image.set_colorkey(pygame.Color(255,0,255,0))
        self.rect = self.image.get_rect()
        texdata = pygame.image.tostring(self.image,"RGBA",0)
        # create an object textures
        self.texid = glGenTextures(1)

        # bind object textures 
        glBindTexture(GL_TEXTURE_2D, self.texid)

        # set texture filters
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

        # Create texture image
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,self.rect.w,self.rect.h,0,GL_RGBA,GL_UNSIGNED_BYTE,texdata)


        self.newList = glGenLists(2)
        glNewList(self.newList, GL_COMPILE)
        glBindTexture(GL_TEXTURE_2D, self.texid)
        glBegin(GL_QUADS)
        glTexCoord2f(0, 0); glVertex3f(0, 0 ,0)
        glTexCoord2f(0, 1); glVertex3f(0, self.rect.h, 0)
        glTexCoord2f(1, 1); glVertex3f(self.rect.w, self.rect.h, 0)
        glTexCoord2f(1, 0); glVertex3f(self.rect.w, 0, 0)

        glEnd()
        glEndList()

    def getImg(self):
        return self.image

    def getPos(self):
        rect = self.getImg().get_rect()
        pos = dict(x=self.x,y=self.y,w=rect[2],h=rect[3])
        return pos

    def draw(self,x,y,rotate=0):
        glLoadIdentity()
        self.x = int(x)
        self.y = int(y-self.rect.h+32)

        glTranslatef(x,y-self.rect.h+32,0)

        glPushAttrib(GL_TRANSFORM_BIT)
        glMatrixMode(GL_TEXTURE)
        glLoadIdentity()
        glRotatef(rotate,0,0,1)
        glPopAttrib()

        if glIsList(self.newList):
            glCallList(self.newList)
def getCordInImage(self, x, y, t):
    return [x - t.x, y - t.y]
gui类

import hashlib, string, pygame
from classes.texture import Texture

'''
Created on Jun 2, 2013

@author: Joel
'''

class gui(object):
    INSTANCES = 0           # Count of instances of buildings
    ID = 0                  # Building ID
    TYPE = 0                # Building type
    NAME = ''               # name of Building
    DESCRIPTION = ''        # Description of building
    IMAGE = ''              # Image name of building 

    zOrder = 0
    clickable = True

    def __init__(self, Game, name = 'Building', description = '', image = 'panel'):
        self.INSTANCES += 1
        self.setName(name)
        self.setDescription(description)
        self.setImage(Game, Game.SETTING["DIR"]["IMAGES"] + Game.SETTING["THEME"] + '\\gui\\'+image+'.png')
        self.setType(name.lower())
        self.setZ(6)

    def getDescription(self):
        return self.DESCRIPTION

    def setDescription(self, description):
        self.DESCRIPTION = description

    def getID(self):
        return self.ID

    def setID(self, i):
        allchr = string.maketrans('','')
        nodigits = allchr.translate(allchr, string.digits)
        s = hashlib.sha224(i).hexdigest()
        s = s.translate(allchr, nodigits)
        self.ID = s[-16:]

    def getImage(self):
        return self.IMAGE

    def setImage(self, Game, i):
        self.IMAGE = Texture(Game.CWD + '\\' + i)

    def getName(self):
        return self.NAME

    def setName(self, name):
        self.NAME = name

    def getType(self):
        return self.TYPE

    def setType(self, t):
        self.TYPE = t

    def click(self, x, y):
        if pygame.mouse.get_pressed()[0] == 1:
            if x > self.x and x < (self.x + self.rect.w):
                if y > self.y and y < (self.y + self.rect.h):
                    print("Clicked: " + str(self.x) + ', ' + str(self.y) + ', ' + str(self.rect.w) + ', ' + str(self.rect.y))

    def getClickable(self):
        return self.clickable

    def setClickable(self, c):
        self.clickable = c

    def getZ(self):
        return self.zOrder

    def setZ(self, z):
        self.zOrder = z
导入hashlib、string、pygame
从class.texture导入纹理
'''
创建于2013年6月2日
@作者:乔尔
'''
类gui(对象):
实例=0#建筑物实例计数
ID=0#建筑物ID
类型=0#建筑类型
名称=“”#建筑物名称
描述=''#建筑物描述
图像=“”#建筑物的图像名称
zOrder=0
可点击=真
def uuu init uuuuuu(自我,游戏,名称='Building',描述='',图像='panel'):
self.INSTANCES+=1
self.setName(名称)
self.setDescription(描述)
self.setImage(Game,Game.SETTING[“DIR”][“IMAGES”]+Game.SETTING[“THEME”]+'\\gui\\\'+image+'.png')
self.setType(name.lower())
self.setZ(6)
def getDescription(自我):
返回自我描述
def setDescription(自我,描述):
self.DESCRIPTION=描述
def getID(自身):
返回self.ID
def setID(自我,i):
allchr=string.maketrans(“”,“”)
nodigits=allchr.translate(allchr,string.digits)
s=hashlib.sha224(i).hexdigest()
s=s.translate(所有chr、nodigits)
self.ID=s[-16:]
def getImage(自我):
回归自我形象
def setImage(自我、游戏、i):
self.IMAGE=纹理(Game.CWD+'\\'+i)
def getName(self):
返回self.NAME
def setName(自我,名称):
self.NAME=名称
def getType(self):
返回自我类型
def设置类型(自身,t):
self.TYPE=t
def单击(自身、x、y):
如果pygame.mouse.get_pressed()[0]==1:
如果x>self.x和x<(self.x+self.rect.w):
如果y>self.y和y<(self.y+self.rect.h):
打印(“单击:”+str(self.x)+'、“+str(self.y)+'、“+str(self.rect.w)+'、“+str(self.rect.y))
def可点击(自身):
返回self.clickable
def设置可点击(自身,c):
self.clickable=c
def getZ(自我):
返回self.zOrder
def setZ(自身,z):
self.zOrder=z
两个可能的答案:

1) 静态地创建一个与屏幕一样大的二维真或假数组-如果单击此处将单击UI,则为真;如果单击此处将不单击UI,则为假。针对此阵列中的位置进行测试单击

2) 使用“绘制并检查”算法(不要回忆起真实姓名)。你知道当你在屏幕上画图时,你是如何画背景的,然后是背景对象,然后是前景对象的吗?您可以使用类似的技巧来检测您单击的对象-以一种纯色绘制背景,以另一种纯色绘制每个对象,以另一种纯色绘制每个UI元素,等等。。。只要每种纯色都是唯一的,您就可以测试此缓冲区中光标下的颜色像素,并使用它来确定鼠标单击的可见颜色。

两种可能的答案:

1) 静态地创建一个与屏幕一样大的二维真或假数组-如果单击此处将单击UI,则为真;如果单击此处将不单击UI,则为假。针对此阵列中的位置进行测试单击


2) 使用“绘制并检查”算法(不要回忆起真实姓名)。你知道当你在屏幕上画图时,你是如何画背景的,然后是背景对象,然后是前景对象的吗?您可以使用类似的技巧来检测您单击的对象-以一种纯色绘制背景,以另一种纯色绘制每个对象,以另一种纯色绘制每个UI元素,等等。。。只要每种纯色都是唯一的,您就可以测试此缓冲区中光标下的颜色像素,并使用它来确定鼠标可以看到和点击的内容。

您可以创建UI的遮罩(如果UI包含在一个表面中,然后应用于屏幕表面,这将是最简单的),并将遮罩的阈值设置为适当的值,以便在遮罩中将透明像素设置为
0

使用遮罩对象的
get_at((x,y))
功能,您可以测试是否设置了遮罩的特定像素(如果设置了像素,则返回非零值)


如果在鼠标位置传递,如果收到非零值,则可以验证鼠标是否位于UI的可见部分上。

可以创建UI的掩码(如果UI包含在一个曲面中,然后应用到屏幕曲面上,这将是最简单的),并将遮罩的阈值设置为适当的值,以便在遮罩中将透明像素设置为
0

使用掩码对象的
get_at((x,y))
函数,您可以测试特定的p
def getCordInImage(self, x, y, t):
    return [x - t.x, y - t.y]
def getAlphaOfPixel(self, t):
    mx,my = pygame.mouse.get_pos()
    x,y = self.getCordInImage(mx,my,t.IMAGE)
    #mask = pygame.mask.from_surface(t.IMAGE.image)
    return t.IMAGE.image.get_at([x,y])[3]
def screen2iso(self, x, y):
    x = x / 2
    xx = (y + x) / (self.SETTING['TILE_WIDTH'] / 2)
    yy = (y - x) / (self.SETTING['TILE_WIDTH'] / 2)
    return xx, yy
def iso2screen(self, x, y):
    xx = (x - y) * (self.SETTING['TILE_WIDTH'] / 2)
    yy = (x + y) * (self.SETTING['TILE_HEIGHT'] / 2)
    return xx, yy