Я разрабатываю RogueLike на python, и я стараюсь изо всех сил использовать ООП и свои небольшие знания, чтобы создать курс python для студентов.
mapRogue = ['~~~~~~~~~~',
'~~~~.....Y',
'YYYYY+YYYY',
'YYYY....YY']
Я хочу преобразовать эту карту строк в двумерный список, содержащий объект, определяющий характер моей плитки в 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 с использованием композиции
Я подозреваю, что есть другой ответ, использующий шаблон композиции и/или стратегии, поэтому я пытаюсь украсить объект Tile поведением Door, но я заблокирован этим словарем...
На самом деле я безуспешно пробовал несколько решений, у вас есть предложение помочь мне решить эту проблему концепции, используя элегантный 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
, чтобы позже правильно вычислить поле зрения для игрока, потому что Door
имеют поведение и ограничивают обзор моего персонажа (с заблокированными атрибутами или fovState). После этого я нарисовал все gameObject
поверх этих уже нарисованных Tile
поверхностей. Дверь является частью вычислений, специфичных только для Tile и других вещей в roguelike, так что это объясняет, почему я так определяю Door
, как я надеюсь.
Так что, вероятно, вы правы с вашим предложением словаря определения игры, мне нужно изменить способ создания экземпляра объекта, определение двери/плитки oop остается прежним, но когда я читаю исходную карту строк, которая содержит элемент, дверь, а также статический объект, я разделяю экземпляр gameObject
и экземпляр Tile
..
Идея словаря для создания экземпляра элемента на карте rogueLike, определенной в списке строк, основана на идее, основанной здесь: https://bitbucket.org/BigYellowCactus/dropout/
Возможно, создатель этого кода, @dominic-kexel, также может помочь нам в этом вопросе?