2016-04-25 113 views
1

我試圖在pygame中製作2D遊戲,有點像口袋妖怪。我現在真的陷入了一個問題,我不知道如何解決。pygame 2d平鋪滾動邊不加載

當我移動我的角色時,我會滾動地圖,讓玩家保持居中。我創建了一個「動畫」,通過每次偏移2個像素的距離,而不是移動整個瓷磚大小,所以我得到流暢的動畫。我遇到的問題是,當我移動時,屏幕不會在我正在移動的邊緣加載新的圖塊,因此邊緣最終會出現空白區域,直到完成完整的動畫。我會鏈接到我的代碼,希望有人能幫助我:)

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() 

回答

2

我寫一個類似的遊戲,我將與你分享我的邏輯。 我的塊是32x32,所以每塊是32像素。

enter image description here

的外邊界是精靈屏幕和內方是顯示器。 你總是在屏幕的各個邊上都有一個精靈。現在,如果您計算屏幕任何一側的像素移動,您可以輕鬆掌握何時需要繪製下一行或一列精靈,但並不總是繪製關閉屏幕。如果我的像素移動是-8(向左移動),我會在屏幕邊界的右側繪製一列精靈,但在可見區域外。對方也一樣。

下面是我的程序中的一些代碼。這是精靈添加代碼。

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 

這裏是sprite移除代碼。

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 

該代碼很容易遵循,因爲我已經評論過它們。希望這可以幫助。

+0

我有向下和向右的移動,通過改變工作: SCREEN = pygame.display.set_mode((TILESIZE *(地圖寬度),TILESIZE *(地圖高度))) 到: SCREEN = pygame.display.set_mode((TILESIZE *(MAP_WIDTH-1),TILESIZE *(MAP_HEIGHT-1)))。 非常感謝!我的問題是我如何繪製現在應該是負面的框架?屏幕上方的瓦片和左側的瓦片!感謝迄今爲止的幫助! – madswed

+0

如果您接受我的幫助,您可以將其標記爲已接受。 :)請詳細說明這個問題。 「畫出應該是負面的畫面?屏幕上方的瓷磚和左邊的瓷磚」是什麼意思?你爲什麼需要畫這些?他們不在可見的屏幕區域嗎? – emorphus

+0

好吧,我會盡我所能。屏幕上方和屏幕左側的瓷磚的確在可見區域外面。問題是當我移動我的角色時,我畫了一個偏移量: (column * TILESIZE + offsetX,row * TILESIZE + offsetY)) 所以它在偏移區域顯示的是白色: SCREEN.fill(WHITE) 我在想,如果我可以在每個方向上繪製可見屏幕1瓦片外部,它所繪製的偏移量不會是白色的,而是下一個瓦片! – madswed