From c3ac27e6f26bd3ebcaa8f3bd620c2d4619aa8de6 Mon Sep 17 00:00:00 2001 From: vg Date: Wed, 9 Nov 2022 22:28:54 +0100 Subject: git-sync on dita --- pygame/arrow-right.png | Bin 0 -> 2840 bytes pygame/main.py | 307 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 307 insertions(+) create mode 100644 pygame/arrow-right.png create mode 100755 pygame/main.py diff --git a/pygame/arrow-right.png b/pygame/arrow-right.png new file mode 100644 index 0000000..c88334f Binary files /dev/null and b/pygame/arrow-right.png differ diff --git a/pygame/main.py b/pygame/main.py new file mode 100755 index 0000000..948b95a --- /dev/null +++ b/pygame/main.py @@ -0,0 +1,307 @@ +#!/usr/bin/python3 + +from dataclasses import dataclass +from pathlib import Path + +#import pygame_sdl2 as pygame +import pygame +import yaml + + +#WINDOW_RESOLUTION = (1280, 720) +WINDOW_RESOLUTION = (800, 600) + +if pygame.ver[0] != '2': + raise ValueError(f'pygame2 required, got {pygame.ver}') + + +class Event(Exception): pass +class QuitEvent(Event): pass + + +@dataclass +class AppState: + menu_selected_index: int = 0 + + +class GuiApp: + + def __init__(self): + pygame.init() + #print(pygame.display.list_modes()) + self.window = pygame.display.set_mode(WINDOW_RESOLUTION) + self.clock = pygame.time.Clock() + self.menu_font = pygame.font.Font(pygame.font.get_default_font(), 32) + self.font_antialias = True + #self.font_antialias = False + self.menu_color = (0, 0, 200) + + def process_input(self, event=None): + if event is None: + event = pygame.event.poll() + if event.type == pygame.KEYDOWN: + print('event', event, 'key name', pygame.key.name(event.key)) + if event.key in (pygame.K_q, pygame.K_ESCAPE): + raise QuitEvent() + if event.type == pygame.QUIT: + raise QuitEvent() + + def update(self): + pass + + def render(self): + self.window.fill((0, 0, 0)) + + # Initial y + y = 50 + + # Title + #surface = self.titleFont.render("TANK BATTLEGROUNDS !!", True, (200, 0, 0)) + #x = (self.window.get_width() - surface.get_width()) // 2 + #self.window.blit(surface, (x, y)) + #y += (200 * surface.get_height()) // 100 + + x = 50 + + # Compute menu width + #menuWidth = 0 + #for item in self.menuItems: + # surface = self.itemFont.render(item['title'], True, (200, 0, 0)) + # menuWidth = max(menuWidth, surface.get_width()) + # item['surface'] = surface + + surface = self.menu_font.render("I love my cat !", + self.font_antialias, self.menu_color) + self.window.blit(surface, (x, y)) + + ## Draw menu items + #x = (self.window.get_width() - menuWidth) // 2 + #for index, item in enumerate(self.menuItems): + # # Item text + # surface = item['surface'] + # self.window.blit(surface, (x, y)) + + # # Cursor + # if index == self.currentMenuItem: + # cursorX = x - self.menuCursor.get_width() - 10 + # cursorY = y + (surface.get_height() - self.menuCursor.get_height()) // 2 + # self.window.blit(self.menuCursor, (cursorX, cursorY)) + + # y += (120 * surface.get_height()) // 100 + + + #pygame.draw.rect(self.window, + # (0,0,255), + # (120,120,400,240)) + + pygame.display.update() + + + def loop(self): + + try: + while 1: + self.process_input() + self.update() + self.render() + self.clock.tick(30) # 30 fps + except QuitEvent: + pass + + print('quitting') + pygame.quit() + + +class GuiAppSub1(GuiApp): + + def __init__(self): + super().__init__() + + self.state = AppState() + self.base_window_fill_color = (0, 0, 0) + self.user_move_vector = (0, 0) + with Path('~/games/.saves/gamedata.yaml').expanduser().open() as fp: + self.gamedb = yaml.safe_load(fp) + self.menu_items = [x['title'] for x in self.gamedb['games']] + self.menu_font_cache = ({}, []) + self.menu_font_cache_max = 40 + self.image_right_arrow = pygame.image.load('arrow-right.png') + #self.last_movement_update_time = self.clock. + self.joysticks = {} + self.joysticks_axis_threshold = 0 + + def menu_font_render(self, text): + cached_surface = self.menu_font_cache[0].get(text, None) + if cached_surface is not None: + self.menu_font_cache[1].remove(text) + self.menu_font_cache[1].append(text) # refresh mru place + return cached_surface + + new_surface = self.menu_font.render(text, + self.font_antialias, + self.menu_color) + + self.menu_font_cache[0][text] = new_surface + self.menu_font_cache[1].append(text) + + if len(self.menu_font_cache[1]) > self.menu_font_cache_max: + removed_item_text = self.menu_font_cache[1].pop(0) + del self.menu_font_cache[0][removed_item_text] + + # debug for cache miss: + print('cache miss for', text) + + return new_surface + + def process_input(self): + movement_up_keys = ( + pygame.K_UP, + pygame.K_k, + ) + movement_down_keys = ( + pygame.K_DOWN, + pygame.K_j, + ) + axis_change = 0 + for event in pygame.event.get(): + go_super = 1 + x, y = self.user_move_vector + if event.type == pygame.KEYDOWN: + if event.key in (*movement_up_keys, *movement_down_keys): + y += 1 if event.key in movement_down_keys else -1 + go_super = 0 + elif event.key in (pygame.K_LEFT, pygame.K_RIGHT): + x += 1 if event.key == pygame.K_LEFT else -1 + go_super = 0 + elif event.type == pygame.KEYUP: + x, y = self.user_move_vector + if event.key in (*movement_up_keys, *movement_down_keys): + y -= 1 if event.key in movement_down_keys else -1 + go_super = 0 + elif event.key in (pygame.K_LEFT, pygame.K_RIGHT): + x -= 1 if event.key == pygame.K_LEFT else -1 + go_super = 0 + elif event.type in (pygame.JOYBUTTONDOWN, pygame.JOYBUTTONUP): + go_super = 0 + factor = 1 if pygame.JOYBUTTONDOWN else -1 + joystick = self.joysticks[event.instance_id] + print('gamepad event', event) + #if event.button == 0: + #y += 1 * factor + if event.type == pygame.JOYBUTTONDOWN: + joystick.rumble(0.3, 0.8, 40) + if event.button == 1: + raise QuitEvent() + #if event.button == 1: + #y -= 1 * factor + elif event.type == pygame.JOYAXISMOTION: + go_super = 0 + if event.axis == 1: # left stick up-down axis + new_axis = self.joysticks_axis_threshold + #print('motion event', event) + if event.value > 0.70: + new_axis = 1 # down activated + elif event.value < 0.5 and event.value > -0.5: + new_axis = 0 # down and up deactivated + elif event.value < -0.70: + new_axis = -1 # up activated + if new_axis != self.joysticks_axis_threshold: + axis_change = 1 + self.joysticks_axis_threshold = new_axis + print('threshold', self.joysticks_axis_threshold) + elif event.type == pygame.JOYDEVICEADDED: + # This event will be generated when the program starts for every + # joystick, filling up the list without needing to create them manually. + joy = pygame.joystick.Joystick(event.device_index) + self.joysticks[joy.get_instance_id()] = joy + print(f"Gamepad {joy.get_instance_id()} connected") + elif event.type == pygame.JOYDEVICEREMOVED: + del self.joysticks[event.instance_id] + print(f"Gamepad {event.instance_id} disconnected") + + if go_super == 0: + if axis_change: + self.user_move_vector = (x, self.joysticks_axis_threshold) + else: + self.user_move_vector = (x, y) + print('new move vector:', self.user_move_vector) + else: + super().process_input(event) + + def update(self): + menu_new_index = self.state.menu_selected_index + if self.user_move_vector[1] < 0: + menu_new_index -= 1 + elif self.user_move_vector[1] > 0: + menu_new_index += 1 + if menu_new_index < 0: + menu_new_index = 0 + elif menu_new_index > (len(self.menu_items)-1): + menu_new_index = len(self.menu_items)-1 + self.state.menu_selected_index = menu_new_index + + def render(self): + self.window.fill(self.base_window_fill_color) + + # Initial y + y = 50 + + # Title + #surface = self.titleFont.render("TANK BATTLEGROUNDS !!", True, (200, 0, 0)) + #x = (self.window.get_width() - surface.get_width()) // 2 + #self.window.blit(surface, (x, y)) + #y += (200 * surface.get_height()) // 100 + + x = 50 + 64 + 5 + + # Compute menu width + #menuWidth = 0 + #for item in self.menuItems: + # surface = self.itemFont.render(item['title'], True, (200, 0, 0)) + # menuWidth = max(menuWidth, surface.get_width()) + # item['surface'] = surface + + y_pad = 5 + font_selected_item_height = None + selected_item_y = y + for index, item in enumerate(self.menu_items): + surface = self.menu_font_render(item) + self.window.blit(surface, (x, y)) + if self.state.menu_selected_index == index: + font_selected_item_height = surface.get_height() + selected_item_y = y + y += surface.get_height() + y_pad + + self.window.blit(self.image_right_arrow, (50, selected_item_y - 64//2 + + font_selected_item_height//2)) + + + fps_surface = self.menu_font_render(f'{self.clock.get_fps():02.0f}') + fps_pos = (self.window.get_width() - fps_surface.get_width(), 0) + self.window.blit(fps_surface, fps_pos) + + ## Draw menu items + #x = (self.window.get_width() - menuWidth) // 2 + #for index, item in enumerate(self.menuItems): + # # Item text + # surface = item['surface'] + # self.window.blit(surface, (x, y)) + + # # Cursor + # if index == self.currentMenuItem: + # cursorX = x - self.menuCursor.get_width() - 10 + # cursorY = y + (surface.get_height() - self.menuCursor.get_height()) // 2 + # self.window.blit(self.menuCursor, (cursorX, cursorY)) + + # y += (120 * surface.get_height()) // 100 + + + #pygame.draw.rect(self.window, + # (0,0,255), + # (120,120,400,240)) + + pygame.display.update() + + +app = GuiAppSub1() +app.loop() -- cgit v1.2.3