⚠️ Clean-Room / Educativo

Este proyecto es educativo y Open Source. No se copia código de otros emuladores. Implementación basada únicamente en documentación técnica y tests permitidas.

Ventana Escalable y Título ViboyColor

Fecha: 2025-12-30 Step ID: 0369 Estado: VERIFIED

Resumen

Se implementó la capacidad de redimensionar la ventana del emulador usando la bandera pygame.RESIZABLE en pygame.display.set_mode(). Se cambió el título de la ventana de "Viboy Color" a "ViboyColor" para una identidad visual más compacta. Se agregó el manejo del evento pygame.VIDEORESIZE en los métodos handle_events() y _show_loading_screen() para actualizar dinámicamente las dimensiones de la ventana cuando el usuario la redimensiona. El renderizado se adapta automáticamente al nuevo tamaño usando pygame.transform.scale().

Concepto de Hardware

Ventanas Redimensionables en Interfaces Gráficas

En aplicaciones gráficas modernas, permitir que los usuarios redimensionen las ventanas es una característica estándar que mejora la experiencia de usuario. Esto es especialmente útil para emuladores, donde los usuarios pueden querer ajustar el tamaño de la ventana según sus preferencias o el tamaño de su pantalla.

Pygame proporciona la bandera pygame.RESIZABLE que permite que la ventana sea redimensionable. Cuando esta bandera está activada:

  • El usuario puede arrastrar los bordes de la ventana para cambiar su tamaño
  • Se genera el evento pygame.VIDEORESIZE cada vez que se redimensiona la ventana
  • El evento contiene las nuevas dimensiones en los atributos event.w (ancho) y event.h (alto)

Escalado de Gráficos

Cuando se redimensiona la ventana, el contenido debe escalarse para adaptarse al nuevo tamaño. En el emulador, el framebuffer interno tiene un tamaño fijo de 160x144 píxeles (tamaño nativo de Game Boy), y este se escala a las dimensiones de la ventana usando pygame.transform.scale(). Este método interpola los píxeles para ajustar el contenido al nuevo tamaño, manteniendo la proporción original cuando es posible.

Nota: Aunque la ventana es redimensionable, el contenido del emulador se escalará para llenar la ventana, lo que puede resultar en distorsión si el usuario hace la ventana muy ancha o muy alta. Para mantener la proporción correcta, sería necesario calcular un factor de escala que mantenga la relación 160:144, pero por ahora se permite cualquier tamaño para dar flexibilidad al usuario.

Implementación

Se modificó la clase Renderer en src/gpu/renderer.py para hacer la ventana redimensionable y cambiar el título.

Modificaciones en el Constructor (__init__)

Se cambió la llamada a pygame.display.set_mode() para incluir la bandera pygame.RESIZABLE:

# Antes:
self.screen = pygame.display.set_mode((self.window_width, self.window_height))

# Después:
self.screen = pygame.display.set_mode((self.window_width, self.window_height), pygame.RESIZABLE)

Se cambió el título de la ventana de "Viboy Color" a "ViboyColor":

# Antes:
pygame.display.set_caption("Viboy Color")

# Después:
pygame.display.set_caption("ViboyColor")

Manejo del Evento VIDEORESIZE en handle_events()

Se agregó el manejo del evento pygame.VIDEORESIZE en el método handle_events() para actualizar las dimensiones de la ventana cuando el usuario la redimensiona:

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        return False
    
    # Manejar redimensionamiento de ventana
    elif event.type == pygame.VIDEORESIZE:
        self.window_width = event.w
        self.window_height = event.h
        # Actualizar el tamaño de la superficie de la ventana
        self.screen = pygame.display.set_mode((self.window_width, self.window_height), pygame.RESIZABLE)

Cuando se detecta el evento VIDEORESIZE, se actualizan las variables self.window_width y self.window_height con las nuevas dimensiones, y se vuelve a llamar a pygame.display.set_mode() con el nuevo tamaño para actualizar la superficie de la ventana.

Manejo del Evento VIDEORESIZE en _show_loading_screen()

Se agregó el mismo manejo del evento pygame.VIDEORESIZE en el método _show_loading_screen() para mantener la consistencia durante la pantalla de carga:

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
        break
    elif event.type == pygame.VIDEORESIZE:
        self.window_width = event.w
        self.window_height = event.h
        # Actualizar el tamaño de la superficie de la ventana
        self.screen = pygame.display.set_mode((self.window_width, self.window_height), pygame.RESIZABLE)
    elif event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE:
            running = False
            break

Decisiones de Diseño

  • Bandera RESIZABLE: Se usa solo pygame.RESIZABLE sin otras banderas adicionales, manteniendo la simplicidad
  • Actualización de dimensiones: Se actualizan tanto las variables internas como la superficie de la ventana para mantener consistencia
  • Título simplificado: Se cambió de "Viboy Color" a "ViboyColor" para una identidad visual más compacta y moderna
  • Escalado automático: El renderizado existente ya usa pygame.transform.scale(), por lo que se adapta automáticamente al nuevo tamaño

Archivos Afectados

  • src/gpu/renderer.py - Agregada bandera pygame.RESIZABLE en set_mode(), cambiado título a "ViboyColor", agregado manejo de pygame.VIDEORESIZE en handle_events() y _show_loading_screen()

Tests y Verificación

La funcionalidad se verificó manualmente ejecutando el emulador:

  • Verificación visual: Se confirmó que la ventana puede ser redimensionada arrastrando los bordes
  • Título de ventana: Se confirmó que el título ahora muestra "ViboyColor" en lugar de "Viboy Color"
  • Adaptación del contenido: Se confirmó que el contenido del emulador se escala correctamente al redimensionar la ventana
  • Pantalla de carga: Se confirmó que el redimensionamiento también funciona durante la pantalla de carga
  • Icono: Se confirmó que el icono de la ventana sigue funcionando correctamente (ya estaba implementado previamente)

Nota: No se requirieron tests unitarios adicionales ya que esta es una funcionalidad de interfaz de usuario que se verifica mejor visualmente.

Fuentes Consultadas

Integridad Educativa

Lo que Entiendo Ahora

  • Ventanas redimensionables en Pygame: La bandera pygame.RESIZABLE permite que los usuarios redimensionen la ventana, y Pygame genera eventos VIDEORESIZE cuando esto ocurre
  • Eventos de Pygame: Los eventos se manejan en el bucle de eventos usando pygame.event.get(), y cada evento tiene un tipo y atributos específicos según el tipo
  • Actualización de superficie: Cuando se redimensiona la ventana, es necesario volver a llamar a pygame.display.set_mode() con las nuevas dimensiones para actualizar la superficie de la ventana
  • Escalado automático: El uso de pygame.transform.scale() en el código de renderizado existente permite que el contenido se adapte automáticamente al nuevo tamaño de la ventana

Lo que Falta Confirmar

  • Si sería beneficioso mantener la proporción de aspecto 160:144 cuando se redimensiona la ventana (actualmente se permite cualquier proporción)
  • Si hay algún impacto en el rendimiento cuando se redimensiona frecuentemente (probablemente mínimo)

Hipótesis y Observaciones

  • El cambio de título a "ViboyColor" es más consistente con la identidad visual moderna del proyecto
  • La capacidad de redimensionar la ventana mejora la usabilidad, especialmente en pantallas de diferentes tamaños
  • El manejo del evento VIDEORESIZE debe hacerse en todos los lugares donde se manejan eventos para mantener consistencia

Próximos Pasos

  • [ ] Considerar mantener la proporción de aspecto 160:144 al redimensionar (opcional)
  • [ ] Continuar con otras mejoras de interfaz de usuario según se requiera
  • [ ] Continuar con el desarrollo del emulador según el roadmap