Python pygame检测鼠标是否在su的非透明部分

2024-09-30 16:35:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图为我的游戏做一个用户界面,有一些曲线到用户界面。现在我可以检测到两个曲面之间的碰撞。我可以通过像素检测两个精灵之间的位置,但似乎鼠标通过像素检测是在暗示我。基本上,我想检测鼠标在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)

gui类

^{pr2}$

pygame


Tags: rectimageimportselfsrcobjectdefgui
3条回答

两个可能的答案:

1)静态创建一个与屏幕一样大的True或False二维数组-如果单击此处将单击UI,则为True;如果单击此处将不单击UI,则为False。在此数组中的位置上测试单击次数。在

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

好吧,我认为这是最好的选择,而不是一些替代方案。会让每个人都保持最新,如果这是有效的或不。在

全局单击变量在dict中存储数据 对象的图层变量范围从1到?从最低层到最高层(类似于html zIndex)

  1. 一回路
    1. 重置全局单击变量
    2. 单击事件获取位置
  2. 在可单击的对象上循环以获得鼠标下的所有内容
    1. 循环鼠标下的所有内容以获得最高层
    2. 返回全局单击变量
  3. 在对象中运行单击代码。在

当前可以修改的层组织。在

佐尔德层

  1. 背景
  2. 不适用
  3. 瓷砖
  4. 平铺选择器
  5. 不适用
  6. 不适用
  7. 面板
  8. 主菜单
  9. GUI按钮
  10. 不适用

循环

for i in range(len(self.OBJECTS)):
    #img = Texture(see op)
    img = self.OBJECTS[i].IMAGE
    print(img)
    e = None
    if self.OBJECTS[i].zOrder == 4: # is isometric image
        # tx and ty are translated positions for screen2iso. See Below
        if ((self.tx >= 0 and self.tx < self.SETTING['MAP_WIDTH']) and (self.ty >= 0 and self.ty < self.SETTING['MAP_HEIGHT'])):
            # map_x and map_y are starting points for the map its self.
            ix, iy = self.screen2iso(
                (x - (self.map_x + (self.SETTING['TILE_WIDTH'] / 2))),
                (y - (self.map_y))
            )
            imgx, imgy = self.screen2iso(
                (img.x - (self.map_x + (self.SETTING['TILE_WIDTH'] / 2))),
                (img.y - (self.map_y))
            )
            if (imgx+2) == ix:
                if (imgy+1) == iy:
                    e = self.OBJECTS[i]
                else:
                    continue
            else:
                continue
    else: # Not an isometric image
        if x > img.x and x < (img.x + img.rect[2]):
            if y > img.y and y < (img.y + img.rect[3]):
                #is click inside of visual area of image?
                if self.getCordInImage(x, y, self.OBJECTS[i].IMAGE):
                    if self.getAlphaOfPixel(self.OBJECTS[i]) != 0:
                        e = self.OBJECTS[i]
                else:
                    continue
            else:
                continue
        else:
            continue
    if e != None:
        if self.CLICKED['zOrder'] < e.getZ():
            self.CLICKED['zOrder'] = e.getZ()
            self.CLICKED['e'] = e
        else:
            continue
    else:
        continue

获取索引

^{pr2}$

获取AlphaOfPixel

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]

屏幕2iso

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

iso2screen

def iso2screen(self, x, y):
    xx = (x - y) * (self.SETTING['TILE_WIDTH'] / 2)
    yy = (x + y) * (self.SETTING['TILE_HEIGHT'] / 2)
    return xx, yy

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

http://www.pygame.org/docs/ref/mask.html#pygame.mask.from_surface

通过mask对象的get_at((x,y))函数,您可以测试是否设置了掩码的特定像素(如果设置了像素,则返回非零值)。在

http://www.pygame.org/docs/ref/mask.html#pygame.mask.Mask.get_at

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

相关问题 更多 >