From 78724ff4b29f3a9fe194400b5e644a3bf81370fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Gro=C3=9F?= Date: Mon, 19 Jun 2023 12:36:08 +0200 Subject: [PATCH] Add header rendering to text component --- src/boarhuntingsimulator.py | 6 +++-- src/location/locations.py | 3 +++ src/utils/input.py | 4 +++- src/utils/text.py | 45 +++++++++++++++++++++++++++++++++++-- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/boarhuntingsimulator.py b/src/boarhuntingsimulator.py index 6c568b0..7a5e9f2 100644 --- a/src/boarhuntingsimulator.py +++ b/src/boarhuntingsimulator.py @@ -5,6 +5,7 @@ from operator import truediv from data import MenuText as mt import utils.text as Text +from utils.text import HeaderStyle from location.locations import * from player import Player from utils.input import Menu, Option @@ -15,7 +16,7 @@ class Game: self.player = Player() #ToDo: move this out of the main file locations = { - "City": SafeZone(self, "Main city", "You find yourself in the small rural town of Mayberry. \nThe town is quaint and charming, with a population of only a few hundred people. \nIt is surrounded by a thick forest, and the only way to get here is on foot. \nThere are a few shops and businesses around."), + "City": SafeZone(self, "Mayberry", "You find yourself in the small rural town of Mayberry. \nThe town is quaint and charming, with a population of only a few hundred people. \nIt is surrounded by a thick forest, and the only way to get here is on foot. \nThere are a few shops and businesses around."), "Forest": Location(self, "the Forest", "You find yourself in a warm and lush oak forest. \nThe dense trees provide plenty of cover from the sun, and the forest floor is carpeted with a thick layer of leaves. \nYou hear the sound of birdsong all around you, and the occasional rustle of small animals in the undergrowth."), } locations["City"].connect_location(locations["Forest"]) @@ -30,9 +31,10 @@ class Game: self.quit = True def main(self): + Text.clear() + Text.print_header("Welcome", HeaderStyle.ROUND) Text.type(mt.intro_text, delay=0.01, newline_delay=1.0) while not self.quit: - print(f"\n[{self.current_location.name}]") options = [ Option("Test option", lambda: print("Test option selected\n")), Option("Test option no callback", None), diff --git a/src/location/locations.py b/src/location/locations.py index c6d4d99..49d8f04 100644 --- a/src/location/locations.py +++ b/src/location/locations.py @@ -1,5 +1,6 @@ """Generic Location""" from utils.input import Option +from utils.text import HeaderStyle import utils.text as Text import time @@ -12,10 +13,12 @@ class Location: self.game = game def look_around(self) -> None: + Text.print_header(self.name, HeaderStyle.ROUND) Text.type(f"{self.description}\n", 0.01, 0.1) time.sleep(0.5) def enter(self) -> None: + Text.print_header(self.name, HeaderStyle.ROUND) print(f"You enter {self.name}.\n") self.game.current_location = self time.sleep(0.5) diff --git a/src/utils/input.py b/src/utils/input.py index 3416899..21e3708 100644 --- a/src/utils/input.py +++ b/src/utils/input.py @@ -2,6 +2,8 @@ Utility to show a seletion menu """ import time +import utils.text as Text + class Option(object): def __init__(self, text: str, callback: callable) -> None: self.text = text @@ -25,7 +27,7 @@ class Menu(object): time.sleep(0.5) self.show() else: - print("") #Newline for better readability + Text.clear() if self.options[selected-1].callback is not None: self.options[selected-1].callback() diff --git a/src/utils/text.py b/src/utils/text.py index 8b4fc79..5978182 100644 --- a/src/utils/text.py +++ b/src/utils/text.py @@ -2,7 +2,14 @@ Utilities for text output """ -import time, sys +import time, os +from enum import IntEnum +from typing import List, Dict + +class HeaderStyle(IntEnum): + LIGHT = 0, + BOLD = 1 + ROUND = 2 def type(text: str, delay: float = 0.05, newline_delay: float = 0.0) -> None: """ Prints the given text, one character at a time, with a delay between each character. @@ -16,4 +23,38 @@ def type(text: str, delay: float = 0.05, newline_delay: float = 0.0) -> None: print(char, end="", flush=True) if (char == "\n"): time.sleep(newline_delay) - time.sleep(delay) \ No newline at end of file + time.sleep(delay) + +def clear() -> None: + os.system('cls' if os.name=='nt' else 'clear') + +def print_header(title: str, style: HeaderStyle = HeaderStyle.LIGHT, padding: int = 1, length: int = 0): + """ Prints the Title wrapped by a decoration char + + Arguments: + title: Title to be printed + style: Changes the viasual style of the header. + Light has single line wraps, bold double lines wraps + Round has single lines with round corners + length: Total length the header has to fill + """ + + #If no length is defined, use the terminal width (-2 to avoid any line breaks) + length = length if length > 0 else os.get_terminal_size()[0] - 2 + + title = f"{' ' * padding}{title}{' ' * padding}" + + characters: List[Dict[str, str]] = [ + { 'line': '─', 'tj_left': '┤', 'corner_tl': '┌', 'corner_tr': '┐', 'corner_bl': '└', 'corner_br': '┘', 'tj_right': '├'}, + { 'line': '═', 'tj_left': '╣', 'corner_tl': '╔', 'corner_tr': '╗', 'corner_bl': '╚', 'corner_br': '╝', 'tj_right': '╠'}, + { 'line': '─', 'tj_left': '┤', 'corner_tl': '╭', 'corner_tr': '╮', 'corner_bl': '╰', 'corner_br': '╯', 'tj_right': '├'}, + ] + + title_length: int = len(title) + pre_wrap_length: int = int(length / 2) - int(title_length / 2) + post_wrap_length: int = length - pre_wrap_length - title_length + + print(' ' * pre_wrap_length + characters[style]['corner_tl'] + characters[style]['line'] * title_length + characters[style]['corner_tr']) + print(f"{characters[style]['line'] * pre_wrap_length}{characters[style]['tj_left']}{title}{characters[style]['tj_right']}{characters[style]['line'] * post_wrap_length}") + print(' ' * pre_wrap_length + characters[style]['corner_bl'] + characters[style]['line'] * title_length + characters[style]['corner_br']) +