commit fb54e8fa4a64298df88baea6c4f1f1a097d1dc28 Author: Kalyax Date: Thu Nov 24 14:30:36 2022 +0100 init diff --git a/README.md b/README.md new file mode 100644 index 0000000..96b6f86 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# jeu_role + +## Informations +Uniquement fonctionnel dans un terminal qui affiche les couleurs ANSI (CMD et Powershell ne marchent pas). +
+Utilisez les flèches directionnelles pour vous déplacer, TAB et ENTRÉE pour confirmer. + +## Référence +[getkey](https://github.com/kcsaff/getkey) pour récupérer les entrées de clavier diff --git a/game/__pycache__/core.cpython-38.pyc b/game/__pycache__/core.cpython-38.pyc new file mode 100644 index 0000000..0021d27 Binary files /dev/null and b/game/__pycache__/core.cpython-38.pyc differ diff --git a/game/__pycache__/personnage.cpython-38.pyc b/game/__pycache__/personnage.cpython-38.pyc new file mode 100644 index 0000000..1378441 Binary files /dev/null and b/game/__pycache__/personnage.cpython-38.pyc differ diff --git a/game/core.py b/game/core.py new file mode 100644 index 0000000..b18b946 --- /dev/null +++ b/game/core.py @@ -0,0 +1,54 @@ +from game.personnage import * + +from graphics.layers import PopUp + +from random import randint + +class Game: + def __init__(self): + self.personnage = None + self.ennemy = None + + def late_init(self): + self.personnage = Personnage(" ", "Guerrier", "player") + self.ennemy = self.rand_ennemy() + + def rand_ennemy(self): + classes = ["Guerrier", "Magicien", "Voleur", "Elfe"] + noms = ["Bill Gates", "Dark Vador", "Gargamel", "G-Man"] + return Personnage(noms[randint(0, 3)], classes[randint(0, 3)], "OPPONENT") + + def init_personnage(self, nom, class_type): + self.personnage = Personnage(nom, class_type, "PLAYER") + + def attack(self, attacker, victim): + atk_jet = attacker.jet_attaque() + def_jet = victim.jet_defense() + if (atk_jet >= def_jet): + rand = randint(1, 8) + victim.change_pdv(rand) + else: + rand = randint(1, 4) + attacker.change_pdv(rand) + + if self.personnage.get_pdv() == 0: + for i in range(50): + PopUp(1, "Vous avez perdu! Relancez le jeu pour continuer...", True) + if self.ennemy.get_pdv() == 0: + self.ennemy = self.rand_ennemy() + + potions = "" + inv = self.personnage.inventaire + if len(inv) >= 6: + potions = f"- Pas de potion car inventaire plein\n" + else: + maxpot = 3 + if len(inv) > 3: + maxpot = 6-len(inv) + for i in range(randint(0, maxpot)): + random = randint(5, 25) + inv.append(Material.POTION) + potions += f"- Potion de 10HP\n" + + PopUp(1, f"Ennemi vaincu!\n{potions}") + self.personnage.change_exp(1) \ No newline at end of file diff --git a/game/personnage.py b/game/personnage.py new file mode 100644 index 0000000..738526f --- /dev/null +++ b/game/personnage.py @@ -0,0 +1,73 @@ +from random import randint +from graphics.layers import Sprite + +class Category: + def __init__(self, nom, __expcoef, inventaire): + self.nom = nom + self.pdv = __expcoef + self.inventaire = inventaire + +class Material: + POTION = "POTION" + EPEE = "EPEE" + BATON = "BATON" + DAGUE = "DAGUE" + ARC = "ARC" + +class Personnage: + def __init__(self, nom, cat, personnage_type): + self.nom = nom + self.__pdv = 20 + self.__exp = 1 + self.cat = cat + if cat == "Guerrier": + self.inventaire = [Material.EPEE, Material.POTION] + self.__expcoef = 10 + elif cat == "Magicien": + self.inventaire = [Material.BATON, Material.POTION] + self.__expcoef = 10 + elif cat == "Voleur": + self.inventaire = [Material.DAGUE, Material.POTION] + self.__expcoef = 3 + elif cat == "Elfe": + self.inventaire = [Material.ARC, Material.POTION] + self.__expcoef = 8 + + Sprite(3, cat, personnage_type) + + def jet_attaque(self): + damage = randint(1, 20) + self.change_exp(self.__expcoef * self.__exp) + return damage + + def jet_defense(self): + damage = randint(1, 20) + self.change_exp(self.__expcoef * self.__exp) + return damage + + def get_pdv(self): + return self.__pdv + def change_pdv(self, nb_pdv): + if self.__pdv - nb_pdv < 0: + self.__pdv = 0 + else: + self.__pdv -= nb_pdv + + def get_xp(self): + return self.__exp + def change_exp(self, nb_exp): + if nb_exp > 0: + self.__exp += nb_exp + else: + raise ValueError("nb_exp attends un nombre positif") + + def affiche_caracteristiques(self): + return (f"Nom: {self.nom}", + f"Type de classe: {self.cat}", + f"Vie: {self.__pdv}", + f"Expérience: {self.__exp}", + f"XPCOEF: {self.__expcoef}" + ) + + def affiche_inventaire(self): + return ["- "+item for item in self.inventaire] \ No newline at end of file diff --git a/game/sprites/Elfe.txt b/game/sprites/Elfe.txt new file mode 100644 index 0000000..f94ca1b --- /dev/null +++ b/game/sprites/Elfe.txt @@ -0,0 +1,16 @@ + @@@@@@& + @@@&&@&@@@@& + &@@%&@@%&@*@@@& + &@%&@@@%*,,,,@@% + &@&&*@@#,,@@@,@% + *&&**%@/*#*,,,#*/@,&* + %@@&@&&***,,,%&& + %&@@@@@#@@&%%%&#@& + &%#@&/##&%**,,,,,/%@& + ***,,,,,,,,,***%%,,,,,****%&&&@@ @% + %#&@@@@@%@((((&@@@ @ + ** (%&@@/(##%(//*#* ( + %@*/#%/&%(//*% + %*//(#% @#(/**% + @%&&&&@ @&&&&%@ + @%%###@ @###%%@ diff --git a/game/sprites/Guerrier.txt b/game/sprites/Guerrier.txt new file mode 100644 index 0000000..719b773 --- /dev/null +++ b/game/sprites/Guerrier.txt @@ -0,0 +1,14 @@ + + @/, + @/### + %#/%%&@@@%& + @@*(%##&&@@%& + /@@@@@@& &&% + &%,@@,,@@ @( + @%&@&%&&@%&@@@% + @//**@ *%%%&%%&% + .@//*/& /#% %&/ + %@ &%/ + @% @&/ + %% &@ + &%#% @% \ No newline at end of file diff --git a/game/sprites/Magicien.txt b/game/sprites/Magicien.txt new file mode 100644 index 0000000..35a67e7 --- /dev/null +++ b/game/sprites/Magicien.txt @@ -0,0 +1,16 @@ + + &&&&&& + &...*&(&& + ., .%.%%%* + ..... %%&&*(#&&####&&& + (##%%%&&%**#%&##&&#&& + ((/&&&&&&%*##&&&#%&&&#( + .& .&&&(#*&&&&#&& + @@&&&%%/@(&&&#&#//** + .@ &&&&##%@@###&% ## + &&%&&%##%%@####% + %%&&&%%@@@@&### + %&&&&&&& @@@%% + **((( *((((@ + ((### .%#%%# + (((#( .%%%%% diff --git a/game/sprites/Voleur.txt b/game/sprites/Voleur.txt new file mode 100644 index 0000000..e6fff19 --- /dev/null +++ b/game/sprites/Voleur.txt @@ -0,0 +1,16 @@ + + + + ,,, + ,,.%%%. + , ,.%%%. + ,,,..,,. + ,,..(((.,. + ,.,,.///,. + ,./(////,. + ./,,*,,,. + .*,.**,, + ,, *, + . . + + \ No newline at end of file diff --git a/getkey/__init__.py b/getkey/__init__.py new file mode 100644 index 0000000..c8f5ad7 --- /dev/null +++ b/getkey/__init__.py @@ -0,0 +1,17 @@ +from __future__ import absolute_import, print_function +import sys +from .platforms import platform, PlatformError, PlatformInvalid + +try: + __platform = platform() +except PlatformError as err: + print('Error initializing standard platform: {}'.format(err.args[0]), + file=sys.stderr) + __platform = PlatformInvalid() + +getkey = __platform.getkey +keys = __platform.keys +key = keys # alias +bang = __platform.bang + +__version__ = '0.6.5' diff --git a/getkey/__pycache__/__init__.cpython-38.pyc b/getkey/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000..e66e764 Binary files /dev/null and b/getkey/__pycache__/__init__.cpython-38.pyc differ diff --git a/getkey/__pycache__/keynames.cpython-38.pyc b/getkey/__pycache__/keynames.cpython-38.pyc new file mode 100644 index 0000000..e9b1c4e Binary files /dev/null and b/getkey/__pycache__/keynames.cpython-38.pyc differ diff --git a/getkey/__pycache__/platforms.cpython-38.pyc b/getkey/__pycache__/platforms.cpython-38.pyc new file mode 100644 index 0000000..7656e9d Binary files /dev/null and b/getkey/__pycache__/platforms.cpython-38.pyc differ diff --git a/getkey/__pycache__/unikeys.cpython-38.pyc b/getkey/__pycache__/unikeys.cpython-38.pyc new file mode 100644 index 0000000..faffe8e Binary files /dev/null and b/getkey/__pycache__/unikeys.cpython-38.pyc differ diff --git a/getkey/keynames.py b/getkey/keynames.py new file mode 100644 index 0000000..51b885b --- /dev/null +++ b/getkey/keynames.py @@ -0,0 +1,481 @@ +# Which key(s) were pressed +# What chars to print (if any) +# Keycode(s) generating event +import string +from .unikeys import UnicodeAsciiKeys + + +# These are used for the names of ctrl keys, etc. +ASCII_NAMES = { + '\t': 'tab', + + ' ': 'space', # 0x20 + '!': 'exclamation', # 0x21 + '"': 'double quote', # 0x22 + '#': 'hash', # 0x23 + '$': 'dollar', # 0x24 + '%': 'percent', # 0x25 + '&': 'ampersand', # 0x26 + '\'': 'single quote', # 0x27 + '(': 'open paren', # 0x28 + ')': 'close paren', # 0x29 + '*': 'asterisk', # 0x2a + '+': 'plus', # 0x2b + ',': 'comma', # 0x2c + '-': 'minus', # 0x2d + '.': 'period', # 0x2e + '/': 'slash', # 0x2f + + ':': 'colon', # 0x3a + ';': 'semicolon', # 0x3b + '<': 'less than', # 0x3c + '=': 'equals', # 0x3d + '>': 'greater than', # 0x3e + '?': 'question', # 0x3f + '@': 'at', # 0x40 + + '[': 'left bracket', # 0x5b + '\\': 'backslash', # 0x5c + ']': 'right bracket', # 0x5d + '^': 'caret', # 0x5e + '_': 'underscore', # 0x5f + '`': 'backtick', # 0x60 + + '{': 'left brace', # 0x7b + '|': 'pipe', # 0x7c + '}': 'right brace', # 0x7d + '~': 'tilde', # 0x7e +} + + +class UnicodeKeys(object): + # Names from ftp://ftp.unicode.org/Public/UNIDATA/NamesList.txt + NULL = chr(0x00) + START_OF_HEADING = chr(0x01) + + +class JargonKeys(object): + BANG = '!' + SHRIEK = '!' + DOUBLE_QUOTE = '"' + QUOTE = '"' + NUMBER_SIGN = '#' + SHARP = '#' + OCTOTHORPE = '#' + BUCK = '$' + CASH = '$' + STRING = '$' + MOD = '%' + GRAPES = '%' + AMPERSAND = '&' + AMP = '&' + AND_SIGN = '&' + APOSTROPHE = '\'' + PRIME = '\'' + TICK = '\'' + STAR = '*' + SPLAT = '*' + GLOB = '*' + ADD = '+' + + +class IntercalKeys(object): + SPOT = '.' + TWO_SPOT = ':' + TAIL = ',' + HYBRID = ';' + MESH = '#' + HALF_MESH = '=' + SPARK = '\'' + BACKSPARK = '`' + WOW = '!' + WHAT = '?' + RABBIT_EARS = '"' + # RABBIT is `"` over `.` + SPIKE = '|' + DOUBLE_OH_SEVEN = '%' + WORM = '-' + ANGLE = '<' + RIGHT_ANGLE = '>' + WAX = '(' + WANE = ')' + U_TURN = '[' + U_TURN_BACK = ']' + EMBRACE = '{' + BRACELET = '}' + SPLAT = '*' + AMPERSAND = '&' + V = 'V' + BOOK = 'V' + # BOOKWORM is `-` over `V` + BIG_MONEY = '$' + # CHANGE is cent sign + SQUIGGLE = '~' + FLAT_WORM = '_' + # OVERLINE is line on top + INTERSECTION = '+' + SLAT = '/' + BACKSLAT = '\\' + WHIRLPOOL = '@' + # HOOKWORK is logical NOT symbol + SHARK = '^' + SHARKFIN = '^' + # BLOTCH is several characters smashed on top of each other + + +class VT100StandardModeKeys(object): + # http://www.braun-home.net/michael/mbedit/info/misc/VT100_commands.htm + # http://www.ccs.neu.edu/research/gpc/MSim/vona/terminal/VT100_Escape_Codes.html + F1 = '\x1bOP' + F2 = '\x1bOQ' + F3 = '\x1bOR' + F4 = '\x1bOS' + + UP = '\x1b[A' + DOWN = '\x1b[B' + RIGHT = '\x1b[C' + LEFT = '\x1b[D' + + +class VT100ApplicationsModeKeys(object): + F1 = '\x1bOP' + F2 = '\x1bOQ' + F3 = '\x1bOR' + F4 = '\x1bOS' + + UP = '\x1bOA' + DOWN = '\x1bOB' + RIGHT = '\x1bOC' + LEFT = '\x1bOD' + + KEYPAD_0 = '\x1bOp' + KEYPAD_1 = '\x1bOq' + KEYPAD_2 = '\x1bOr' + KEYPAD_3 = '\x1bOs' + KEYPAD_4 = '\x1bOt' + KEYPAD_5 = '\x1bOu' + KEYPAD_6 = '\x1bOv' + KEYPAD_7 = '\x1bOw' + KEYPAD_8 = '\x1bOx' + KEYPAD_9 = '\x1bOy' + KEYPAD_MINUS = '\x1bOm' + KEYPAD_COMMA = '\x1bOl' + KEYPAD_PERIOD = '\x1bOn' + KEYPAD_ENTER = '\x1bOM' + + +class VT220Keys(object): + # F1-F5 didn't exist historically, but were added by later emulators + F1 = '\x1b[11~' + F2 = '\x1b[12~' + F3 = '\x1b[13~' + F4 = '\x1b[14~' + F5 = '\x1b[15~' + + # Historical keys + F6 = '\x1b[17~' + F7 = '\x1b[18~' + F8 = '\x1b[19~' + F9 = '\x1b[20~' + F10 = '\x1b[21~' + F11 = '\x1b[23~' + F12 = '\x1b[24~' + + # F13+ and key combinations to enter them are of limited usefulness today + + +class UnixKeys(object): + # Keys found experimentally, of unknown provenance + ESC = '\x1b' + + HOME = '\x1b[H' + END = '\x1b[F' + PAGE_UP = '\x1b[5' + PAGE_DOWN = '\x1b[6' + + ENTER = '\n' + CR = '\r' + BACKSPACE = '\x7f' + + SPACE = ' ' + + INSERT = '\x1b[2~' + DELETE = '\x1b[3~' + + +class AlternativeUnixFunctionKeys(object): + # Unsure origin: alternate V220 mode? + F1 = '\x1bO11~' + F2 = '\x1bO12~' + F3 = '\x1bO13~' + F4 = '\x1bO14~' + F5 = '\x1bO15~' + F6 = '\x1bO17~' + F7 = '\x1bO18~' + F8 = '\x1bO19~' + F9 = '\x1bO20~' + F10 = '\x1bO21~' + F11 = '\x1bO23~' + F12 = '\x1bO24~' + + +class WindowsKeys(object): + ESC = '\x1b' + + LEFT = '\xe0K' + RIGHT = '\xe0M' + UP = '\xe0H' + DOWN = '\xe0P' + + ENTER = '\r' + BACKSPACE = '\x08' + SPACE = ' ' + + F1 = '\x00;' + F2 = '\x00<' + F3 = '\x00=' + F4 = '\x00>' + F5 = '\x00?' + F6 = '\x00@' + F7 = '\x00A' + F8 = '\x00B' + F9 = '\x00C' + F10 = '\x00D' + F11 = '\xe0\x85' + F12 = '\xe0\x86' + + INSERT = '\xe0R' + DELETE = '\xe0S' + PAGE_UP = '\xe0I' + PAGE_DOWN = '\xe0Q' + HOME = '\xe0G' + END = '\xe0O' + + CTRL_F1 = '\x00^' + CTRL_F2 = '\x00_' + CTRL_F3 = '\x00`' + CTRL_F4 = '\x00a' + CTRL_F5 = '\x00b' + CTRL_F6 = '\x00c' + CTRL_F7 = '\x00d' # Captured by something? + CTRL_F8 = '\x00e' + CTRL_F9 = '\x00f' + CTRL_F10 = '\x00g' + CTRL_F11 = '\xe0\x89' + CTRL_F12 = '\xe0\x8a' + + CTRL_HOME = '\xe0w' + CTRL_END = '\xe0u' + CTRL_INSERT = '\xe0\x92' + CTRL_DELETE = '\xe0\x93' + CTRL_PAGE_DOWN = '\xe0v' + + CTRL_2 = '\x00\x03' + CTRL_UP = '\xe0\x8d' + CTRL_DOWN = '\xe0\x91' + CTRL_LEFT = '\xe0s' + CTRL_RIGHT = '\xe0t' + + CTRL_ALT_A = '\x00\x1e' + CTRL_ALT_B = '\x000' + CTRL_ALT_C = '\x00.' + CTRL_ALT_D = '\x00 ' + CTRL_ALT_E = '\x00\x12' + CTRL_ALT_F = '\x00!' + CTRL_ALT_G = '\x00"' + CTRL_ALT_H = '\x00#' + CTRL_ALT_I = '\x00\x17' + CTRL_ALT_J = '\x00$' + CTRL_ALT_K = '\x00%' + CTRL_ALT_L = '\x00&' + CTRL_ALT_M = '\x002' + CTRL_ALT_N = '\x001' + CTRL_ALT_O = '\x00\x18' + CTRL_ALT_P = '\x00\x19' + CTRL_ALT_Q = '\x00\x10' + CTRL_ALT_R = '\x00\x13' + CTRL_ALT_S = '\x00\x1f' + CTRL_ALT_T = '\x00\x14' + CTRL_ALT_U = '\x00\x16' + CTRL_ALT_V = '\x00/' + CTRL_ALT_W = '\x00\x11' + CTRL_ALT_X = '\x00-' + CTRL_ALT_Y = '\x00\x15' + CTRL_ALT_Z = '\x00,' + CTRL_ALT_1 = '\x00x' + CTRL_ALT_2 = '\x00y' + CTRL_ALT_3 = '\x00z' + CTRL_ALT_4 = '\x00{' + CTRL_ALT_5 = '\x00|' + CTRL_ALT_6 = '\x00}' + CTRL_ALT_7 = '\x00~' + CTRL_ALT_8 = '\x00\x7f' + CTRL_ALT_9 = '\x00\x80' + CTRL_ALT_0 = '\x00\x81' + CTRL_ALT_MINUS = '\x00\x82' + CTRL_ALT_EQUALS = '\x00x83' + CTRL_ALT_BACKSPACE = '\x00\x0e' + + ALT_F1 = '\x00h' + ALT_F2 = '\x00i' + ALT_F3 = '\x00j' + ALT_F4 = '\x00k' + ALT_F5 = '\x00l' + ALT_F6 = '\x00m' + ALT_F7 = '\x00n' + ALT_F8 = '\x00o' + ALT_F9 = '\x00p' + ALT_F10 = '\x00q' + ALT_F11 = '\xe0\x8b' + ALT_F12 = '\xe0\x8c' + ALT_HOME = '\x00\x97' + ALT_END = '\x00\x9f' + ALT_INSERT = '\x00\xa2' + ALT_DELETE = '\x00\xa3' + ALT_PAGE_UP = '\x00\x99' + ALT_PAGE_DOWN = '\x00\xa1' + ALT_LEFT = '\x00\x9b' + ALT_RIGHT = '\x00\x9d' + ALT_UP = '\x00\x98' + ALT_DOWN = '\x00\xa0' + + CTRL_ALT_LEFT_BRACKET = '\x00\x1a' + CTRL_ALT_RIGHT_BRACKET = '\x00\x1b' + CTRL_ALT_SEMICOLON = '\x00\'' + CTRL_ALT_SINGLE_QUOTE = '\x00(' + CTRL_ALT_ENTER = '\x00\x1c' + CTRL_ALT_SLASH = '\x005' + CTRL_ALT_PERIOD = '\x004' + CTRL_ALT_COMMA = '\x003' + + +class ControlKeys(object): + def __init__(self, format='CTRL_{}'): + for i in range(0x20): + low_char = chr(i) + high_char = chr(i + 0x40) + name = ASCII_NAMES.get(high_char, high_char).upper() + ctrl_name = format.format(name) + setattr(self, ctrl_name, low_char) + + +class AsciiKeys(object): + def __init__( + self, + lower_format='{}', upper_format='SHIFT_{}', digit_format='N{}', + ascii_names=ASCII_NAMES, + ): + for letter in string.ascii_lowercase: + name = lower_format.format(letter.upper()) + setattr(self, name, letter) + for letter in string.ascii_uppercase: + name = upper_format.format(letter.upper()) + setattr(self, name, letter) + for digit in string.digits: + name = digit_format.format(digit) + setattr(self, name, digit) + for char, name in ascii_names.items(): + name = name.upper().replace(' ', '_') + setattr(self, name, char) + + +class Keys(object): + def __init__(self, keyclasses): + self.__names = dict() # Map of codes -> names + self.__codes = dict() # Map of names -> codes + + self.__escapes = set() + + for keyclass in keyclasses: + for name in dir(keyclass): + if self._is_key_name(name): + code = getattr(keyclass, name) + self.register(name, code) + + def register(self, name, code): + if name not in self.__codes: + self.__codes[name] = code + if code not in self.__names: + self.__names[code] = name + for i in range(len(code)): + self.__escapes.add(code[:i]) + + # Update towards canonicity + while True: + canon_code = self.canon(code) + canon_canon_code = self.canon(canon_code) + if canon_code != canon_canon_code: + self.__codes[self.name(code)] = canon_canon_code + else: + break + while True: + canon_name = self.name(self.code(name)) + canon_canon_name = self.name(self.code(canon_name)) + if canon_name != canon_canon_name: + self.__names[self.code(name)] = canon_canon_name + else: + break + + @property + def escapes(self): + return self.__escapes + + @property + def names(self): + return self.__codes.keys() + + def name(self, code): + return self.__names.get(code) + + def code(self, name): + return self.__codes.get(name) + + def canon(self, code): + name = self.name(code) + return self.code(name) if name else code + + def __getattr__(self, name): + code = self.code(name) + if code is not None: + return code + else: + return self.__getattribute__(name) + + def _is_key_name(self, name): + return name == name.upper() and not name.startswith('_') + + +def _make_escapes(codes): + escapes = set() + for code in codes: + for i in range(len(code)): + escapes.add(code[:i]) + return escapes + + +unix_keys = Keys([ + VT100StandardModeKeys(), + VT100ApplicationsModeKeys(), + VT220Keys(), + UnixKeys(), + AlternativeUnixFunctionKeys(), + AsciiKeys(), + ControlKeys(), + UnicodeAsciiKeys(), + JargonKeys(), + IntercalKeys() +]) +windows_keys = Keys([ + WindowsKeys(), + AsciiKeys(), + ControlKeys(), + UnicodeAsciiKeys(), + JargonKeys(), + IntercalKeys() +]) + + +PLATFORM_KEYS = { + 'unix': unix_keys, + 'windows': windows_keys, +} diff --git a/getkey/platforms.py b/getkey/platforms.py new file mode 100644 index 0000000..3bb4345 --- /dev/null +++ b/getkey/platforms.py @@ -0,0 +1,238 @@ +# -*- coding: utf-8 -*- +# Initially taken from: +# http://code.activestate.com/recipes/134892/ +# Thanks to Danny Yoo + +from __future__ import absolute_import, print_function +from contextlib import contextmanager +import codecs +import os +import sys +from .keynames import PLATFORM_KEYS + + +class PlatformError(Exception): + pass + + +class Platform(object): + def __init__(self, keys=None, interrupts=None): + keys = keys or self.KEYS + + if isinstance(keys, str): + keys = PLATFORM_KEYS[keys] + self.key = self.keys = keys + if interrupts is None: + interrupts = self.INTERRUPTS + self.interrupts = { + self.keys.code(name): action + for name, action in interrupts.items() + } + + assert( + self.__class__.getchar != Platform.getchar or + self.__class__.getchars != Platform.getchars + ) + + def getkey(self, blocking=True): + buffer = '' + for c in self.getchars(blocking): + buffer += c + if buffer not in self.keys.escapes: + break + + keycode = self.keys.canon(buffer) + if keycode in self.interrupts: + interrupt = self.interrupts[keycode] + if isinstance(interrupt, BaseException) or \ + issubclass(interrupt, BaseException): + raise interrupt + else: + raise NotImplementedError('Unimplemented interrupt: {!r}' + .format(interrupt)) + return keycode + + def bang(self): + while True: + code = self.getkey(True) + name = self.keys.name(code) or '???' + print('{} = {!r}'.format(name, code)) + + # You MUST override at least one of the following + def getchars(self, blocking=True): + char = self.getchar(blocking) + while char: + yield char + char = self.getchar(False) + + def getchar(self, blocking=True): + for char in self.getchars(blocking): + return char + else: + return None + + +class PlatformUnix(Platform): + KEYS = 'unix' + INTERRUPTS = {'CTRL_C': KeyboardInterrupt} + + def __init__(self, keys=None, interrupts=None, + stdin=None, select=None, tty=None, termios=None): + """Make Unix Platform object. + + Arguments: + keys (Keys): Keys object to use for escapes & names. + interrupts (dict): Map of keys to interrupt actions + (Ctrl-C -> KeyboardInterrupt by default) + stdin (file descriptor): file object to use (stdin by default) + select (callable): select function (select.select by default) + tty (module): tty module + termios (module): termios module + """ + super(PlatformUnix, self).__init__(keys, interrupts) + self.stdin = stdin or sys.stdin + if not select: + from select import select + if not tty: + import tty + if not termios: + import termios + self.select = select + self.tty = tty + self.termios = termios + + try: + self.__decoded_stream = OSReadWrapper(self.stdin) + except Exception as err: + raise PlatformError('Cannot use unix platform on non-file-like stream') + + def fileno(self): + return self.__decoded_stream.fileno() + + @contextmanager + def context(self): + fd = self.fileno() + old_settings = self.termios.tcgetattr(fd) + self.tty.setcbreak(fd) + try: + yield + finally: + self.termios.tcsetattr( + fd, self.termios.TCSADRAIN, old_settings + ) + + def getchars(self, blocking=True): + """Get characters on Unix.""" + with self.context(): + if blocking: + yield self.__decoded_stream.read(1) + while self.select([self.fileno()], [], [], 0)[0]: + yield self.__decoded_stream.read(1) + + +class OSReadWrapper(object): + """Wrap os.read binary input with encoding in standard stream interface. + + We need this since os.read works more consistently on unix, but only + returns byte strings. Since the user might be typing on an international + keyboard or pasting unicode, we need to decode that. Fortunately + python's stdin has the fileno & encoding attached to it, so we can + just use that. + """ + def __init__(self, stream, encoding=None): + """Construct os.read wrapper. + + Arguments: + stream (file object): File object to read. + encoding (str): Encoding to use (gets from stream by default) + """ + self.__stream = stream + self.__fd = stream.fileno() + self.encoding = encoding or stream.encoding + self.__decoder = codecs.getincrementaldecoder(self.encoding)() + + def fileno(self): + return self.__fd + + @property + def buffer(self): + return self.__stream.buffer + + def read(self, chars): + buffer = '' + while len(buffer) < chars: + buffer += self.__decoder.decode(os.read(self.__fd, 1)) + return buffer + + +class PlatformWindows(Platform): + KEYS = 'windows' + INTERRUPTS = {'CTRL_C': KeyboardInterrupt} + + def __init__(self, keys=None, interrupts=None, msvcrt=None): + super(PlatformWindows, self).__init__(keys, interrupts) + if msvcrt is None: + import msvcrt + self.msvcrt = msvcrt + + def getchars(self, blocking=True): + """Get characters on Windows.""" + + if blocking: + yield self.msvcrt.getch() + while self.msvcrt.kbhit(): + yield self.msvcrt.getch() + + +class PlatformTest(Platform): + KEYS = 'unix' + INTERRUPTS = {} + + def __init__(self, chars='', keys=None, interrupts=None): + super(PlatformTest, self).__init__(keys, interrupts) + self.chars = chars + self.index = 0 + + def getchar(self, blocking=True): + if self.index >= len(self.chars) and not blocking: + return '' + else: + char = self.chars[self.index] + self.index += 1 + return char + + +class PlatformInvalid(Platform): + KEYS = 'unix' + INTERRUPTS = {'CTRL_C': KeyboardInterrupt} + + def getchar(self, blocking=True): + raise RuntimeError('Cannot getkey on invalid platform!') + + +def windows_or_unix(*args, **kwargs): + try: + import msvcrt + except ImportError: + return PlatformUnix(*args, **kwargs) + else: + return PlatformWindows(*args, **kwargs) + + +PLATFORMS = [ + ('linux', PlatformUnix), + ('darwin', PlatformUnix), + ('win32', PlatformWindows), + ('cygwin', windows_or_unix), +] + + +def platform(name=None, keys=None, interrupts=None): + name = name or sys.platform + for prefix, ctor in PLATFORMS: + if name.startswith(prefix): + return ctor(keys=keys, interrupts=interrupts) + else: + raise NotImplementedError('Unknown platform {!r}'.format(name)) + + diff --git a/getkey/unikeys.py b/getkey/unikeys.py new file mode 100644 index 0000000..3f0e389 --- /dev/null +++ b/getkey/unikeys.py @@ -0,0 +1,167 @@ +class UnicodeAsciiKeys(object): + NULL = '\x00' + START_OF_HEADING = '\x01' + START_OF_TEXT = '\x02' + END_OF_TEXT = '\x03' + END_OF_TRANSMISSION = '\x04' + ENQUIRY = '\x05' + ACKNOWLEDGE = '\x06' + BELL = '\x07' + BACKSPACE = '\x08' + CHARACTER_TABULATION = '\t' + HORIZONTAL_TABULATION = '\t' + TAB = '\t' + LINE_FEED = '\n' + NEW_LINE = '\n' + END_OF_LINE = '\n' + LINE_TABULATION = '\x0b' + VERTICAL_TABULATION = '\x0b' + FORM_FEED = '\x0c' + CARRIAGE_RETURN = '\r' + SHIFT_OUT = '\x0e' + SHIFT_IN = '\x0f' + DATA_LINK_ESCAPE = '\x10' + DEVICE_CONTROL_ONE = '\x11' + DEVICE_CONTROL_TWO = '\x12' + DEVICE_CONTROL_THREE = '\x13' + DEVICE_CONTROL_FOUR = '\x14' + NEGATIVE_ACKNOWLEDGE = '\x15' + SYNCHRONOUS_IDLE = '\x16' + END_OF_TRANSMISSION_BLOCK = '\x17' + CANCEL = '\x18' + END_OF_MEDIUM = '\x19' + SUBSTITUTE = '\x1a' + ESCAPE = '\x1b' + INFORMATION_SEPARATOR_FOUR = '\x1c' + FILE_SEPARATOR = '\x1c' + INFORMATION_SEPARATOR_THREE = '\x1d' + GROUP_SEPARATOR = '\x1d' + INFORMATION_SEPARATOR_TWO = '\x1e' + RECORD_SEPARATOR = '\x1e' + INFORMATION_SEPARATOR_ONE = '\x1f' + UNIT_SEPARATOR = '\x1f' + SPACE = ' ' + EXCLAMATION_MARK = '!' + FACTORIAL = '!' + BANG = '!' + QUOTATION_MARK = '"' + NUMBER_SIGN = '#' + POUND_SIGN = '#' + HASH = '#' + CROSSHATCH = '#' + OCTOTHORPE = '#' + DOLLAR_SIGN = '$' + ESCUDO = '$' + PERCENT_SIGN = '%' + AMPERSAND = '&' + APOSTROPHE = "'" + APOSTROPHE_QUOTE = "'" + APL_QUOTE = "'" + LEFT_PARENTHESIS = '(' + OPENING_PARENTHESIS = '(' + RIGHT_PARENTHESIS = ')' + CLOSING_PARENTHESIS = ')' + ASTERISK = '*' + STAR = '*' + PLUS_SIGN = '+' + COMMA = ',' + DECIMAL_SEPARATOR = ',' + HYPHEN_MINUS = '-' + HYPHEN_OR_MINUS_SIGN = '-' + FULL_STOP = '.' + PERIOD = '.' + DOT = '.' + DECIMAL_POINT = '.' + SOLIDUS = '/' + SLASH = '/' + VIRGULE = '/' + DIGIT_ZERO = '0' + DIGIT_ONE = '1' + DIGIT_TWO = '2' + DIGIT_THREE = '3' + DIGIT_FOUR = '4' + DIGIT_FIVE = '5' + DIGIT_SIX = '6' + DIGIT_SEVEN = '7' + DIGIT_EIGHT = '8' + DIGIT_NINE = '9' + COLON = ':' + SEMICOLON = ';' + LESS_THAN_SIGN = '<' + EQUALS_SIGN = '=' + GREATER_THAN_SIGN = '>' + QUESTION_MARK = '?' + COMMERCIAL_AT = '@' + AT_SIGN = '@' + LATIN_CAPITAL_LETTER_A = 'A' + LATIN_CAPITAL_LETTER_B = 'B' + LATIN_CAPITAL_LETTER_C = 'C' + LATIN_CAPITAL_LETTER_D = 'D' + LATIN_CAPITAL_LETTER_E = 'E' + LATIN_CAPITAL_LETTER_F = 'F' + LATIN_CAPITAL_LETTER_G = 'G' + LATIN_CAPITAL_LETTER_H = 'H' + LATIN_CAPITAL_LETTER_I = 'I' + LATIN_CAPITAL_LETTER_J = 'J' + LATIN_CAPITAL_LETTER_K = 'K' + LATIN_CAPITAL_LETTER_L = 'L' + LATIN_CAPITAL_LETTER_M = 'M' + LATIN_CAPITAL_LETTER_N = 'N' + LATIN_CAPITAL_LETTER_O = 'O' + LATIN_CAPITAL_LETTER_P = 'P' + LATIN_CAPITAL_LETTER_Q = 'Q' + LATIN_CAPITAL_LETTER_R = 'R' + LATIN_CAPITAL_LETTER_S = 'S' + LATIN_CAPITAL_LETTER_T = 'T' + LATIN_CAPITAL_LETTER_U = 'U' + LATIN_CAPITAL_LETTER_V = 'V' + LATIN_CAPITAL_LETTER_W = 'W' + LATIN_CAPITAL_LETTER_X = 'X' + LATIN_CAPITAL_LETTER_Y = 'Y' + LATIN_CAPITAL_LETTER_Z = 'Z' + LEFT_SQUARE_BRACKET = '[' + OPENING_SQUARE_BRACKET = '[' + REVERSE_SOLIDUS = '\\' + BACKSLASH = '\\' + RIGHT_SQUARE_BRACKET = ']' + CLOSING_SQUARE_BRACKET = ']' + CIRCUMFLEX_ACCENT = '^' + LOW_LINE = '_' + SPACING_UNDERSCORE = '_' + GRAVE_ACCENT = '`' + LATIN_SMALL_LETTER_A = 'a' + LATIN_SMALL_LETTER_B = 'b' + LATIN_SMALL_LETTER_C = 'c' + LATIN_SMALL_LETTER_D = 'd' + LATIN_SMALL_LETTER_E = 'e' + LATIN_SMALL_LETTER_F = 'f' + LATIN_SMALL_LETTER_G = 'g' + LATIN_SMALL_LETTER_H = 'h' + LATIN_SMALL_LETTER_I = 'i' + LATIN_SMALL_LETTER_J = 'j' + LATIN_SMALL_LETTER_K = 'k' + LATIN_SMALL_LETTER_L = 'l' + LATIN_SMALL_LETTER_M = 'm' + LATIN_SMALL_LETTER_N = 'n' + LATIN_SMALL_LETTER_O = 'o' + LATIN_SMALL_LETTER_P = 'p' + LATIN_SMALL_LETTER_Q = 'q' + LATIN_SMALL_LETTER_R = 'r' + LATIN_SMALL_LETTER_S = 's' + LATIN_SMALL_LETTER_T = 't' + LATIN_SMALL_LETTER_U = 'u' + LATIN_SMALL_LETTER_V = 'v' + LATIN_SMALL_LETTER_W = 'w' + LATIN_SMALL_LETTER_X = 'x' + LATIN_SMALL_LETTER_Y = 'y' + LATIN_SMALL_LETTER_Z = 'z' + LEFT_CURLY_BRACKET = '{' + OPENING_CURLY_BRACKET = '{' + LEFT_BRACE = '{' + VERTICAL_LINE = '|' + VERTICAL_BAR = '|' + RIGHT_CURLY_BRACKET = '}' + CLOSING_CURLY_BRACKET = '}' + RIGHT_BRACE = '}' + TILDE = '~' + DELETE = '\x7f' diff --git a/graphics/__pycache__/colors.cpython-38.pyc b/graphics/__pycache__/colors.cpython-38.pyc new file mode 100644 index 0000000..f316dce Binary files /dev/null and b/graphics/__pycache__/colors.cpython-38.pyc differ diff --git a/graphics/__pycache__/engine.cpython-38.pyc b/graphics/__pycache__/engine.cpython-38.pyc new file mode 100644 index 0000000..04cfc79 Binary files /dev/null and b/graphics/__pycache__/engine.cpython-38.pyc differ diff --git a/graphics/__pycache__/key_listener.cpython-38.pyc b/graphics/__pycache__/key_listener.cpython-38.pyc new file mode 100644 index 0000000..70d416e Binary files /dev/null and b/graphics/__pycache__/key_listener.cpython-38.pyc differ diff --git a/graphics/__pycache__/layers.cpython-38.pyc b/graphics/__pycache__/layers.cpython-38.pyc new file mode 100644 index 0000000..09c82bc Binary files /dev/null and b/graphics/__pycache__/layers.cpython-38.pyc differ diff --git a/graphics/colors.py b/graphics/colors.py new file mode 100644 index 0000000..6b49415 --- /dev/null +++ b/graphics/colors.py @@ -0,0 +1,44 @@ +class Colors: + RESET = '\33[0m' + BOLD = '\33[1m' + ITALIC = '\33[3m' + URL = '\33[4m' + BLINK = '\33[5m' + BLINK2 = '\33[6m' + SELECTED = '\33[7m' + + BLACK = '\33[30m' + RED = '\33[31m' + GREEN = '\33[32m' + YELLOW = '\33[33m' + BLUE = '\33[34m' + VIOLET = '\33[35m' + BEIGE = '\33[36m' + WHITE = '\33[37m' + + BLACKBG = '\33[40m' + REDBG = '\33[41m' + GREENBG = '\33[42m' + YELLOWBG = '\33[43m' + BLUEBG = '\33[44m' + VIOLETBG = '\33[45m' + BEIGEBG = '\33[46m' + WHITEBG = '\33[47m' + + GREY = '\33[90m' + RED2 = '\33[91m' + GREEN2 = '\33[92m' + YELLOW2 = '\33[93m' + BLUE2 = '\33[94m' + VIOLET2 = '\33[95m' + BEIGE2 = '\33[96m' + WHITE2 = '\33[97m' + + GREYBG = '\33[100m' + REDBG2 = '\33[101m' + GREENBG2 = '\33[102m' + YELLOWBG2 = '\33[103m' + BLUEBG2 = '\33[104m' + VIOLETBG2 = '\33[105m' + BEIGEBG2 = '\33[106m' + WHITEBG2 = '\33[107m' \ No newline at end of file diff --git a/graphics/engine.py b/graphics/engine.py new file mode 100644 index 0000000..f2bdbc5 --- /dev/null +++ b/graphics/engine.py @@ -0,0 +1,98 @@ +import os +from graphics.colors import Colors + +class Screen: + """Moteur graphique basé sur des claques""" + instance = None + + def __init__(self, game): + Screen.instance = self + + size = os.get_terminal_size() + if size.columns < 120 or size.lines < 30: + raise OSError("terminal is too small") + self.x = size.columns + self.y = size.lines - 2 + self.frame = {} + self.__layers = {} + self.handlers = [] + + game.late_init() + self.game = game + + def set_layer(self, layer): + self.__layers[layer.name] = layer + + def del_layer(self, name): + del self.__layers[name] + + def get_layer(self, name): + if not name in self.__layers.keys(): + raise ValueError("unknown key") + return self.__layers[name] + + def __combine_layers(self): + self.frame = {} + layers = sorted(self.__layers.values(), key=lambda layer: layer.z_index) + for layer in layers: + layer.draw() + self.frame.update(layer.frame) + + def draw(self): + self.__combine_layers() + buffer = "" + for y in range(self.y): + for x in range(self.x): + if (x, y) in self.frame: + buffer += self.frame[(x, y)] + else: + buffer += " " + buffer += "\n" + print("\033[H\033[J", end="") + print(buffer) + + def send_key(self, key): + """Envoie les touches reçues à tous les calques actifs""" + for layer in list(self.__layers.values()): + if layer.handle_keys == True: + layer.key_handler(key) + + +class Layer: + def __init__(self, z_index, name): + self.name = name + self.frame = {} + self.z_index = z_index + self.x = Screen.instance.x + self.y = Screen.instance.y + self.handle_keys = True + + Screen.instance.set_layer(self) + + def put_char(self, char, x, y, colors=[]): + if x > self.x or x < 0 or y > self.y or y < 0: + raise ValueError("out of range pixel") + self.frame[(x, y)] = "".join(colors) + char + Colors.RESET + + def put_string(self, string, x, y, colors=[]): + if x > self.x or x < 0 or y > self.y or y < 0: + raise ValueError("out of range pixel") + string = string.split("\n") + for string_y in range(len(string)): + for string_x in range(len(string[string_y])): + self.frame[(x+string_x, y+string_y)] = "".join(colors) + string[string_y][string_x] + Colors.RESET + + def rect(self, x1, y1, x2, y2, colors=[], template=' '): + if (x1 > self.x or x1 < 0 or y1 > self.y or y1 < 0) or (x2 > self.x or x2 < 0 or y2 > self.y or y2 < 0): + raise ValueError("out of range pixel") + if len(template) > 1: + raise ValueError("template should be 1 char long") + for x in range(x1, x2+1): + for y in range(y1, y2+1): + self.frame[(x, y)] = "".join(colors) + template + Colors.RESET + + def draw(self): + self.frame = {} + + def key_handler(self): + pass \ No newline at end of file diff --git a/graphics/key_listener.py b/graphics/key_listener.py new file mode 100644 index 0000000..45e4d4e --- /dev/null +++ b/graphics/key_listener.py @@ -0,0 +1,10 @@ +from threading import Thread +from getkey import getkey + +def __listener(screen): + while True: + key = getkey() + screen.send_key(key) + +def build_thread(screen): + return Thread(target=__listener, args=(screen,)) diff --git a/graphics/layers.py b/graphics/layers.py new file mode 100644 index 0000000..c3b6720 --- /dev/null +++ b/graphics/layers.py @@ -0,0 +1,173 @@ +from graphics.colors import Colors +from graphics.engine import Layer + +from graphics.engine import Screen + +from getkey import keys +from re import match + +class GUI(Layer): + """Calque du menu principal""" + def __init__(self, z_index): + super().__init__(z_index, "gui") + self.__current = 0 + self.__buttons = ["Attaquer", "Inventaire"] + self.__inventaire = False + self.handle_keys = False + + self.__page = 1 + + def draw(self): + super().draw() + if self.__inventaire == False: + x = 1 + for button in self.__buttons: + color = (Colors.REDBG, Colors.BLACK) if self.__buttons[self.__current] == button else (Colors.WHITEBG, Colors.BLACK) + self.put_string(button, x, self.y-10, color) + x += len(button)+1 + + stats = Screen.instance.game.personnage.affiche_caracteristiques() + for i in range(5): + self.put_string(stats[i], 1, self.y-8+i, [Colors.RED2]) + + ennemy_stats = Screen.instance.game.ennemy.affiche_caracteristiques() + for i in range(5): + self.put_string(ennemy_stats[i], self.x-(self.x-2)//3, self.y-8+i, [Colors.BLUE2]) + + else: + x = 1 + for button in self.__buttons: + color = (Colors.REDBG, Colors.BLACK) if self.__buttons[self.__current] == button else (Colors.WHITEBG, Colors.BLACK) + self.put_string(button, x, self.y-10, color) + x += len(button)+1 + + self.put_string("Votre inventaire:", 1, self.y-8, [Colors.RED2]) + stats = Screen.instance.game.personnage.affiche_inventaire() + for i in range(len(stats)): + self.put_string(stats[i], 1, self.y-7+i, [Colors.RED2]) + + return self + + def key_handler(self, key): + if key == keys.RIGHT and self.__current < len(self.__buttons)-1: + self.__current += 1 + elif key == keys.LEFT and self.__current > 0: + self.__current -= 1 + elif key == keys.ENTER: + if self.__inventaire == False: + if self.__current == 0: + attacker = Screen.instance.game.personnage + victim = Screen.instance.game.ennemy + Screen.instance.game.attack(attacker, victim) + elif self.__current == 1: + self.__inventaire = True + self.__buttons = ["Retour", "Utiliser une potion"] + else: + if self.__current == 0: + self.__inventaire = False + self.__buttons = ["Attaquer", "Inventaire"] + elif self.__current == 1: + perso = Screen.instance.game.personnage + for item in range(len(perso.inventaire)): + if perso.inventaire[item] == "POTION": + perso.change_pdv(-10) + del perso.inventaire[item] + break + + + +class StartPopUp(Layer): + """Calque du menu de lancement""" + def __init__(self, z_index): + super().__init__(z_index, "popup") + self.__classes = ["Guerrier", "Magicien", "Voleur", "Elfe"] + self.__choosen_class = 0 + self.__username = "" + self.__missing_un = False + + def draw(self): + super().draw() + #bg + self.rect(self.x//3, self.y//6, self.x*2//3, self.y//4 + self.y//3, Colors.WHITEBG) + #name + self.put_string("Nom: (A-z)", self.x//3 + 1, self.y//6 + 1, [Colors.WHITEBG, Colors.BLACK]) + self.rect(self.x//3 + 1, self.y//6 + 2, self.x*2//3 - 2, self.y//6 + 2, Colors.REDBG if self.__missing_un else Colors.BLACKBG) + self.put_string(self.__username, self.x//3 + 1, self.y//6 + 2, [Colors.WHITE, Colors.BLACKBG]) + #Classes + self.put_string("Classe perso.: (Flèches)", self.x//3 + 1, self.y//6 + 4, [Colors.WHITEBG, Colors.BLACK]) + y = 0 + for user_class in self.__classes: + colors = [Colors.REDBG, Colors.BLACK] if y == self.__choosen_class else [Colors.GREYBG, Colors.WHITE] + self.put_string(user_class, self.x//3 + 2, self.y//6 + 5 + y, colors) + y += 1 + + self.put_string("TAB pour confirmer", self.x//3 + 1, self.y//4 + self.y//3 -1, [Colors.WHITEBG, Colors.BLACK]) + + return self + + def key_handler(self, key): + if match("[a-zA-Z]", key): + self.__username += key + elif key == keys.BACKSPACE: + self.__username = self.__username[:-1] + elif key == keys.UP and self.__choosen_class > 0: + self.__choosen_class -= 1 + elif key == keys.DOWN and self.__choosen_class < 3: + self.__choosen_class += 1 + elif key == keys.TAB: + if len(self.__username) == 0: + self.__missing_un = True + return + Screen.instance.get_layer("gui").handle_keys = True + Screen.instance.del_layer("popup") + Screen.instance.game.init_personnage(self.__username, self.__classes[self.__choosen_class]) + +class PopUp(Layer): + """Calque du menu de lancement""" + def __init__(self, z_index, message, block=False): + super().__init__(z_index, "popup") + self.message = message + self.block = block + Screen.instance.get_layer("gui").handle_keys = False + + def draw(self): + super().draw() + self.rect(self.x//3, self.y//6, self.x*2//3, self.y//4 + self.y//3, Colors.WHITEBG) + length = (self.x*2//3-1) - (self.x//3+1) + x = 0 + y = 0 + for char in self.message: + if char == "\n": + x = 0 + y += 1 + continue + self.put_char(char, self.x//3 + 1 + x, self.y//6 + 1 + y, [Colors.WHITEBG, Colors.BLACK]) + x += 1 + if x == length: + x = 0 + y += 1 + + if not self.block: + self.put_string("TAB pour confirmer", self.x//3 + 1, self.y//4 + self.y//3 -1, [Colors.WHITEBG, Colors.BLACK]) + + return self + + def key_handler(self, key): + if key == keys.TAB and not self.block: + Screen.instance.get_layer("gui").handle_keys = True + Screen.instance.del_layer("popup") + +class Sprite(Layer): + def __init__(self, z_index, sprite_name, personnage_type): + super().__init__(z_index, personnage_type) + self.personnage_type = personnage_type + self.sprite_name = sprite_name + + def draw(self): + super().draw() + with open(f"game/sprites/{self.sprite_name}.txt", "r") as sprite: + pos = (1, 1) if self.personnage_type == "PLAYER" else (Screen.instance.x*2//3+1, 1) + self.put_string(sprite.read(), *pos) + + def key_handler(self, key): + pass \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..24b582e --- /dev/null +++ b/main.py @@ -0,0 +1,21 @@ +from game.personnage import * +from game.core import Game + +import graphics.layers as layers +from graphics.engine import Screen +import graphics.key_listener as listener + +from time import sleep + +if __name__ == "__main__": + #Initialise la partie graphique + game = Game() + screen = Screen(game) + layers.StartPopUp(1) + layers.GUI(2) + + listener.build_thread(screen).start() + + while True: + screen.draw() + sleep(0.4) \ No newline at end of file