我在 python 中开发了一个 RogueLike,我尝试用 OOP 和我的一点知识来为学生构建一个 python 课程。
mapRogue = ['~~~~~~~~~~',
'~~~~.....Y',
'YYYYY+YYYY',
'YYYY....YY']
我想将此字符串映射转换为 2D 列表,其中包含定义我在 RogueLike 中的图块性质的对象。为此,我决定在读取此变量时使用字典来映射字符键和类以进行实例化mapRogue
。
我找到了一个使用继承的解决方案,但是恕我直言,这段代码并没有我想要的那么优雅,如果我以后想添加其他类型的平铺行为,可能不是很灵活。
使用继承的 DOOR 类
class Tile(object):
#a tile of the map and its properties
def __init__(self, name, char, position, blocked, color=(255, 255, 255), bgcolor=(0, 0, 0)):
self.name = name
self.blocked = blocked
self.char = char
self.color = color
self.bgcolor = bgcolor
self.position = position
class Door(Tile):
def __init__(self, name, char, position, blocked, bgcolor, key,color=(255, 255, 255), open=False ):
Tile.__init__( self,name, char, position, blocked, color, bgcolor)
self.state = open
self.key = key
def opening(self, key):
if self.key == key:
self.state = True
tilesObject = {".": {"name": 'floor', "obj": Tile, "bgcolor": (233, 207, 177), "block": False},
"Y": {"name": 'forest', "obj": Tile, "bgcolor": (25, 150, 64), "block": True},
"~": {"name": 'water', "obj": Tile, "bgcolor": (10, 21, 35), "block": False},
"+": {"name": 'doors', "obj": Door, "bgcolor": (10, 10, 25), "block": False}}
import types
def load(mymap):
tileMap = []
x, y = (0,0)
for line in mymap:
tileLine = []
for value in line:
try:
tile = tilesObject[value]
except KeyError:
return "Error on key"
if tile["obj"].__name__ == "Door":
obj = tile["obj"](name=tile["name"], position=(x, y), char=value, blocked=tile["block"],bgcolor=tile["bgcolor"], key="42isTheKey", open=False)
else:
obj = tile["obj"](name=tile["name"], position=(x, y), char=value, blocked=tile["block"],bgcolor=tile["bgcolor"])
x += 1
tileLine.append(obj)
x = 0
y += 1
tileMap.append(tileLine)
return tileMap
for line in load(mapRogue):
for obj in line:
print obj , "\n"
使用组合的 DOOR 类
我怀疑还有其他使用组合和/或策略模式的答案,所以我尝试用 Door 行为装饰 Tile 对象,但我被这个字典阻止了......
实际上我尝试了多种解决方案但没有成功,你有没有一个建议可以帮助我使用优雅的 oop 和 python 解决这个概念问题?
class Tile(object):
#a tile of the map and its properties
def __init__(self, name, char, position, blocked, color=(255, 255, 255), bgcolor=(0, 0, 0), door=None):
self.name = name
self.blocked = blocked
self.char = char
self.color = color
self.bgcolor = bgcolor
self.door = door
self.position = position
# Door decorate the Tile object using composition
class Door(object):
def __init__(self, key, open=False):
self.state = open
self.key = key
def opening(self, key):
if self.key == key:
self.state = True
tilesObject = {".": {"name": 'floor', "obj": Tile, "bgcolor": (233, 207, 177), "block": False},
"Y": {"name": 'forest', "obj": Tile, "bgcolor": (25, 150, 64), "block": True},
"~": {"name": 'water', "obj": Tile, "bgcolor": (10, 21, 35), "block": False},
"+": {"name": 'doors', "obj": Door, "bgcolor": (10, 10, 25), "block": False}}
def load(mymap):
tileMap = []
x, y = (0,0)
for line in mymap:
tileLine = []
for value in line:
try:
tile = tilesObject[value]
except KeyError:
return "Error on key"
# Here i need to detect when obj is Door
# because i need to define a special Tile
# decorated by Door behavior,
# so it seems this is not a good solution :/
x += 1
tileLine.append(obj)
x = 0
y += 1
tileMap.append(tileLine)
return tileMap
一些信息的更新:
感谢@User和@Hyperborreus的回答,你是对的,我在这里简化了我的例子,在我的代码中,我有两层:
Tile
不动的,- 以及
GameObjects
可以移动、攻击、防御和许多其他功能,composition
就像本教程中使用的一样
使用pygame
,我使用函数显示我的所有Tiles
对象。draw_tile()
所以在这一点上,我需要一个Door
和Tile
类之间的链接,以便稍后为玩家正确计算 fov,因为Door
我的角色有行为并限制了我的角色的视野(属性被阻止或 fovState)。在那之后,我gameObject
在这些已经绘制的Tile
表面上绘制了所有的 。Door 是仅特定于 Tile 的计算的一部分,以及 roguelike 中的其他东西,所以这解释了为什么我定义了Door
我希望的 like。
所以可能你对游戏定义字典的提议是正确的,我需要改变我实例化对象的方式,门/瓷砖的 oop 定义是一样的,但是当我阅读包含项目、门和的初始字符串映射时静态对象,我将gameObject
实例化和Tile
实例化分开..
字典在字符串列表中定义的 rogueLike 映射上实例化元素的想法基于此处建立的想法:https ://bitbucket.org/BigYellowCactus/dropout/
也许这段代码的创建者@dominic-kexel 也可以帮助我们解决这一点?