python - 在 Pygame 中组合纹理图 block 、墙壁和导出的单独关卡贴图

标签 python pygame

我正在尝试将 2 个单独的列表变成一张图 block map 。

  1. 用于放置色 block 或纹理
  2. 用于保持墙壁**和导出点的位置。

我使用两种不同的方法来创建图 block ,使用字符来表示图 block 。我可以让这两种方法单独工作,但想组合或使用它们?

我希望知道如何将两个列表中的两个结果结合起来

#map of the colors or textured tiles
level1tile = ["------",
              "-$$---",
              "-$^^$-",
              "------"
    ]
#level1tile is a simple mapping: char -> colour
colors = {'X': pygame.color.THECOLORS['blue'],
          '-': pygame.color.THECOLORS['grey'],
          '^': pygame.color.THECOLORS['brown'] ]        
          }

#map of the walls and level exits
level1wall = ["WWWWWW",
              "W    E",
              "W WW W",
              "WWWWWW"
    ]
#level1wall is collision detection W = wall, E = exit, P = Player
  1. 用于放置色 block 或纹理
  2. 用于保持墙壁**和导出点的位置。

我将添加不可见的项目,因此我想保留两个单独的 map ,以便某些标题可以具有与墙相同的纹理,也可以不具有相同的纹理。

一些可能用途的示例: 1.你可以穿过一些水砖,但不能穿过其他水砖 2.流沙、隐形元素或陷阱

所以在第一张 map 中代表X蓝色的水 block

 colors = {'X': pygame.color.THECOLORS['blue']}

在第二个中,我代表水,W代表墙碰撞检测。

我通过使用W作为墙来封锁区域以进行碰撞检测,在此示例中,蓝色或水和灰色或岩砖是玩家无法行走的区域。

Background titles

我通过使用W作为墙壁来封锁区域以进行碰撞检测,在此示例中,蓝色或水和灰色或岩砖是玩家无法行走的区域。但我想保留两张 map ,以防我想添加不可见的区域或者一些可以行走的水等。

Method 1

level = ["WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW",
         "W           WWWWWWWWW WW          EW",
         "W            WWWWWWW               W",
         "W           WW             WWW     W",
         "W          WW             WWWWW    W",
         "W                        WWWWWWW   W",
         "W                        WWWWWW    W",
         "W                        WWWWWWW   W",
         "W                         WWWWWW   W",
         "W                            WW    W",
         "W                                  W",
         "W                W                 W",
         "W               WWW                W",
         "W              WWWWW               W",
         "W              WWWWW               W",
         "W             WWWWW                W",
         "W              WWWWWW              W",
         "W                 WWW              W",
         "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"]


# W = wall, E = exit, P = Player
x = y = 0
for row in level:
    for col in row:
        if col == "W":
            Wall((x, y))
        if col == "E":
            end_rect = pygame.Rect(x, y, 32, 32)
        x += 32
    y += 32
    x = 0

我正在使用我从阅读成员(member) Sloth 帖子中学到的技术来创建颜色或纹理图 block map 。

levelB = ["------------------------------------",
         "-  $$$$$$$$$--------- --   $ $ $ $E-",
         "- $  $$$$$$$$-------^^^^         $$-",
         "-$ $$$$$$$$ --     ^^^^    XXX    $-",
         "-  $$$$$$$ --  $  ^^^^    XXXXX    -",
         "-    $$$$$$$      ^^^^   XXXXXXX   -",
         "- $$$$$$$$$$      ^^^^   XXXXXX    -",
         "-    $$$$$$$$     ^^^^   XXXXXXX   -",
         "-$$$$$$$$$$$$$$  ^^^^     XXXXXX   -",
         "-     $$$$$$$   ^^^^         XX    -",
         "-  $ $$$       ^^^^        $ $ $ $ -",
         "- $$$$$$     ^^^^-         $$$$$$$$-",
         "-  $$$$$$   ^^^^---      $$$$$ $ $ -",
         "- $$$$$    ^^^^-----        $$$$$$$-",
         "- $$$$$$$  ^^^^-----       $ $ $ $ -",
         "- $$$$$$$ ^^^^-----       $$$$$$ $$-",
         "-  $$$$$$ ^^^^ ------      $ $ $ $ -",
         "- $$$$$$$$  ^^^^  ---            $$-",
         "------------------------------------"]
#a simple mapping: char -> colour
colors = {'X': pygame.color.THECOLORS['blue'],
          '-': pygame.color.THECOLORS['grey'],
          '$': pygame.color.THECOLORS['green'],
          '^': pygame.color.THECOLORS['brown'], 
          'E': pygame.color.THECOLORS['black']        
          }

blocksize = 32

我将用纹理贴图交换颜色

enter image description here

########################################

enter image description here

下面是我按照所提供的答案进行的尝试,但我只完成了一半的检查。

完整来源

import os
import random
import pygame

#map of the colors or textured tiles
level1tile = ["------------------------------------",
         "-  $$$$$$$$$--------- --   $ $ $ $E-",
         "- $  $$$$$$$$-------^^^^         $$-",
         "-$ $$$$$$$$ --     ^^^^    XXX    $-",
         "-  $$$$$$$ --  $  ^^^^    XXXXX    -",
         "-    $$$$$$$      ^^^^   XXXXXXX   -",
         "- $$$$$$$$$$      ^^^^   XXXXXX    -",
         "-    $$$$$$$$     ^^^^   XXXXXXX   -",
         "-$$$$$$$$$$$$$$  ^^^^     XXXXXX   -",
         "-     $$$$$$$   ^^^^         XX    -",
         "-  $ $$$       ^^^^        $ $ $ $ -",
         "- $$$$$$     ^^^^-         $$$$$$$$-",
         "-  $$$$$$   ^^^^---      $$$$$ $ $ -",
         "- $$$$$    ^^^^-----        $$$$$$$-",
         "- $$$$$$$  ^^^^-----       $ $ $ $ -",
         "- $$$$$$$ ^^^^-----       $$$$$$ $$-",
         "-  $$$$$$ ^^^^ ------      $ $ $ $ -",
         "- $$$$$$$$  ^^^^  ---            $$-",
         "------------------------------------"]
#a simple mapping: char -> color
colors = {'X': pygame.color.THECOLORS['blue'],
          '-': pygame.color.THECOLORS['grey'],
          '$': pygame.color.THECOLORS['green'],
          '^': pygame.color.THECOLORS['brown'], 
          'E': pygame.color.THECOLORS['black']        
          }

blocksize = 32
#map of the walls and level exits
level1wall = ["WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW",
         "W           WWWWWWWWW WW          EW",
         "W            WWWWWWW               W",
         "W           WW             WWW     W",
         "W          WW             WWWWW    W",
         "W                        WWWWWWW   W",
         "W                        WWWWWW    W",
         "W                        WWWWWWW   W",
         "W                         WWWWWW   W",
         "W                            WW    W",
         "W                                  W",
         "W                W                 W",
         "W               WWW                W",
         "W              WWWWW               W",
         "W              WWWWW               W",
         "W             WWWWW                W",
         "W              WWWWWW              W",
         "W                 WWW              W",
         "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"]


# Class for the Player object
class Player(object):

    def __init__(self):
        self.rect = pygame.Rect(32, 32, 16, 16)

    def move(self, dx, dy):

        # Move each axis separately. Note that this checks for collisions both times.
        if dx != 0:
            self.move_single_axis(dx, 0)
        if dy != 0:
            self.move_single_axis(0, dy)

    def move_single_axis(self, dx, dy):

        # Move the rect
        self.rect.x += dx
        self.rect.y += dy

        # If you collide with a wall, move out based on velocity
        for wall in walls:
            if self.rect.colliderect(wall.rect):
                if dx > 0: # collide right
                    self.rect.right = wall.rect.left
                if dx < 0: # collide left
                    self.rect.left = wall.rect.right
                if dy > 0: # collide top
                    self.rect.bottom = wall.rect.top
                if dy < 0: # collide bottom
                    self.rect.top = wall.rect.bottom

# Nice class to hold a wall rect
class Wall(object):

    def __init__(self, pos):
        walls.append(self)
        self.rect = pygame.Rect(pos[0], pos[1], 32, 32)
#level1wall is collision detection W = wall, E = exit, P = Player

#Block
class Block(pygame.sprite.Sprite):
    # Constructor. Pass in the color of the block, and its x and y position
    def __init__(self, color, width, height, x, y):
       # Call the parent class (Sprite) constructor
       pygame.sprite.Sprite.__init__(self)

       # Create an image of the block, and fill it with a color.
       # This could also be an image loaded from the disk.
       self.image = pygame.Surface([width, height])
       self.image.fill(color)

       # Fetch the rectangle object that has the dimensions of the image
       # Update the position of this object by setting the values of rect.x and rect.y
       self.rect = self.image.get_rect(top=y, left=x)

pygame.init()


# Set up the display
pygame.display.set_caption("Tiles and Walls!")
screen = pygame.display.set_mode((len(level[0])* blocksize, len(level*blocksize)))
#screen = pygame.display.set_mode((1150, 600))

clock = pygame.time.Clock()
walls = [] # List to hold the walls
player = Player() # Create the player


combined_list = []  # initialize a blank list
for i in range(len(level1tile)):  # build your new list
  combined_list.append(zip(level1tile[i], level1wall[i]))

    # Parse the level string above. W = wall, E = exit
x = y = 0
for row in level1wall:
    for col in row:
        if col == "W":
            Wall((x, y))
        if col == "E":
            end_rect = pygame.Rect(x, y, 32, 32)
        x += 32
    y += 32
    x = 0

running = True
while running:

    clock.tick(60)

    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            running = False
        if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
            running = False

    # Move the player if an arrow key is pressed
    key = pygame.key.get_pressed()
    if key[pygame.K_LEFT]:
        player.move(-2, 0)
    if key[pygame.K_RIGHT]:
        player.move(2, 0)
    if key[pygame.K_UP]:
        player.move(0, -2)
    if key[pygame.K_DOWN]:
        player.move(0, 2)

    # Just added this to make it slightly fun ;)
    if player.rect.colliderect(end_rect):
        raise SystemExit("Next Level!")

    # Draw the scene
    screen.fill((0, 0, 0))
    for wall in walls:
        pygame.draw.rect(screen, (255, 255, 255), wall.rect)
    pygame.draw.rect(screen, (255, 0, 0), end_rect)
    pygame.draw.rect(screen, (255, 200, 0), player.rect)
    pygame.display.flip()

最佳答案

没有 Itertools

我可能建议使用 zip() Python 中的函数。基本上它需要两个(或更多)列表作为参数并返回一个列表,其中每个元素都是该位置原始两个列表的值的元组。例如,您可以创建一个新列表,其中在 map 中的每个位置都有一个元组 (tile, wall):

combined_list = []  # initialize a blank list
for i in range(len(level1tile)):  # build your new list
  combined_list.append(zip(level1tile[i], level1wall[i]))

使用问题中的第一个示例返回:

combined_list = 
[[('-', 'W'), ('-', 'W'), ('-', 'W'), ('-', 'W'), ('-', 'W'), ('-', 'W')],
 [('-', 'W'), ('$', ' '), ('$', ' '), ('-', ' '), ('-', ' '), ('-', 'E')],
 [('-', 'W'), ('$', ' '), ('^', 'W'), ('^', 'W'), ('$', ' '), ('-', 'W')],
 [('-', 'W'), ('-', 'W'), ('-', 'W'), ('-', 'W'), ('-', 'W'), ('-', 'W')]]

然后,您可以获取 map 中任何给定位置的图 block 和墙壁状态,(x, y),类似于:

(tile, wall) = combined_list[x][y]

然后您可以分别访问tilewall:

>> (tile, wall) = combined_list[1][0]
>> tile
    '-'
>> wall
    'W'

这符合您正在寻找的内容吗?

可能有一种非常聪明的方法将这两个字符串列表与列表理解结合起来,但我无法完全让它为我工作。

编辑:使用 Itertools

有一个聪明的方法可以使用itertools来做到这一点。 !嗯,有点像。我无法完全保留您的 2D 布局,而是设法将所有 (tile, wall) 元组放入单个 1 x n*m 长度列表中(如与 n x m 2D 列表相反):

import itertools as it
combined = list(it.izip(it.chain.from_iterable(level1tile), it.chain.from_iterable(level2tile)))

现在您可以通过以下方式访问位置(x, y)处的(tile, wall)值:

(tile, wall) = combined[x + y*n]  # where "n" is how many columns you have in your map

可能仍然有一种更优雅的方式来使用itertools(或不使用)来做到这一点,但希望这会有所帮助。

关于python - 在 Pygame 中组合纹理图 block 、墙壁和导出的单独关卡贴图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31505548/

相关文章:

python - Pygame Surface.fill() 不起作用

python - Pygame 动画 - IndexError : list index out of range

Python 字符串格式 "%4d"%

Python 3 : os. walk() 文件路径 UnicodeEncodeError: 'utf-8' codec can't encode: surrogates not allowed

python - Python中的变量名可以以整数开头吗?

python - 将列表值解压为文本

python - 这种方法是否为 "vectorized"- 用于中等数据集,速度相对较慢

python - 如何从文件中创建单词数组?

python - Sprite 图像没有出现在pygame中

python - 为什么 "rat"不能穿过TOP和BOTTOM墙,但可以穿过LEFT和RIGHT?