Pygame 二维图块滚动边缘未加载
Pygame 2d tile scrolling edges don't load
我正在尝试在 pygame 中制作一款类似于口袋妖怪的 2d 游戏。现在我真的陷入了一个问题,我不知道如何解决。
当我移动我的角色时,我会滚动地图而不是让玩家保持居中。我创建了一个 "animation",方法是一次将距离偏移 2 个像素,而不是移动整个图块大小,这样我就可以平滑地移动。我遇到的问题是,当我移动时,屏幕不会在我正在移动的边缘加载新的图块,因此边缘最终会变成白色 space 直到我完成完整的动画。我会 link 我的代码,希望有人能帮助我 :)
TILESIZE = 32
MAP_WIDTH = 25
MAP_HEIGHT = 25
class Player(pygame.sprite.Sprite):
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
super().__init__()
self.name = "Player"
self.width = width
self.height = height
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = int(TILESIZE * (MAP_WIDTH / 2)) - TILESIZE / 2
self.rect.y = int(TILESIZE * (MAP_HEIGHT / 2)) - TILESIZE / 2
class World:
def __init__(self):
self.shiftX = 0
self.shiftY = 0
self.tile_map = [ [DIRT for w in range(MAP_WIDTH)] for h in range(MAP_HEIGHT)]
for row in range(MAP_HEIGHT):
for column in range(MAP_WIDTH):
try:
if real_map[row + self.shiftY][column + self.shiftX] == 0:
tile = DIRT
elif real_map[row + self.shiftY][column + self.shiftX] == 1:
tile = GRASS
elif real_map[row + self.shiftY][column + self.shiftX] == 2:
tile = WATER
else:
tile = DIRT
self.tile_map[row][column] = tile
except:
self.tile_map[row][column] = WATER
def shiftWorld(self):
for row in range(MAP_HEIGHT):
for column in range(MAP_WIDTH):
try:
if real_map[row + self.shiftY][column + self.shiftX] == 0:
tile = DIRT
elif real_map[row + self.shiftY][column + self.shiftX] == 1:
tile = GRASS
elif real_map[row + self.shiftY][column + self.shiftX] == 2:
tile = WATER
else:
tile = DIRT
self.tile_map[row][column] = tile
except:
self.tile_map[row][column] = WATER
def okToMove(self, key):
if key[K_w]:
if self.tile_map[int(MAP_WIDTH/2 - 1)][int(MAP_HEIGHT/2)] != 2:
return True
elif key[K_s]:
if self.tile_map[int(MAP_WIDTH/2 + 1)][int(MAP_HEIGHT/2)] != 2:
return True
elif key[K_a]:
if self.tile_map[int(MAP_WIDTH/2)][int(MAP_HEIGHT/2) - 1] != 2:
return True
elif key[K_d]:
if self.tile_map[int(MAP_WIDTH/2)][int(MAP_HEIGHT/2) + 1] != 2:
return True
def start_game():
pygame.init()
clock = pygame.time.Clock()
#HÄR KAN VI MÅLA UPP MER
#SCREEN = pygame.display.set_mode((MAP_WIDTH*TILESIZE, MAP_HEIGHT*TILESIZE))
world = World()
SCREEN = pygame.display.set_mode((TILESIZE * (MAP_WIDTH-2), TILESIZE * (MAP_HEIGHT-4)))
running = True
player = Player(BLACK, 32, 32)
sprites = pygame.sprite.Group()
sprites.add(player)
movement = 0
offsetY = 0
offsetX = 0
animation_north = False
animation_south = False
animation_west = False
animation_east = False
while running:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
#Get keyinput and do whatever needs to be done
key = pygame.key.get_pressed()
if key[K_ESCAPE]:
pygame.quit()
sys.exit()
if animation_east or animation_north or animation_south or animation_west:
pass
else:
if key[K_w]:
okToMove = world.okToMove(key)
if okToMove == True:
animation_north = True
else:
pass
elif key[K_a]:
okToMove = world.okToMove(key)
if okToMove == True:
animation_west = True
elif key[K_s]:
okToMove = world.okToMove(key)
if okToMove == True:
animation_south = True
elif key[K_d]:
okToMove = world.okToMove(key)
if okToMove == True:
animation_east = True
if animation_north == True:
if movement == 32:
movement = 0
world.shiftY -= 1
world.shiftWorld()
offsetY = 0
animation_north = False
else:
offsetY += 4
movement += 4
if animation_south == True:
if movement == 32:
movement = 0
world.shiftY += 1
world.shiftWorld()
offsetY = 0
animation_south = False
intY = 0
else:
offsetY -= 4
movement += 4
if animation_west == True:
if movement == 32:
movement = 0
world.shiftX -= 1
world.shiftWorld()
offsetX = 0
animation_west = False
else:
offsetX += 4
movement += 4
if animation_east == True:
if movement == 32:
world.shiftX += 1
world.shiftWorld()
movement = 0
offsetX = 0
animation_east = False
else:
offsetX -= 4
movement += 4
SCREEN.fill(WHITE)
for row in range(MAP_HEIGHT):
for column in range(MAP_WIDTH):
SCREEN.blit(textures[world.tile_map[row][column]], (column*TILESIZE + offsetX, row*TILESIZE + offsetY))
sprites.draw(SCREEN)
pygame.display.update()
pygame.display.flip()
clock.tick(60)
start_game()
我正在写一个类似的游戏,我会和你分享我的逻辑。
我的块是 32x32 所以每个块是 32 像素。
外框是精灵画面,内框是显示器。
你总是在屏幕的四面都有一个额外的精灵。现在,如果您计算屏幕任何一侧的像素移动,您就可以很容易地跟踪何时需要绘制下一行或下一列精灵,而不是它们总是在屏幕外绘制。如果我的像素移动是 -8(向左移动),我会在屏幕边界 os 的右侧绘制一列精灵,但在可见区域之外。另一边也一样。
这是我程序中的一些代码。这是精灵添加代码。
def add_sprites(self):
"""sprites are added to the group which appear on screen right. the column number is the value in ColDrawn. We selct columns from the list according to this value. Once the end of the column list is reached we start again from the first one. We cycle thru the list depending on the NumCycle[0] value."""
if self.ColDrawn < self.Columns_in_Dungeon - 1:
self.ColDrawn += 1
else: # all the columns drawn so increment the flag
self.ColDrawn = 0
self.NumCycle[1] += 1
if self.NumCycle[1] >= self.NumCycle[0]: # if the flag is equal to the number of cycles the screen is scrolled then set numcycle[2] to True
self.NumCycle[2] = True
else: # screen can be scrolled
spritecol = self.all_wall_sprite_columns_list[self.ColDrawn]
self.wallspritegroup.add(spritecol) # add column of sprites to the sprite group
return
这里是精灵移除代码。
def remove_sprites(self):
"""sprites are removed from the group as they exit from screen left."""
for sprt in self.wallspritegroup: # remove_basic sprites that move_basic off screen on left
if sprt.rect.x <= -48:
sprt.rect.x = self.screenw # reset the x position and
sprt.kill()
#spritegrp.remove_basic(sprt) # remove_basic the sprite from the sprite group
return
代码很容易理解,因为我已经对它们进行了注释。希望这有帮助。
我正在尝试在 pygame 中制作一款类似于口袋妖怪的 2d 游戏。现在我真的陷入了一个问题,我不知道如何解决。
当我移动我的角色时,我会滚动地图而不是让玩家保持居中。我创建了一个 "animation",方法是一次将距离偏移 2 个像素,而不是移动整个图块大小,这样我就可以平滑地移动。我遇到的问题是,当我移动时,屏幕不会在我正在移动的边缘加载新的图块,因此边缘最终会变成白色 space 直到我完成完整的动画。我会 link 我的代码,希望有人能帮助我 :)
TILESIZE = 32
MAP_WIDTH = 25
MAP_HEIGHT = 25
class Player(pygame.sprite.Sprite):
def __init__(self, color, width, height):
# Call the parent class (Sprite) constructor
super().__init__()
self.name = "Player"
self.width = width
self.height = height
self.image = pygame.Surface([width, height])
self.image.fill(color)
self.rect = self.image.get_rect()
self.rect.x = int(TILESIZE * (MAP_WIDTH / 2)) - TILESIZE / 2
self.rect.y = int(TILESIZE * (MAP_HEIGHT / 2)) - TILESIZE / 2
class World:
def __init__(self):
self.shiftX = 0
self.shiftY = 0
self.tile_map = [ [DIRT for w in range(MAP_WIDTH)] for h in range(MAP_HEIGHT)]
for row in range(MAP_HEIGHT):
for column in range(MAP_WIDTH):
try:
if real_map[row + self.shiftY][column + self.shiftX] == 0:
tile = DIRT
elif real_map[row + self.shiftY][column + self.shiftX] == 1:
tile = GRASS
elif real_map[row + self.shiftY][column + self.shiftX] == 2:
tile = WATER
else:
tile = DIRT
self.tile_map[row][column] = tile
except:
self.tile_map[row][column] = WATER
def shiftWorld(self):
for row in range(MAP_HEIGHT):
for column in range(MAP_WIDTH):
try:
if real_map[row + self.shiftY][column + self.shiftX] == 0:
tile = DIRT
elif real_map[row + self.shiftY][column + self.shiftX] == 1:
tile = GRASS
elif real_map[row + self.shiftY][column + self.shiftX] == 2:
tile = WATER
else:
tile = DIRT
self.tile_map[row][column] = tile
except:
self.tile_map[row][column] = WATER
def okToMove(self, key):
if key[K_w]:
if self.tile_map[int(MAP_WIDTH/2 - 1)][int(MAP_HEIGHT/2)] != 2:
return True
elif key[K_s]:
if self.tile_map[int(MAP_WIDTH/2 + 1)][int(MAP_HEIGHT/2)] != 2:
return True
elif key[K_a]:
if self.tile_map[int(MAP_WIDTH/2)][int(MAP_HEIGHT/2) - 1] != 2:
return True
elif key[K_d]:
if self.tile_map[int(MAP_WIDTH/2)][int(MAP_HEIGHT/2) + 1] != 2:
return True
def start_game():
pygame.init()
clock = pygame.time.Clock()
#HÄR KAN VI MÅLA UPP MER
#SCREEN = pygame.display.set_mode((MAP_WIDTH*TILESIZE, MAP_HEIGHT*TILESIZE))
world = World()
SCREEN = pygame.display.set_mode((TILESIZE * (MAP_WIDTH-2), TILESIZE * (MAP_HEIGHT-4)))
running = True
player = Player(BLACK, 32, 32)
sprites = pygame.sprite.Group()
sprites.add(player)
movement = 0
offsetY = 0
offsetX = 0
animation_north = False
animation_south = False
animation_west = False
animation_east = False
while running:
for event in pygame.event.get():
if event.type==QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
#Get keyinput and do whatever needs to be done
key = pygame.key.get_pressed()
if key[K_ESCAPE]:
pygame.quit()
sys.exit()
if animation_east or animation_north or animation_south or animation_west:
pass
else:
if key[K_w]:
okToMove = world.okToMove(key)
if okToMove == True:
animation_north = True
else:
pass
elif key[K_a]:
okToMove = world.okToMove(key)
if okToMove == True:
animation_west = True
elif key[K_s]:
okToMove = world.okToMove(key)
if okToMove == True:
animation_south = True
elif key[K_d]:
okToMove = world.okToMove(key)
if okToMove == True:
animation_east = True
if animation_north == True:
if movement == 32:
movement = 0
world.shiftY -= 1
world.shiftWorld()
offsetY = 0
animation_north = False
else:
offsetY += 4
movement += 4
if animation_south == True:
if movement == 32:
movement = 0
world.shiftY += 1
world.shiftWorld()
offsetY = 0
animation_south = False
intY = 0
else:
offsetY -= 4
movement += 4
if animation_west == True:
if movement == 32:
movement = 0
world.shiftX -= 1
world.shiftWorld()
offsetX = 0
animation_west = False
else:
offsetX += 4
movement += 4
if animation_east == True:
if movement == 32:
world.shiftX += 1
world.shiftWorld()
movement = 0
offsetX = 0
animation_east = False
else:
offsetX -= 4
movement += 4
SCREEN.fill(WHITE)
for row in range(MAP_HEIGHT):
for column in range(MAP_WIDTH):
SCREEN.blit(textures[world.tile_map[row][column]], (column*TILESIZE + offsetX, row*TILESIZE + offsetY))
sprites.draw(SCREEN)
pygame.display.update()
pygame.display.flip()
clock.tick(60)
start_game()
我正在写一个类似的游戏,我会和你分享我的逻辑。 我的块是 32x32 所以每个块是 32 像素。
外框是精灵画面,内框是显示器。 你总是在屏幕的四面都有一个额外的精灵。现在,如果您计算屏幕任何一侧的像素移动,您就可以很容易地跟踪何时需要绘制下一行或下一列精灵,而不是它们总是在屏幕外绘制。如果我的像素移动是 -8(向左移动),我会在屏幕边界 os 的右侧绘制一列精灵,但在可见区域之外。另一边也一样。
这是我程序中的一些代码。这是精灵添加代码。
def add_sprites(self):
"""sprites are added to the group which appear on screen right. the column number is the value in ColDrawn. We selct columns from the list according to this value. Once the end of the column list is reached we start again from the first one. We cycle thru the list depending on the NumCycle[0] value."""
if self.ColDrawn < self.Columns_in_Dungeon - 1:
self.ColDrawn += 1
else: # all the columns drawn so increment the flag
self.ColDrawn = 0
self.NumCycle[1] += 1
if self.NumCycle[1] >= self.NumCycle[0]: # if the flag is equal to the number of cycles the screen is scrolled then set numcycle[2] to True
self.NumCycle[2] = True
else: # screen can be scrolled
spritecol = self.all_wall_sprite_columns_list[self.ColDrawn]
self.wallspritegroup.add(spritecol) # add column of sprites to the sprite group
return
这里是精灵移除代码。
def remove_sprites(self):
"""sprites are removed from the group as they exit from screen left."""
for sprt in self.wallspritegroup: # remove_basic sprites that move_basic off screen on left
if sprt.rect.x <= -48:
sprt.rect.x = self.screenw # reset the x position and
sprt.kill()
#spritegrp.remove_basic(sprt) # remove_basic the sprite from the sprite group
return
代码很容易理解,因为我已经对它们进行了注释。希望这有帮助。