Pygame 滚动地图

0 投票
2 回答
2005 浏览
提问于 2025-04-18 10:35

我正在制作一个类“流氓”的游戏,想让摄像头在玩家移动时跟着他在地图上走。

我已经能让绘制功能只在瓷砖在摄像头视口内时执行(用灰色显示),但我还不能让摄像头固定在窗口的角落。

现在的情况是这样的:

enter image description here

而我希望它是这样的:

enter image description here

有没有办法“裁剪”屏幕表面,或者只复制摄像头视口内的内容,然后再把它显示在屏幕上?

可能我这样做有点复杂。我是在遍历整个地图,为每个瓷砖创建一个矩形,并使用 '.contains()' 检查它是否在摄像头视口矩形内。

编辑:

这是我绘制地图的方式:

for x in xrange(mymap.width):
    for y in xrange(mymap.height):
        lit = field_of_view.lit(x, y)
        visited = field_of_view.visited(x, y)
        graphic = mymap.tileAt(x, y).graphic
        if lit:
            color = mymap.tileAt(x, y).color
        elif visited:
            color = GRAY
        else:
            color = BLACK
        renderedgraphic = myfont.render(graphic, 1, color)
        screen.blit(renderedgraphic, (x*TILESIZE, y*TILESIZE))

我对玩家、怪物、物品等也做了同样的事情,但每个都在自己的类方法里。

我的摄像头设置是这样的:

class Camera(Object):
    def __init__(self, x, y):
        graphic = ''
        Object.__init__(self, graphic, x, y)
        self.rect = pygame.Rect(x, y, CAMERA_WIDTH * 2 + 5, CAMERA_HEIGHT * 2 + 5)

    def update(self):
        self.x = PLAYER.x
        self.y = PLAYER.y

        startx = ((self.x * TILESIZE) - CAMERA_WIDTH) + 5
        starty = ((self.y * TILESIZE) - CAMERA_HEIGHT) + 5
        self.rect = pygame.Rect(startx, starty, CAMERA_WIDTH * 2 + 5, CAMERA_HEIGHT * 2 + 5)

所以我试了用户3762084说的方法。

简单来说:

for x in xrange(mymap.width):
    for y in xrange(mymap.height):
        ... # do fov stuff        
        tile = Tile.At(x, y)  # get tile instance
        if tile:
            tile.update() # update it's relative position
            screen.blit(renderedgraphic, (tile.relX * TILESIZE, tile.relX * TILESIZE)) # blit the postion to it's relative position

结果是这样的:

enter image description here

所有内容都挤在窗口的一侧。如果玩家移动,整个画面就变黑了。

2 个回答

1

好的,我找到了我想要的东西,不过我做了一点小改动。如果有人有更好的方法,请告诉我。

我改变了我的地图绘制方式。

  • 我获取了相机的矩形位置,包括左上角和右下角;
  • 把这些位置转换成世界坐标;
  • 用一个枚举器遍历这些坐标;
  • 根据X和Y进行一些小的/已访问的雾计算;
  • 然后用枚举器的'i'和'j'在屏幕上绘制。

这是代码:

topleft = Map.toWorld(camera.rect.topleft)
bottomright = Map.toWorld(camera.rect.bottomright)
for i, x in enumerate(xrange(topleft[0], bottomright[0])):
    for j, y in enumerate(xrange(topleft[1], bottomright[1])):
        tile = mymap.tileAt(x, y)
        object = [obj for obj in Object.OBJECTS if obj.pos == (x,y)]
        if tile:
            lit = field_of_view.lit(x, y)
            visited = field_of_view.visited(x, y)
            graphic = tile.graphic
            if lit:
                color = tile.color
            elif visited:
                color = GRAY
            else:
                color = BLACK
            renderedgraphic = myfont.render(ch, 1, graphic)
            screen.blit(renderedgraphic, Map.toScreen((i + 1, j)))
        if object:
            Draw.drawObject(object[0], Map.toScreen((i + 1, j)))

现在唯一的问题是,当玩家在地图的边缘时,会出现一个黑色边框。

2

我之前创建滚动环境的方法是给每个物体设置在世界中的坐标,然后给你的相机一个位置。在绘制的时候,你需要根据物体的实际坐标和相机的坐标来计算每个物体在屏幕上的位置。

class Tile:
    def __init__(self, x, y, other_variables):
        self.x = x
        self.y = y

        # relative vars for later
        self.relX = None
        self.relY = None

# then your camera should have a position as well as its width and height:
class Camera:
    def __init__(self, x, y, width, height):
        # assign those variables here

# your drawing function:
for tile in tiles:
    tile.relX = tile.x - camera.x
    tile.relY = tile.y - camera.y
    # blit your tiles to the screen at the relative coordinates

另外,你还可以检查一下某个方块是否完全在相机的视野之外,如果是的话,就不绘制这些方块。

撰写回答