我正在尝试将2个单独的列表变成一张地图。
用于放置色块或纹理
是要保留墙壁**和出口的位置。
我正在使用两种不同的方法创建图块,这些图块使用字符表示图块。我可以使这两种方法分别工作,但想将两者结合使用?
我理想地想知道如何将两个列表中的两个结果合并,
#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.你可以走过一些水砖,但不能走过
2.流沙,隐形物品或陷阱
因此,在第一张地图中,用X蓝色代表水瓦片
colors = {'X': pygame.color.THECOLORS['blue']}
在第二个中,我用W表示水以进行壁碰撞检测。
在此示例中,我通过使用W进行墙壁碰撞检测来遮挡区域,蓝色或水,灰色或岩砖是玩家无法行走的区域。
在此示例中,我通过使用W进行墙壁碰撞检测来遮挡区域,蓝色或水,灰色或岩砖是玩家无法行走的区域。但是我想保留两张地图,以防万一我想添加不可见的区域或也许可以在上面行走的水等。
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
我正在使用我从这里阅读Sloth帖子的成员中学到的技术来创建颜色或纹理图块。
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
我将用纹理贴图替换颜色
######################################
以下是我尝试遵循给出的答案的尝试,但我仍然只能执行一半的检查。
完整资料
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
我可能建议在Python中使用zip()
函数。基本上,它使用两个(或多个)列表作为参数,并返回一个列表,其中每个元素都是该位置原始两个列表的值的元组。例如,您可以创建一个新列表,其中地图中的每个位置都有一个元组(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')]]
然后,您可以使用以下类似方法获取地图中任何给定位置
(x, y)
的瓷砖和墙壁状态:(tile, wall) = combined_list[x][y]
然后,您可以分别访问
tile
和wall
:>> (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)))
现在,您可以使用以下命令访问位置
(tile, wall)
的(x, y)
值:(tile, wall) = combined[x + y*n] # where "n" is how many columns you have in your map
使用
itertools
(或不使用)可能仍然有一种更优雅的方法,但是希望这会有所帮助。关于python - 结合单独的关卡贴图以获取Pygame中的纹理图块,墙和导出,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31505548/