首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PyGame:平移平面图会导致空白

PyGame:平移平面图会导致空白
EN

Stack Overflow用户
提问于 2017-12-30 12:42:26
回答 3查看 387关注 0票数 4

我在Python3.4.3 (Win8.1)上使用PyGame 1.9.2。

我的游戏窗口由一个使用48x48px瓷砖的平铺地图组成。游戏的框架使用游戏框架类的以下方法,根据玩家的输入移动瓷砖:

代码语言:javascript
复制
def moveTiles(self):
    xmove = self.parent.dt * self.panning[0] * self.panning_speed
    ymove = self.parent.dt * self.panning[1] * self.panning_speed
    for tile in self.game_map:
        tile.x += xmove
        tile.y += ymove
        tile.rect.x = int(tile.x)
        tile.rect.y = int(tile.y)
        tile.pos = (tile.rect.x, tile.rect.y)

虽然"self.panning_speed“很容易解释,但self.panning是一个包含x和y摇摄的两个值的列表(例如0,0= no panning,-1,1=平移左,等等)。

然后,tile.x/tile.y值被用作rect和pos的x-/y-值(pos用于闪动)。

我对每个瓷砖的x/y值加一个完全相同的值,然后对它们使用" int“,据我所知,它总是将浮点数降到下一个整数。从技术上看,每个瓷砖的x/y值的相对变化与任何其他瓷砖的x/y值完全相同。

然而:我仍然不时地看到行或列之间的空隙!这些空白出现不规则,但非常明显,当你停止摇摄,当一个缺口是可见的,这个差距将一直存在,直到你再次泛起。

有关示例,请参阅此图像:如图所示(红色方格中的黑线是空隙,金色和粉红色是瓷砖)。

在我的代码中,这些空白会发生在哪里?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-12-30 18:32:17

这里有一个更好的解决方案。当播放机移动时,只需将velocity添加到panning向量,就不会移动瓷砖。然后,当瓷砖被切割以得到正确的位置时,平移会添加到瓷砖的rect.topleft位置。在将其添加到平铺位置之前,您必须先将平移转换为整数(在示例中创建另一个向量,称为offset ),否则仍然会得到空白。

代码语言:javascript
复制
import itertools
import pygame as pg
from pygame.math import Vector2


TILE_SIZE = 44
TILE_IMG1 = pg.Surface((TILE_SIZE, TILE_SIZE))
TILE_IMG1.fill(pg.Color('dodgerblue3'))
TILE_IMG2 = pg.Surface((TILE_SIZE, TILE_SIZE))
TILE_IMG2.fill(pg.Color('aquamarine3'))


class Tile(pg.sprite.Sprite):

    def __init__(self, pos, image):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect(topleft=pos)
        self.pos = Vector2(pos)


def main():
    screen = pg.display.set_mode((640, 480))
    clock = pg.time.Clock()
    dt = 0

    image_cycle = itertools.cycle((TILE_IMG1, TILE_IMG2))
    game_map = pg.sprite.Group()
    # Create tile instances and add them to the game map group.
    for y in range(16):
        for x in range(20):
            image = next(image_cycle)
            game_map.add(Tile((x*TILE_SIZE, y*TILE_SIZE), image))
        next(image_cycle)

    panning = Vector2(0, 0)
    velocity = Vector2(0, 0)

    done = False

    while not done:
        for event in pg.event.get():
            if event.type == pg.QUIT:
                done = True
            elif event.type == pg.KEYDOWN:
                if event.key == pg.K_a:
                    velocity.x = 100
                elif event.key == pg.K_d:
                    velocity.x = -100
            elif event.type == pg.KEYUP:
                if event.key == pg.K_d and velocity.x < 0:
                    velocity.x = 0
                elif event.key == pg.K_a and velocity.x > 0:
                    velocity.x = 0

        # Add the velocity to the panning when we're moving.
        if velocity.x != 0 or velocity.y != 0:
            panning += velocity * dt

        game_map.update()

        screen.fill((30, 30, 30))
        # Assigning screen.blit to a local variable improves the performance.
        screen_blit = screen.blit
        # Convert the panning to ints.
        offset = Vector2([int(i) for i in panning])
        # Blit the tiles.
        for tile in game_map:
            # Add the offset to the tile's rect.topleft coordinates.
            screen_blit(tile.image, tile.rect.topleft+offset)

        pg.display.flip()
        dt = clock.tick(30) / 1000


if __name__ == '__main__':
    pg.init()
    main()
    pg.quit()

另一种选择是在程序开始时将瓷砖涂在一个大的背景表面上。这样你就不会有差距,这也会提高你的性能。

票数 1
EN

Stack Overflow用户

发布于 2017-12-30 15:54:54

我认为问题在于,float不能保留所有的值,我们有0.1 + 0.2 != 0.3的情况,它能使预期的结果和所得到的结果有区别。

您只能使用整数值来更改所有瓷砖的位置,即。

代码语言:javascript
复制
tile.rect.x = int(xmove)
tile.rect.y = int(ymove)

通过这种方式,您可以只松散较小的值(小于一个像素),但是如果您累积了许多小值,那么您可以得到很少的像素。

因此,您可以尝试累积浮点数和整数值之间的差异。

我无法检查这是否正确,但我会这样做

代码语言:javascript
复制
def moveTiles(self):

    # add moves to already cumulated differences betweeen floats and integers
    self.xcululated += self.parent.dt * self.panning[0] * self.panning_speed
    self.ycululated += self.parent.dt * self.panning[1] * self.panning_speed

    # get only integer values
    xmove = int(self.xcululated)
    ymove = int(self.ycululated)

    # remove integers from floats
    self.xcululated += xmove
    self.ycululated += ymove

    for tile in self.game_map:
        # use the same integer values for all tiles
        tile.rect.x += xmove
        tile.rect.y += tmove
票数 1
EN

Stack Overflow用户

发布于 2017-12-31 15:35:07

我认为主要的问题是你的游戏资产没有填充。

填充在资产中是非常重要的,特别是当您使用相机和浮动值时。

有时候,当使用相机时,浮点数不能提供所需的精度,并且会导致纹理出血或你在游戏中不时看到的线条。

解决方案是在资产中添加填充。

我这样做的方式如下:

  1. 下载并安装GIMP
  2. 安装一个可以从这里添加填充的插件。
  3. 加载每个资产并使用GIMP中的插件添加填充。

没有必要更改任何资产的名称。只需添加填充和覆盖即可。

我希望这对你有帮助,如果你有任何进一步的问题,请随时在下面发表评论!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48034044

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档