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
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.VIDEORESIZEcada vez que se redimensiona la ventana - El evento contiene las nuevas dimensiones en los atributos
event.w(ancho) yevent.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.RESIZABLEsin 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 banderapygame.RESIZABLEenset_mode(), cambiado título a "ViboyColor", agregado manejo depygame.VIDEORESIZEenhandle_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
- Documentación de Pygame: pygame.display.set_mode()
- Documentación de Pygame: Eventos de Pygame
- Documentación de Pygame: pygame.display.set_caption()
Integridad Educativa
Lo que Entiendo Ahora
- Ventanas redimensionables en Pygame: La bandera
pygame.RESIZABLEpermite que los usuarios redimensionen la ventana, y Pygame genera eventosVIDEORESIZEcuando 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
VIDEORESIZEdebe 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