def __init__(self, position: (float, float), game_system: GameSystem, game_info: GameInfo, dungeon: Dungeon): super().__init__(position) self.__dungeon = dungeon self.__game_system = game_system self.__game_info = game_info self.__mover = Mover() self.__anime_frame = 0 self.__pre_direction = Direction.NEWTRAL self.__next_position: (int, int) = None self.__character_chip = CharacterChip((16, 16), (16 * 4, 16 * 4), direction_pattern_num=4) self.__direction = 0 self.__damage_view_time = 0 self.__stats = self.__get_default_stats()
def __init__(self, position: (int, int), game_system: GameSystem, game_info: GameInfo, dungeon: Dungeon, player: Player, event_map: Matrix): super().__init__(position) self.__dungeon = dungeon self.__event_map = event_map self.__player = player self.__game_system = game_system self.__game_info = game_info self.__mover = Mover() self.__anime_frame = 0 self.__direction = Direction.NEWTRAL self.__next_position: (int, int) = None self.__character_chip = CharacterChip( (16, 16), (16*10, 16*10), direction_pattern_num=1 ) self.__anime_frame = 0 floor = game_info.floor start_size = 3 max_size = math.floor(floor / 3) search_size = start_size if start_size < max_size: search_size = random.randint(start_size, max_size) self.__search_size = search_size max_enemy_type = math.ceil(floor / 3) if max_enemy_type > self.__MAX_ENEMY_TYPE -1: max_enemy_type = self.__MAX_ENEMY_TYPE -1 self.type = random.randint(0, max_enemy_type) self.__stats = self.__get_default_stats() self.__debug_text = f'{self.__stats.max_hp}' self.__character_chip.set_character_no(self.type) self.__damage_view_time = 0
class Enemy(Event): __IMAGE = "resource/image/enemy.png" __MAX_ENEMY_TYPE = 10 @property def stats(self) -> Stats: return self.__stats @property def next_position(self) -> (int, int): return self.__next_position def __init__( self, position: (int, int), game_system: GameSystem, game_info: GameInfo, dungeon: Dungeon, player: Player, event_map: Matrix, ): super().__init__(position) self.__dungeon = dungeon self.__event_map = event_map self.__player = player self.__game_system = game_system self.__game_info = game_info self.__mover = Mover() self.__anime_frame = 0 self.__direction = Direction.NEWTRAL self.__next_position: (int, int) = None self.__character_chip = CharacterChip((16, 16), (16 * 10, 16 * 10), direction_pattern_num=1) self.__anime_frame = 0 floor = game_info.floor start_size = 3 max_size = math.floor(floor / 3) search_size = start_size if start_size < max_size: search_size = random.randint(start_size, max_size) self.__search_size = search_size max_enemy_type = math.ceil(floor / 3) if max_enemy_type > self.__MAX_ENEMY_TYPE - 1: max_enemy_type = self.__MAX_ENEMY_TYPE - 1 self.type = random.randint(0, max_enemy_type) self.__stats = self.__get_default_stats() self.__debug_text = "{}".format(self.__stats.max_hp) self.__character_chip.set_character_no(self.type) self.__damage_view_time = 0 def __get_default_stats(self) -> Stats: floor = self.__game_info.floor min_level = math.ceil(floor / 2) level = random.randint(min_level, floor) max_hp = 60 * \ (self.type + math.ceil(level / 2)) + \ (level - 1) * 10 strength = math.ceil(max_hp / 8) return Stats(level=level, max_hp=max_hp, strength=strength) def __can_move(self, position: (int, int)) -> bool: event_map = self.__event_map floor_map = self.__dungeon.floor_map if not floor_map.is_in(position): return False y, x = position if floor_map[y, x] == FloorType.WALL: return False if event_map[y, x] is not None: return False if self.__player.map_coordinate == position: return False return True def __get_next_position(self) -> (int, int): reach_y, reach_x = self.__get_player_reach() y, x = self.map_coordinate if abs(reach_y) <= self.__search_size \ and abs(reach_x) <= self.__search_size: param = (0, 0) if abs(reach_x) > abs(reach_y): param = (y, x + (numpy.sign(reach_x) * -1)) else: param = (y + (numpy.sign(reach_y) * -1), x) return param move = random.choice([0, 1]) new_x = int(x) new_y = int(y) if move == 0: x = new_x + random.choice([-1, 1]) else: y = new_y + random.choice([-1, 1]) return (y, x) def __get_player_reach(self) -> (int, int): player_y, player_x = self.__player.map_coordinate y, x = self.map_coordinate return (y - player_y, x - player_x) def battle(self): damage = self.__player.stats.strength +random.randint(1, math.floor(self.__player.stats.level * 1.2) + 5) self.stats.damage(damage) self.__damage_view_time = 10 def get_item(self) -> Optional[Item]: if random.random() < 0.8: return None item_type = random.choice([ Item.Type.SA_ADD_20, Item.Type.SA_ADD_20, Item.Type.SA_ADD_20, Item.Type.SA_ADD_20, Item.Type.SA_ADD_100, ]) return Item(item_type) def ready_move(self) -> bool: next_position = self.__get_next_position() if not self.__can_move(next_position): return False self.__next_position = next_position self.__mover.ready() y = next_position[0] - self.map_coordinate[0] x = next_position[1] - self.map_coordinate[1] self.__direction = (y, x) return True def __do_move(self): self.__anime_frame += 1 y, x = self.__direction value = self.__mover.get_next_plan() position = (self.y + float(y) * value, self.x + float(x) * value) self.set_position(position) if not self.__mover.have_plan(): self.__moved() def __moved(self): self.set_position(self.__next_position) self.__next_position = None def move(self): if self.__next_position is None: return self.__do_move() def __draw_bar(self, position: (int, int)): game_system = self.__game_system width = self.width - 2 height = 4 y_adjust = 4 border_size = 1 x = position[0] + 1 y = position[1] - (y_adjust + height) max_width = width - border_size * 2 hp = math.ceil(self.stats.hp / self.stats.max_hp * max_width) game_system.add_draw_object(Rect((x, y), (width, height), Color.WHITE)) game_system.add_draw_object( Rect((x + border_size, y + border_size), (max_width, height - border_size * 2), Color.RED)) game_system.add_draw_object( Rect((x + border_size, y + border_size), (hp, height - border_size * 2), Color.GREEN)) def __draw_level(self, position: (int, int)): game_system = self.__game_system x = position[0] y = position[1] + self.height - 8 text = str(self.stats.level) if DebugManager.is_debug: text += " " + self.__debug_text text1 = Text(text, (x, y), Color.RED, font_size=Text.FontSize.SS, is_absolute_position=False) game_system.add_draw_object(text1) def __get_animation_image(self) -> Image: file_path = self.__IMAGE rect = self.__character_chip.get_draw_rect( pattern=math.ceil(self.__anime_frame / 2)) return Image(file_path, area_rect=rect) def __draw_damage(self, position: (int, int)): game_system = self.__game_system adjust = self.__damage_view_time x = position[0] y = position[1] + self.height - 48 + adjust text = Text(str(self.stats.pre_damage), (x, y), Color.WHITE, font_size=Text.FontSize.NORMAL, is_absolute_position=False) game_system.add_draw_object(text) def draw(self): self.__anime_frame += 1 position = self.__game_info.convert_map_to_display((self.x, self.y)) image = self.__get_animation_image() image.set_position(position) self.__game_system.add_draw_object(image) self.__draw_level(position) self.__draw_bar(position) if self.__damage_view_time > 0: self.__damage_view_time -= 1 self.__draw_damage(position)
class Player(Event): class CharacterType: NORMAL = 0 DIE = 1 __IMAGE = 'resource/image/player.png' @property def stats(self) -> Stats: return self.__stats @property def next_position(self) -> (int, int): return self.__next_position def __init__(self, position: (float, float), game_system: GameSystem, game_info: GameInfo, dungeon: Dungeon): super().__init__(position) self.__dungeon = dungeon self.__game_system = game_system self.__game_info = game_info self.__mover = Mover() self.__anime_frame = 0 self.__pre_direction = Direction.NEWTRAL self.__next_position: (int, int) = None self.__character_chip = CharacterChip((16, 16), (16 * 4, 16 * 4), direction_pattern_num=4) self.__direction = 0 self.__damage_view_time = 0 self.__stats = self.__get_default_stats() def __get_default_stats(self) -> Stats: return Stats(level=1, max_hp=300, strength=100, satiation=300, potion=0, bom=0) def reset_stats(self): self.__stats = self.__get_default_stats() if DebugManager.is_debug: for _ in range(1, DebugManager.level): self.stats.level_up() self.stats.add_potion(DebugManager.potion) self.stats.add_bom(DebugManager.bom) def add_item(self, item: Item): item_type = item.item_type if item_type == Item.Type.POTION: self.stats.add_potion(1) return if item_type == Item.Type.BOM: self.stats.add_bom(1) return if item_type == Item.Type.SA_SPOILED: self.stats.set_satiation(int(self.stats.satiation / 2)) return if item_type == Item.Type.SA_ADD_20: self.__stats.add_satiation(20) return if item_type == Item.Type.SA_ADD_100: self.__stats.add_satiation(100) return def setup_start_position(self): floor_map = self.__dungeon.floor_map height, width = floor_map.shape while True: y = random.randint(3, height - 4) x = random.randint(3, width - 4) self.set_position((y, x)) if floor_map[y, x] == FloorType.FLOOR: break self.__direction = Direction.DOWN def set_character_type(self, _type: int): self.__character_chip.set_character_no(_type) def use_item(self, item: Item): if item.item_type == Item.Type.POTION: self.__stats.add_hp(500) self.__stats.add_potion(-1) if item.item_type == Item.Type.BOM: self.__stats.add_bom(-1) def __can_move(self, direction: (int, int)) -> bool: if direction == Direction.NEWTRAL: return False next_position = self.__get_next_position(direction) floor_map = self.__dungeon.floor_map if not floor_map.is_in(next_position): return False if floor_map[next_position] == FloorType.WALL: return False return True def __get_direction_no(self) -> int: order = Direction.get_order(self.__direction) if order == -1: order = 2 return order def __get_next_position(self, direction: (int, int)) -> (int, int): y, x = direction next_position = (self.map_coordinate[0] + y, self.map_coordinate[1] + x) return next_position def ready_move(self, direction: (int, int)) -> bool: if not self.__can_move(direction): return False next_position = self.__get_next_position(direction) self.__next_position = next_position self.__direction = direction self.__stats.hungry() self.__pre_direction = direction self.__mover.ready() return True def __get_animation_image(self) -> Image: file_path = self.__IMAGE rect = self.__character_chip.get_draw_rect(self.__get_direction_no(), self.__anime_frame) return Image(file_path, area_rect=rect) def __do_move(self): self.__anime_frame += 1 y, x = self.__direction value = self.__mover.get_next_plan() position = (self.y + float(y) * value, self.x + float(x) * value) self.set_position(position) if not self.__mover.have_plan(): self.__moved() def __moved(self): self.set_position(self.__next_position) self.__next_position = None def battle(self, target_enemy: object): from model.event.enemy import Enemy enemy: Enemy = target_enemy damage = enemy.stats.strength + random.randint(1, enemy.stats.level + 5) self.__stats.damage(damage) self.__damage_view_time = 10 def back(self): y, x = self.__pre_direction self.add_position((y * -1, x * -1)) def is_moving(self) -> bool: return self.__next_position is not None def is_level_up(self, target_enemy: object) -> bool: if self.stats.is_max_level(): return False from model.event.enemy import Enemy enemy: Enemy = target_enemy return random.randint(0, enemy.stats.max_hp) > random.randint( 0, self.stats.max_hp) def set_direction(self, direction: int): self.__direction = direction def move(self): if self.__next_position is None: return self.__do_move() def __draw_damage(self, position: (int, int)): game_system = self.__game_system adjust = self.__damage_view_time x = position[0] y = position[1] + self.height - 16 + adjust text = Text(str(self.stats.pre_damage), (x, y), Color.YELLOW, font_size=Text.FontSize.NORMAL, is_absolute_position=False) game_system.add_draw_object(text) def draw(self): position = self.__game_info.convert_map_to_display((self.x, self.y)) image = self.__get_animation_image() image.set_position(position) self.__game_system.add_draw_object(image) if self.__damage_view_time > 0: self.__damage_view_time -= 1 self.__draw_damage(position)