我(重新)搜索了很多关于这个问题的信息,但我没有设法找到合适的答案/解决方案,尽管许多科目都是关于类似的问题。
我制作了roguelike游戏(使用libtcodpy库),我遇到了一个问题。
我有类Object,控制对手和功能的类打开了大门。
class Object:
class Object:
#obiekty
def __init__(self, x, y, char, name, color, blocks=False, always_visible=False, remember=None, fighter=None, ai=None, item=None, equipment=None):
self.x = x
self.y = y
self.char = char
self.name = name
self.color = color
self.blocks = blocks
self.always_visible = always_visible
self.remember = remember
if self.remember:
self.remember.owner = self
self.fighter = fighter
if self.fighter:
self.fighter.owner = self
self.ai = ai
if self.ai:
self.ai.owner = self
self.item = item
if self.item:
self.item.owner = self
self.equipment = equipment
if self.equipment:
self.equipment.owner = self
self.item = Item()
self.item.owner = self
def move(self, dx, dy):
#move if not blocked
if not is_blocked(self.x + dx, self.y + dy):
self.x += dx
self.y += dy
def move_shop(self, dx, dy):
#move in shops
if not is_blocked(self.x + dx, self.y + dy) and is_object(self.x + dx, self.y + dy):
self.x += dx
self.y += dy
def move_towards(self, target_x, target_y):
#move to player
dx = target_x - self.x
dy = target_y - self.y
ddx = 0
ddy = 0
if dx > 0:
ddx = 1
elif dx < 0:
ddx = -1
if dy > 0:
ddy = 1
elif dy < 0:
ddy = -1
if not is_blocked(self.x + ddx, self.y + ddy):
self.move(ddx, ddy)
elif is_blocked(self.x + ddx, self.y + ddy):
if not is_door(self.x + ddx, self.y + ddy):
if ddx != 0:
if not is_blocked(self.x + ddx, self.y):
self.move(ddx, 0)
return
if ddy != 0:
if not is_blocked(self.x, self.y + ddy):
self.move(0, ddy)
return
elif is_door(self.x + ddx, self.y + ddy):
if ddx != 0:
use_door(object)
return
elif ddy != 0:
use_door(object)
return
def distance_to(self, other):
#return distance to object
dx = other.x - self.x
dy = other.y - self.y
return math.sqrt(dx ** 2 + dy ** 2)
def distance(self, x, y):
#return distance to coords
return math.sqrt((x - self.x) ** 2 + (y - self.y) ** 2)
def send_to_back(self):
#drawning objects
global objects
objects.remove(self)
objects.insert(0, self)
def draw(self):
if (libtcod.map_is_in_fov(fov_map, self.x, self.y) or
(self.always_visible and map[self.x][self.y].explored)):
libtcod.console_set_default_foreground(con, self.color)
libtcod.console_put_char(con, self.x, self.y, self.char, libtcod.BKGND_NONE)
def clear(self):
#erase
if libtcod.map_is_in_fov(fov_map, self.x, self.y):
libtcod.console_put_char_ex(con, self.x, self.y, '.', libtcod.darker_yellow, libtcod.black)
简单的&#39; ai&#39;独特的npc类:
class ImpNPC1_2:
global friendly_villages, hostile_villages, hostile_npc
memory_x = None
memory_y = None
def take_turn(self):
#monsters turn
monster = self.owner
if '2npc_1c' not in hostile_npc:
if '1st_city' in friendly_villages:
if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
self.owner.move_shop(libtcod.random_get_int(0, -1, 1), libtcod.random_get_int(0, -1, 1))
if '1st_city' in hostile_villages:
if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
self.memory_x = player.x
self.memory_y = player.y
if monster.distance_to(player) >= 2:
monster.move_towards(player.x, player.y)
elif player.fighter.hp > 0:
monster.fighter.attack(player)
elif self.memory_x != None and self.memory_y != None: #simple fake-memory
monster.move_towards(self.memory_x, self.memory_y)
if monster.x == self.memory_x and monster.y == self.memory_y or libtcod.random_get_int(0, 0, 100) > AI_INTEREST:
self.memory_x = None
self.memory_y = None
else:
while True:
x = libtcod.random_get_int(0, monster.x - 20, monster.x + 20)
y = libtcod.random_get_int(0, monster.y - 20, monster.y + 20)
if can_walk_between(monster.x, monster.y, x, y): break
self.memory_x = x
self.memory_y = y
if '2npc_1c' in hostile_npc:
if libtcod.map_is_in_fov(fov_map, monster.x, monster.y):
self.memory_x = player.x
self.memory_y = player.y
if monster.distance_to(player) >= 2:
monster.move_towards(player.x, player.y)
elif player.fighter.hp > 0:
monster.fighter.attack(player)
elif self.memory_x != None and self.memory_y != None:
monster.move_towards(self.memory_x, self.memory_y)
if monster.x == self.memory_x and monster.y == self.memory_y or libtcod.random_get_int(0, 0, 100) > AI_INTEREST:
self.memory_x = None
self.memory_y = None
else:
while True:
x = libtcod.random_get_int(0, monster.x - 20, monster.x + 20)
y = libtcod.random_get_int(0, monster.y - 20, monster.y + 20)
if can_walk_between(monster.x, monster.y, x, y): break
self.memory_x = x
self.memory_y = y
(是的,我知道这是重复的,但我会在hostile_village中指定npc的行为。)
功能use_door:
#DRZWI
def use_door(object):
if 'locked' in object.name:
message('The door is locked.', libtcod.white)
return
if 'closed' in object.name:
map[object.x][object.y].blocked = False
map[object.x][object.y].block_sight = False
map[object.x][object.y].it_is_door = False
object.blocks = False
object.char = '/'
object.name = 'open door'
fov_recompute = True
for obj in objects:
if 'closed' in obj.name and obj.x == object.x + 1 and obj.y == object.y:
return
if 'closed' in obj.name and obj.x == object.x - 1 and obj.y == object.y:
return
if 'closed' in obj.name and obj.x == object.x and obj.y == object.y + 1:
return
if 'closed' in obj.name and obj.x == object.x and obj.y == object.y - 1:
return
initialize_fov()
return
if 'open' in object.name:
map[object.x][object.y].blocked = True
map[object.x][object.y].block_sight = True
map[object.x][object.y].it_is_door = True
object.blocks = True
object.char = '+'
object.name = 'closed door'
fov_recompute = True
for obj in objects:
if 'open' in obj.name and obj.x == object.x + 1 and obj.y == object.y:
return
if 'open' in obj.name and obj.x == object.x - 1 and obj.y == object.y:
return
if 'open' in obj.name and obj.x == object.x and obj.y == object.y + 1:
return
if 'open' in obj.name and obj.x == object.x and obj.y == object.y - 1:
return
initialize_fov()
return
其他代码片段(我认为这可能对定位问题有用):
def is_blocked(x, y):
#check blocktiles
if map[x][y].blocked:
return True
for object in objects:
if object.blocks and object.x == x and object.y == y:
return True
return False
def is_object(x, y):
#check objects
if map[x][y].it_is_object:
return True
for object in objects:
if object.blocks and object.x == x and object.y == y:
return True
return False
def is_door(x, y):
#check doors
if map[x][y].it_is_door:
return True
for object in objects:
if object.blocks and object.x == x and object.y == y:
return True
return False
###ANOTHER_PIECE_OF_CODE
def make_1st_city():
global map
global objects
global village
global upstairs
global downstairs
objects = [player]
player.x = 3
player.y = 20
map = [ [ Tile(True) for y in range(MAP_HEIGHT) ] for x in range(MAP_WIDTH) ]
smap = ['################################################################################',
'#GGHHGGGHHGGGGHGGHGHGGGHGGHGGHHGGHGHGGHHGGHGGHGHGGGHGHHHGGHGGGHHGGGHHGGHGHGHGHG#',
'#G1111111111111111111111111111111111111111111111111111111111111111111111111111G#',
'#H1676767676767676767676111111111111111111111111111111122222222222221111111111G#',
'#G16767676767676767676761111111111111111111111111111111KJJJJJJJJJJJ21111111111H#',
'#G167676767676767676767611222222K2222222K222221111111113JJJJJJJJJJJ21111111111G#',
'#H1676767676767676767676112JJJJJJJJJJJJJJJJJJ2111111111KJJJJJJJJJJJ21111111111H#',
'#G1676767676767676767676112JJJJJJJJJJJJJJJJJJ211111111122222222222221111111111G#',
'#H167676767676767676767611KJJJJJJJJJJJJJJJJJJK11111111111111111111111111111111G#',
'#H1676767676767676767676112JJJJJJJJJJJJJJJJJJ211111111111111111111111111111111G#',
'#G16767676767676767676761122K2222K232K22222K2211111111111111111111111111111111H#',
'#G1111111111111111111111111111111111111111111111111111111111111111111111111111H#',
'#G1111111111111111111111111111111111111111111111111111111111111111111111111111G#',
'#H1111111111111111111111111111111111111111111111111111222222222222222211111111H#',
'#H11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111G#',
'#G11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111G#',
'#H11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111H#',
'#G11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111H#',
'#G11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111H#',
'#G111111111112222K222K232K222K2222111111111111111111112JJJJJJJJJJJJJJ211111111H#',
'#G111111111112JJJJJJJJJJJJJJJJJJJ2111111111111111111112JJJJJJJJJJJJJJ211111111G#',
'#H11111111111KJJJJJJJJJJJJJJJJJJJK111111111111111111112JJJJJJJJJJJJJJ211111111G#',
'#H111111111112JJJJJJJJJJJJJJJJJJJ2111111111111111111112JJJJJJJJJJJJJJ211111111H#',
'#H111111111112JJJJJJJJJJJJJJJJJJJ2111118181111111111113JJJJJJJJJJJJJJ211111111G#',
'#G111111111112JJJJJJJJJJJJJJJJJJJ2111111911111111111112JJJJJJJJJJJJJJ211111111G#',
'#G11111111111KJJJJJJJJJJJJJJJJJJJK111118181111111111112JJJJJJJJJJJJJJ211111111H#',
'#H111111111112JJJJJJJJJJJJJJJJJJJ2111111111111111111112JJJJJJJJJJJJJJ211111111G#',
'#H11111111111222222222222222222222111111111111111111112JJJJJJJJJJJJJJ211111111H#',
'#H11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111G#',
'#H11111111111111111111111111111111111111111111111111112JJJJJJJJJJJJJJ211111111H#',
'#G11111111111232232232232232232211111111111111111111112JJJJJJJJJJJJJJ211111111G#',
'#G111111111112JJ2JJ2JJ2JJ2JJ2JJ211111111111111111111112JJJJJJJJJJJJJJ211111111G#',
'#H111111111112JJ2JJ2JJ2JJ2JJ2JJ211111111111111111111112JJJJJJJJJJJJJJ211111111H#',
'#G6776711111122222222222222222221111111111111111111111222222222222222211111111G#',
'#G6677666711111111111116676676766667111111111111111111116777676711111111111111H#',
'#54454667676777766766767745455444667667666761111166776677456676767611111111111H#',
'#41145544776745454544677451111144446667674466677677676745444545676676111111111H#',
'#41111114554541111114454511111111145664455444547776764541114444454676776711111G#',
'#51111111111111111111111111111111114444111111445544454411111144544567676767677H#',
'#41111111111111111111111111111111111111111111111111111111111111444445545666766H#',
'#41111111111111111111111111111111111111111111111111111111111111111555554545455G#',
'#GGGHHGHHHHHGGGGHGGHGHGGGHGHGGHGHGGHGHGGHGHGGGHGGGGHGHHGGGHGHGGHGHGHHGGHGHGGHGG#',
'################################################################################',]
MAP_HEIGHT1 = len(smap)
MAP_WIDTH1 = len(smap[0])
map = [ [ Tile(True) for y in range(MAP_HEIGHT) ] for x in range(MAP_WIDTH) ]
for y in range(MAP_HEIGHT1):
for x in range(MAP_WIDTH1):
if smap[y][x] != '#':
map[x][y] = Tile(False)
if smap[y][x] == '#':
map[x][y] = Tile(True)
if smap[y][x] == '1':
map[x][y] = Tile(False)
if smap[y][x] == '2':
wall = Object(x, y, '#', 'wall', libtcod.darker_gray, always_visible=True)
objects.append(wall)
map[x][y].blocked = True
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == '3':
door = Object(x, y, '+', 'closed door', libtcod.darkest_flame, always_visible=True)
objects.append(door)
map[x][y].blocked = True
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = True
if smap[y][x] == '4':
mountain1 = Object(x, y, '^', 'mountain', libtcod.dark_gray, always_visible=True)
objects.append(mountain1)
map[x][y].blocked = True
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == '5':
mountain2 = Object(x, y, '^', 'mountain', libtcod.white, always_visible=True)
objects.append(mountain2)
map[x][y].blocked = True
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == '6':
long_grass1 = Object(x, y, ';', 'long grass', libtcod.desaturated_yellow, always_visible=True)
objects.append(long_grass1)
map[x][y].blocked = False
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == '7':
long_grass2 = Object(x, y, ';', 'long grass', libtcod.desaturated_chartreuse, always_visible=True)
objects.append(long_grass2)
map[x][y].blocked = False
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == '8':
tree = Object(x, y, 'T', 'tree', libtcod.dark_green, always_visible=True)
objects.append(tree)
map[x][y].blocked = True
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == '9':
tree2 = Object(x, y, '"', 'tree', libtcod.darker_orange, always_visible=True)
objects.append(tree2)
map[x][y].blocked = True
map[x][y].block_sight = False
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == 'G':
grass4 = Object(x, y, ',', 'grass', libtcod.darker_orange, always_visible=True)
objects.append(grass4)
map[x][y].blocked = True
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == 'H':
grass6 = Object(x, y, ';', 'long grass', libtcod.darkest_orange, always_visible=True)
objects.append(grass6)
map[x][y].blocked = True
map[x][y].block_sight = True
map[x][y].it_is_object = False
map[x][y].it_is_door = False
if smap[y][x] == 'J':
floor = Object(x, y, '.', 'floor', libtcod.darkest_orange, always_visible=True)
objects.append(floor)
map[x][y].blocked = False
map[x][y].block_sight = False
map[x][y].it_is_object = True
map[x][y].it_is_door = False
if smap[y][x] == 'K':
window = Object(x, y, '.', 'window', libtcod.lightest_sky, always_visible=True)
objects.append(window)
map[x][y].blocked = True
map[x][y].block_sight = False
map[x][y].it_is_object = False
map[x][y].it_is_door = False
npc = Object(32, 7, 't', '1st npc 1st city', libtcod.white, blocks=True, always_visible=False, ai=ImpNPC1_1())
objects.append(npc)
npc = Object(60, 4, 't', '2nd npc 1st city', libtcod.white, blocks=True, always_visible=False, ai=ImpNPC1_2())
objects.append(npc)
npc = Object(27, 22, 't', '3rd npc 1st city', libtcod.white, blocks=True, always_visible=False, ai=ImpNPC1_1())
objects.append(npc)
npc = Object(60, 22, 't', '4th npc 1st city', libtcod.white, blocks=True, always_visible=False, ai=ImpNPC1_1())
objects.append(npc)
upstairs = Object(3, 20, '<', 'stairs', libtcod.white, always_visible=True)
objects.append(upstairs)
upstairs.send_to_back()
downstairs = Object(30, 41, '^', 'mountain', libtcod.white, always_visible=False)
objects.append(downstairs)
问题是什么?玩家和计算机使用相同的打开门的机制。玩家可以打开门,没有问题,错误和崩溃。当计算机试图打开一扇门时,应用程序崩溃。
回溯:
Traceback (most recent call last):
File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 13441, in <module>
main_menu()
File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 13422, in main_menu
play_game()
File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 13404, in play_game
object.ai.take_turn()
File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 633, in take_turn
monster.move_towards(player.x, player.y)
File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 252, in move_towards
use_door(object)
File "D:/progr/python/ide/pycharm/proj/humfall/#ASCII/hf_t2.py", line 11272, in use_door
if 'locked' in object.name:
AttributeError: type object 'object' has no attribute 'name'
24 bits font.
key color : 0 0 0
24bits greyscale font. converting to 32bits
我知道打电话给班级&#39;对象&#39;很不幸,但是如果我改变了,那就用Thing替换它,引用是相同的:只有&#34; AttributeError:类型对象&#39;对象&#39;没有属性&#39; name&#39; &#34;更改为&#34; AttributeError:class Thing没有属性&#39; name&#39; &#34;
答案 0 :(得分:1)
在move_towards
功能中:
elif is_door(self.x + ddx, self.y + ddy):
if ddx != 0:
use_door(object)
return
elif ddy != 0:
use_door(object)
return
看起来您希望use_door
的参数成为坐标self.x + ddx, self.y + ddy
处的对象,但这不是您在此处传递的内容。您只是传递了内置的object
类,它与您定义的Object
类无关。我无法从您的代码段中判断这是否可行,但请尝试从map
获取对象。
elif is_door(self.x + ddx, self.y + ddy):
if ddx != 0:
use_door(map[self.x + ddx][self.y + ddy])
return
elif ddy != 0:
use_door(map[self.x + ddx][self.y + ddy])
return