PyGame Platformer,内置互动平台

2024-10-03 02:35:02 发布

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

我在寻找最简单的方法。我正在尝试实现可以通过鼠标绘制的平台(具有完全碰撞检测)。现在我有一个画线的函数,它可以画一些小的圆,但是它们靠得太近了,或多或少看起来像一条线。最好的解决办法是创造一点pygame.矩形每个圆上的物体?会有很多矩形物体。这不是一个图像,所以像素完美似乎不是一个选择?你知道吗

def drawGradientLine(screen, index, start, end, width, color_mode):
    #color values change based on index
    cvar1 = max(0, min(255, 9 * index-256))
    cvar2 = max(0, min(255, 9 * index))
    #green(0,255,0), blue(0,0,255), red(255,0,0), yellow(255,255,0)
    if color_mode == 'green':
        color = (cvar1, cvar2, cvar1)
    elif color_mode == 'blue':
        color = (cvar1, cvar1, cvar2)
    elif color_mode == 'red':
        color = (cvar2, cvar1, cvar1)
    elif color_mode == 'yellow':
        color = (cvar2, cvar2, cvar1)
    dx = end[0] - start[0]
    dy = end[1] - start[1]
    dist = max(abs(dx), abs(dy))
    for i in xrange(dist):
        x = int(start[0]+float(i)/dist*dx)
        y = int(start[1]+float(i)/dist*dy)
        pygame.draw.circle(screen, color, (x, y), width)

这就是我的绘图功能。这是我的循环,我把它放在我的主要比赛项目循环中。你知道吗

  i = 0
  while (i < len(pointList)-1):
      drawGradientLine(screen, i, pointList[i], pointList[i + 1], r, mode)
      i += 1   

感谢您的帮助,碰撞检测现在让我非常头疼(我的瓷砖也无法正确使用……)。你知道吗


Tags: indexmodedistscreenstartmaxcolorend
2条回答

你有什么理由坚持用圆圈吗?你知道吗

矩形将使线条/矩形更加平滑,并使碰撞检测更加容易,除非您希望查看像素完美的碰撞。你知道吗

您似乎也不会将绘制的对象保存在任何位置(如列表或精灵组中),因此如何检查碰撞?你知道吗


这是我为游戏做的一个leveleditor,它并不完美,但它很有效:

https://gist.github.com/marcusmoller/bae9ea310999db8d8d95

工作原理:

  • 整个游戏级别被分成10x10px的网格,以便于绘制
  • leveleditor检查是否正在单击鼠标,然后保存该鼠标位置
  • 玩家现在将鼠标移动到另一个位置并释放鼠标按钮,leveleditor现在保存新位置。你知道吗
  • 现在你有了两个不同的坐标,可以很容易地把它们做成一个矩形。你知道吗

与其创建一大堆rect对象来测试碰撞,我建议创建一个mask的可碰撞对象,并测试碰撞。基本上,mask是在图像中使用哪些像素和哪些像素不在图像中的映射。你几乎可以把它想象成一个表面的阴影或轮廓。你知道吗

当您调用pygame.draw.circle时,您已经通过了一个曲面。现在你直接在屏幕上画图,这对我的建议可能没有多大用处。我建议创建一个rect覆盖所绘制线的整个区域,然后创建一个该大小的曲面,然后将线绘制到此曲面。我的代码将假设您已经知道线的点的边界。你知道吗

line_rect = pygame.Rect(leftmost, topmost, rightmost - leftmost, bottommost - topmost)
line_surf = pygame.Surface((line_rect.width, line_rect.height))

drawGradientLine函数中,必须将点坐标转换为line_surf的对象空间。你知道吗

while (i < len(pointList)-1):
    drawGradientLine(line_surf, (line_rect.x, line_rect.y), i, pointList[i], pointList[i+1], r, mode)
    i += 1

def drawGradientLine(surf, offset, index, start, end, width, color_mode):
    # the code leading up to where you draw the circle...
    for i in xrange(dist):
        x = int(start[0]+float(i)/dist*dx) - offset[0]
        y = int(start[1]+float(i)/dist*dy) - offset[1]
        pygame.draw.circle(surf, color, (x, y), width)

现在,您将有一个曲面,其中绘制的对象将被快速加载到该曲面上。请注意,如果要绘制的线的宽度大于1,则在创建曲面时可能需要向曲面添加一些填充。你知道吗

既然已经有了曲面,就需要创建它的mask。你知道吗

surf_mask = pygame.mask.from_surface(line_surf)

希望这对你来说不会太复杂!现在,您可以检查掩码中的每个“活动”点是否在播放器的rect内发生碰撞(或在平台中绘制的任何其他要碰撞的对象),也可以从此类播放器对象的表面创建掩码,并使用pygame.Mask.overlap_area函数检查像素完美碰撞。你知道吗

# player_surf is a surface object I am imagining exists
# player_rect is a rect object I am imagining exists
overlap_count = surf_mask.overlap_area(player_surf, (line_rect.x - player_rect.x, line_rect.y - player_rect.y))

overlap_count应该是掩码之间重叠的像素数的计数。如果这大于零,那么你就知道发生了碰撞。你知道吗

以下是pygame.Mask.overlap_area:http://www.pygame.org/docs/ref/mask.html#pygame.mask.Mask.overlap_area的文档

相关问题 更多 >