commit 3219438a227266f80738b72e2f0a30cc3a7fa931 Author: anthony-melin Date: Tue Jul 28 19:06:22 2026 +0200 🎉 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9834fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.egg-info +logs +.idea diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..825c32f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ +# Changelog diff --git a/Jamin.json b/Jamin.json new file mode 100644 index 0000000..0e2354c --- /dev/null +++ b/Jamin.json @@ -0,0 +1,9 @@ +{ + "name": "Jamin", + "max_pv": 30, + "current_pv": 30, + "strength": 5, + "protection": 1, + "speed": 2, + "mob_type": 0 +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3ed8bc2 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Elironwars - Pygame UI + +Ce projet est un plugin du moteur de jeu elironwars (d-crawler) permettant un affichage interactif avec pygame. diff --git a/assets/orc.png b/assets/orc.png new file mode 100755 index 0000000..9b4a0bb Binary files /dev/null and b/assets/orc.png differ diff --git a/assets/orc2.jpg b/assets/orc2.jpg new file mode 100755 index 0000000..81f915c Binary files /dev/null and b/assets/orc2.jpg differ diff --git a/assets/potato_man.jpg b/assets/potato_man.jpg new file mode 100755 index 0000000..7e998a5 Binary files /dev/null and b/assets/potato_man.jpg differ diff --git a/assets/succube.png b/assets/succube.png new file mode 100755 index 0000000..def0da3 Binary files /dev/null and b/assets/succube.png differ diff --git a/format.sh b/format.sh new file mode 100755 index 0000000..b8f0563 --- /dev/null +++ b/format.sh @@ -0,0 +1,2 @@ +isort src tests +autopep8 src tests diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f2cae4b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,41 @@ +[project] +name = "elironwars-pygame" +version = "0.0.0" +description = "Ce projet est un plugin du moteur de jeu elironwars (d-crawler)." +readme = "README.md" +keywords = [] +requires-python = ">= 3.14" +dependencies = [ + "pygame >= 2.6.1", +] +authors = [ + { name = "Raggaroth", email = "b.baudouin@pm.me" }, + { name = "Toucan", email = "anthony.melin@laposte.net" }, +] +maintainers = [ + { name = "Raggaroth", email = "b.baudouin@pm.me" } +] + +[project.urls] +Homepage = "https://gitea.raggaroth-factory.fr/public/elironwars-pygame" +Documentation = "https://gitea.raggaroth-factory.fr/public/elironwars-pygame/wiki" +Repository = "https://gitea.raggaroth-factory.fr/public/elironwars-pygame.git" +Issues = "https://gitea.raggaroth-factory.fr/public/elironwars-pygame/issues" +Changelog = "https://github.com/me/spam/blob/master/CHANGELOG.md" + +[build-system] +requires = ["setuptools >= 77.0.3"] +build-backend = "setuptools.build_meta" + +[project.entry-points."elironwars.ui"] +pygame = "elironwars_pygame.main:PygameUi" + +[tool.isort] +profile = "black" +src_paths = ["src", "tests"] +known_first_party = ["elironwars"] + +[tool.autopep8] +max_line_length = 120 +in-place = true +recursive = true diff --git a/src/elironwars_pygame/__init__.py b/src/elironwars_pygame/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/elironwars_pygame/main.py b/src/elironwars_pygame/main.py new file mode 100644 index 0000000..a483305 --- /dev/null +++ b/src/elironwars_pygame/main.py @@ -0,0 +1,436 @@ +import sys +import time + +import pygame + +from .screen import Screen +from .text import Text, Title + +SCREEN_BG_COLOR = (50, 50, 50) + +MOB_ASSETS = { + 'Yanaar': 'assets/orc.png', + 'Ulnarain': 'assets/orc2.jpg', + 'Skroll': 'assets/potato_man.jpg', +} + +PLAYER_ASSET = 'assets/succube.png' + + +class PygameUi: + + def __init__(self): + self.screen = Screen() + self.show_title() + + def show_title(self): + title = Title().set_position(center=self.screen.rect.center) + space = Text('press space').set_position(midtop=title.rect.midbottom) + + loop_start = time.time() + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_SPACE: + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + + loop_time = time.time() - loop_start + if loop_time % 2.0 > 1.0: + space.show(self.screen.surface) + + self.screen.refresh() + + def empty_room(self): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('Room empty', font_size=48).set_position(center=inner_box.center) + + instructions = Text('Press enter to continue', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + instructions.show(self.screen.surface) + self.screen.refresh() + + def meet_mob(self, mob): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('Mob in the room', font_size=48).set_position(midtop=inner_box.midtop) + + instructions = Text('Press enter to continue', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + spec_margin = 16 + spec_box = pygame.Rect( + inner_box.left, + title.rect.bottom + spec_margin, + inner_box.width, + instructions.rect.top - title.rect.bottom - (spec_margin * 2) + ) + + img = pygame.image.load(MOB_ASSETS[mob.name]) + img_rect = img.get_rect().fit(pygame.Rect(0, 0, spec_box.height, spec_box.height)) + img = pygame.transform.smoothscale(img, img_rect.size) + img_rect = img.get_rect(midleft=spec_box.midleft) + + props_box = pygame.Rect( + img_rect.right, + spec_box.top, + spec_box.width - img_rect.width, + spec_box.height, + ) + + mob_name = Text(mob.name, font_size=36) + mob_name = mob_name.set_position(midtop=props_box.midtop) + + mob_pv = Text(f"PV: {mob.current_pv}/{mob.max_pv}") + mob_pv = mob_pv.set_position(top=mob_name.rect.bottom + 36, left=props_box.left + 16) + + mob_strength = Text(f"Force: {mob.strength}") + mob_strength = mob_strength.set_position(top=mob_pv.rect.bottom + 24, left=props_box.left + 16) + + mob_protection = Text(f"Protection: {mob.protection}") + mob_protection = mob_protection.set_position(top=mob_strength.rect.bottom + 24, + left=props_box.left + 16) + + mob_speed = Text(f"Vitesse: {mob.speed}") + mob_speed = mob_speed.set_position(top=mob_protection.rect.bottom + 24, left=props_box.left + 16) + + texts = [ + title, + mob_name, + mob_pv, + mob_strength, + mob_protection, + mob_speed, + instructions, + ] + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + self.screen.surface.blit(img, img_rect) + for text in texts: + text.show(self.screen.surface) + self.screen.refresh() + + def player_dead(self): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('You are dead', font_size=48).set_position(center=inner_box.center) + + instructions = Text('Press enter to continue', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + instructions.show(self.screen.surface) + self.screen.refresh() + + def mob_dead(self, mob): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('You win', font_size=48).set_position(center=inner_box.center) + + instructions = Text('Press enter to continue', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + instructions.show(self.screen.surface) + self.screen.refresh() + + def run_away(self): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('You are running away', font_size=48).set_position(center=inner_box.center) + + for _ in range(60): # 60 tick at 60fps => loop for 1sec + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + self.screen.refresh() + + def leave(self, player): + title = Text(f'Goodbye {player.name}', font_size=48).set_position(center=self.screen.surface.get_rect().center) + for _ in range(60): # 60 tick at 60fps => loop for 1sec + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + self.screen.refresh() + + def select_player(self, player): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('Player selection', font_size=48).set_position(midtop=inner_box.midtop) + + instructions = Text('Press enter to continue', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + spec_margin = 16 + spec_box = pygame.Rect( + inner_box.left, + title.rect.bottom + spec_margin, + inner_box.width, + instructions.rect.top - title.rect.bottom - (spec_margin * 2) + ) + + img = pygame.image.load(PLAYER_ASSET) + img_rect = img.get_rect().fit(pygame.Rect(0, 0, spec_box.height, spec_box.height)) + img = pygame.transform.smoothscale(img, img_rect.size) + img_rect = img.get_rect(midleft=spec_box.midleft) + + props_box = pygame.Rect( + img_rect.right, + spec_box.top, + spec_box.width - img_rect.width, + spec_box.height, + ) + + player_name = Text(player.name, font_size=36) + player_name = player_name.set_position(midtop=props_box.midtop) + + player_pv = Text(f"PV: {player.current_pv}/{player.max_pv}") + player_pv = player_pv.set_position(top=player_name.rect.bottom + 36, left=props_box.left + 16) + + player_strength = Text(f"Force: {player.strength}") + player_strength = player_strength.set_position(top=player_pv.rect.bottom + 24, left=props_box.left + 16) + + player_protection = Text(f"Protection: {player.protection}") + player_protection = player_protection.set_position( + top=player_strength.rect.bottom + 24, left=props_box.left + 16) + + player_speed = Text(f"Vitesse: {player.speed}") + player_speed = player_speed.set_position(top=player_protection.rect.bottom + 24, left=props_box.left + 16) + + texts = [ + title, + player_name, + player_pv, + player_strength, + player_protection, + player_speed, + instructions, + ] + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + self.screen.surface.blit(img, img_rect) + for text in texts: + text.show(self.screen.surface) + self.screen.refresh() + + def entering_room(self, room_name): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text(f'Room {room_name + 1}', font_size=48).set_position(center=inner_box.center) + + instructions = Text('Press enter to continue', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + instructions.show(self.screen.surface) + self.screen.refresh() + + def last_room(self): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('End of level', font_size=48).set_position(center=inner_box.center) + + instructions = Text('Press enter to continue', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + instructions.show(self.screen.surface) + self.screen.refresh() + + def entering_donjon(self, level): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text(f'Level 1 - {len(level.rooms)} rooms', font_size=48).set_position(center=inner_box.center) + + instructions = Text('Press enter to continue', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + loop = False + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + instructions.show(self.screen.surface) + self.screen.refresh() + + def action_menu(self, actions_autorisees): + texts = [Text(action.libelle) for n, action in enumerate(actions_autorisees)] + arrow = Text('> ') + action_index = 0 + + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('Select action', font_size=48).set_position(midtop=inner_box.midtop) + + instructions = Text('Press enter to continue; Press up or down to move arrow', font_size=24) + instructions = instructions.set_position(left=inner_box.left, bottom=inner_box.bottom) + + action_box = pygame.Rect(inner_box.left + 64, title.rect.bottom + 64, inner_box.width, inner_box.height) + last_bottom = action_box.top + for text in texts: + text.set_position(left=action_box.left, top=last_bottom) + last_bottom = text.rect.bottom + 24 + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key in (pygame.K_KP_ENTER, pygame.K_RETURN): + return actions_autorisees[action_index] + elif event.key == pygame.K_DOWN: + action_index = min(action_index + 1, len(actions_autorisees) - 1) + elif event.key == pygame.K_UP: + action_index = max(action_index - 1, 0) + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + for text in texts: + text.show(self.screen.surface) + arrow.set_position(midright=texts[action_index].rect.midleft).show(self.screen.surface) + instructions.show(self.screen.surface) + self.screen.refresh() + + def fight_pvs(self, player, mob, pvs): + margin = 16 + inner_box = pygame.Rect(margin, margin, self.screen.width - (margin * 2), self.screen.height - (margin * 2)) + + title = Text('Fight', font_size=48).set_position(midtop=inner_box.midtop) + + player_img = pygame.image.load(PLAYER_ASSET) + player_img_rect = player_img.get_rect().fit(pygame.Rect(0, 0, 128, 128)) + player_img = pygame.transform.smoothscale(player_img, player_img_rect.size) + player_img_rect = player_img.get_rect(left=inner_box.left + 48, centery=inner_box.centery) + + mob_img = pygame.image.load(MOB_ASSETS[mob.name]) + mob_img_rect = mob_img.get_rect().fit(pygame.Rect(0, 0, 128, 128)) + mob_img = pygame.transform.smoothscale(mob_img, mob_img_rect.size) + mob_img_rect = mob_img.get_rect(right=inner_box.right - 48, centery=inner_box.centery) + + init_fight = [{ + 'player': player.max_pv, + 'mob': mob.max_pv, + }] + + all_pvs = init_fight + pvs + + for pv in all_pvs: + for _ in range(60): # 60 tick at 60fps => loop for 1sec + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + + self.screen.surface.fill(SCREEN_BG_COLOR) + title.show(self.screen.surface) + self.screen.surface.blit(player_img, player_img_rect) + self.screen.surface.blit(mob_img, mob_img_rect) + + (Text(f"{pv['player']}/{player.max_pv}", font_size=36) + .set_position(midtop=player_img_rect.midbottom) + .show(self.screen.surface)) + (Text(f"{pv['mob']}/{mob.max_pv}", font_size=36) + .set_position(midtop=mob_img_rect.midbottom) + .show(self.screen.surface)) + + self.screen.refresh() diff --git a/src/elironwars_pygame/screen.py b/src/elironwars_pygame/screen.py new file mode 100644 index 0000000..7ea15c5 --- /dev/null +++ b/src/elironwars_pygame/screen.py @@ -0,0 +1,42 @@ +import pygame + + +class Screen: + + def __init__(self, width=640, height=360, caption='Elironwars'): + # Initialisation de Pygame + pygame.init() + + # CrĂ©ation de la fenĂȘtre + self.width, self.height = width, height + self.surface = pygame.display.set_mode((self.width, self.height)) + pygame.display.set_caption(caption) + # Horloge pour limiter les FPS + self.clock = pygame.time.Clock() + + @property + def rect(self): + return self.surface.get_rect() + + def refresh(self): + # Met Ă  jour l'affichage + pygame.display.flip() + + # Limite Ă  60 FPS + self.clock.tick(60) + + @staticmethod + def close(): + pygame.quit() + + +if __name__ == '__main__': + screen = Screen() + + loop = True + while loop: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + loop = False + + screen.refresh() diff --git a/src/elironwars_pygame/text.py b/src/elironwars_pygame/text.py new file mode 100644 index 0000000..a64c4e0 --- /dev/null +++ b/src/elironwars_pygame/text.py @@ -0,0 +1,31 @@ +import pygame + + +class Text: + + def __init__(self, text, font_size=24, color=(255, 255, 255)): + self.text = text + self.police = pygame.font.Font(None, font_size) + self.surface = self.police.render(text, True, color) + self.rect = self.surface.get_rect() + + def set_color(self, color): + self.surface = self.police.render(self.text, True, color) + return self + + def at(self, x, y): + self.rect = self.surface.get_rect(x=x, y=y) + return self + + def set_position(self, **kwargs): + self.rect = self.surface.get_rect(**kwargs) + return self + + def show(self, surface: pygame.Surface): + surface.blit(self.surface, self.rect) + + +class Title(Text): + + def __init__(self, text='Elironwars'): + super().__init__(text, font_size=128)