You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Pygame玩家精灵限制在自定义多边形边界内?

问题:将Pygame玩家精灵限制在多边形边界内

我已经实现了将玩家精灵限制在窗口矩形范围内,但不知道如何把它限制在动态多边形边界里。

现有代码

Player精灵类

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.movex = 0
        self.movey = 0
        self.frame = 0
        self.images = []
        for i in range(1,5):
            img = pygame.image.load(os.path.join('assets/player', 'run-' + str(i) + '.png')).convert_alpha()
            self.images.append(img)
        self.image = self.images[0]
        self.rect = self.image.get_rect()

    def control(self,x,y):
        self.movex += x
        self.movey += y

    def update(self):
        self.rect.x = self.rect.x + self.movex
        self.rect.y = self.rect.y + self.movey    

多边形边界定义

self.boundaries = [
    [[(475,350),(575,350),(500,550),(300,550)],],
    [[(0,0),(100,100),(200,200)]],
    [[(0,0),(100,100),(200,200)]],
]

当前尝试的限制逻辑(未成功)

self.stages.level=0
self.stages_boundary_index=0

##self.stages.player.rect.clamp_ip(pygame.display.get_surface().get_rect())

#Detection between sprite and a boundary
"""             
x = self.stages.boundaries[self.stages.level][self.stages.boundary_index]
print(x)
elem=Rect(x[0],x[1],x[2],x[3])
self.stages.player.rect.clamp_ip(elem) 
"""

编辑说明:尝试碰撞检测后存在边界偏移

我写了一套线与线、矩形与多边形的碰撞检测代码,但实际运行时发现边界有偏移问题:

def collideLineLine(l1_p1, l1_p2, l2_p1, l2_p2):

    # normalized direction of the lines and start of the lines
    P  = pygame.math.Vector2(*l1_p1)
    line1_vec = pygame.math.Vector2(*l2_p1) - P
    R = line1_vec.normalize()
    Q  = pygame.math.Vector2(*l2_p1)
    line2_vec = pygame.math.Vector2(*l2_p2) - Q
    S = line2_vec.normalize()

    # normal vectors to the lines
    RNV = pygame.math.Vector2(R[1], -R[0])
    SNV = pygame.math.Vector2(S[1], -S[0])
    RdotSVN = R.dot(SNV)
    if RdotSVN == 0:
        return False

    # distance to the intersection point
    QP  = Q - P
    t = QP.dot(SNV) / RdotSVN
    u = QP.dot(RNV) / RdotSVN

    return t > 0 and u > 0 and t*t < line1_vec.magnitude_squared() and u*u < line2_vec.magnitude_squared()

def colideRectLine(rect, p1, p2):
    return (collideLineLine(p1, p2, rect.topleft, rect.bottomleft) or
            collideLineLine(p1, p2, rect.bottomleft, rect.bottomright) or
            collideLineLine(p1, p2, rect.bottomright, rect.topright) or
            collideLineLine(p1, p2, rect.topright, rect.topleft))

def collideRectPolygon(rect, polygon):
    for i in range(len(polygon)-1):
        if colideRectLine(rect, polygon[i], polygon[i+1]):
            return True
    return False

class Player(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.movex = 0
        self.movey = 0
        self.frame = 0
        self.images = []
        for i in range(1,5):
            img = pygame.image.load(os.path.join('assets/player', 'run-' + str(i) + '.png')).convert_alpha()
            self.images.append(img)
        self.image = self.images[0]
        self.rect = self.image.get_rect()

    def control(self,x,y):
        self.movex += x
        self.movey += y

    def update(self,boundary):

        if self.movex > 0:
            self.image = self.images[self.frame//ani] 
            if self.movey !=0:
                if collideRectPolygon(self.rect, boundary):
                    self.rect.x+=self.movex
                    self.rect.y+=self.movey
                else:
                    self.rect.x-=self.movex
                    self.rect.y-=self.movey
                    self.movex=0
                    self.movey=0
            else:
                if collideRectPolygon(self.rect, boundary):
                    self.rect.x+=self.movex
                else:
                    self.rect.x-=self.movex
                    self.movex=0
        elif self.movex < 0:
            self.image = pygame.transform.flip(self.images[self.frame // ani], True, False)
            if self.movey !=0:
                if collideRectPolygon(self.rect, boundary):
                    self.rect.x+=self.movex
                    self.rect.y+=self.movey   
                else:
                    self.rect.x-=self.movex
                    self.rect.y-=self.movey
                    self.movex=0
                    self.movey=0
            else:
                if collideRectPolygon(self.rect, boundary):
                    self.rect.x+=self.movex
                else:
                    self.rect.x-=self.movex
                    self.movex=0
        else:
            self.image = self.images[self.frame//ani] 
            if self.movey !=0:
                if collideRectPolygon(self.rect, boundary):
                    self.rect.y+=self.movey
                else:
                    self.rect.y-=self.movey
                    self.movey=0
            else:
                pass

内容的提问来源于stack exchange,提问作者Arundeep Chohan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:25:21