From 222ee11c0c3a046960cd29b2ef4af127cc8f2a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Sat, 11 Nov 2023 20:25:39 +0000 Subject: [PATCH] chore: improved support for graphics --- src/python/boytacean/gb.py | 4 +--- src/python/boytacean/graphics.py | 34 ++++++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/python/boytacean/gb.py b/src/python/boytacean/gb.py index ba224ef6..f471f5ae 100644 --- a/src/python/boytacean/gb.py +++ b/src/python/boytacean/gb.py @@ -223,9 +223,7 @@ This is a [Game Boy](https://en.wikipedia.org/wiki/Game_Boy) emulator built usin self._video.save_frame(self.image(), self._frame_index) self._video.compute_next(self._frame_index) - # @TODO: this should be sample, meaning that not every - # single frame is sent to the display (performance) - if self._display != None: + if self._display != None and self._display.should_render(self._frame_index): from .graphics import Display cast(Display, self._display).render_frame(self.frame_buffer()) diff --git a/src/python/boytacean/graphics.py b/src/python/boytacean/graphics.py index c6a98052..89fb480c 100644 --- a/src/python/boytacean/graphics.py +++ b/src/python/boytacean/graphics.py @@ -1,3 +1,4 @@ +from math import ceil from typing import Union from sdl2 import ( SDL_QUIT, @@ -8,15 +9,18 @@ from sdl2 import ( SDL_DestroyTexture, SDL_FreeSurface, ) -from sdl2.ext import Window, Renderer, Color, init as init_sdl, get_events +from sdl2.ext import Window, Renderer, init as init_sdl, get_events -from .boytacean import DISPLAY_WIDTH, DISPLAY_HEIGHT +from .boytacean import DISPLAY_WIDTH, DISPLAY_HEIGHT, VISUAL_FREQ class Display: _width: int = DISPLAY_WIDTH _height: int = DISPLAY_HEIGHT _title: str = "Boytacean" + _scale: float = 3.0 + _frame_gap: int = 60 + _next_frame: int = 60 _window: Union[Window, None] = None _renderer: Union[Renderer, None] = None @@ -25,20 +29,32 @@ class Display: width: int = DISPLAY_WIDTH, height: int = DISPLAY_HEIGHT, title="Boytacean", + scale=3.0, + start_frame=0, + fps=5, ): self._width = width self._height = height self._title = title + self._scale = scale + self._frame_gap = ceil(VISUAL_FREQ / fps) + self._next_frame = start_frame + self._frame_gap self._window = None self._renderer = None self.build() def build(self): init_sdl() - self._window = Window(self._title, size=(self._width, self._height)) + self._window = Window( + self._title, + size=(int(self._width * self._scale), int(self._height * self._scale)), + ) self._window.show() self._renderer = Renderer(self._window) + def should_render(self, frame_index) -> bool: + return frame_index >= self._next_frame + def render_frame(self, frame_buffer: bytes): if not self._window: raise RuntimeError("Window not initialized") @@ -49,7 +65,7 @@ class Display: # we consider that every time there's a request for a new # frame draw the queue of SDL events should be flushed events = get_events() - for event in events: + for _ in events: pass surface = SDL_CreateRGBSurfaceFrom( @@ -58,9 +74,9 @@ class Display: DISPLAY_HEIGHT, 24, DISPLAY_WIDTH * 3, - 0x000000ff, - 0x0000ff00, - 0x00ff0000, + 0x000000FF, + 0x0000FF00, + 0x00FF0000, 0x0, ) texture = SDL_CreateTextureFromSurface( @@ -72,9 +88,11 @@ class Display: self._renderer.sdlrenderer, texture, None, - SDL_Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT), + None, ) self._renderer.present() finally: SDL_DestroyTexture(texture) SDL_FreeSurface(surface) + + self._next_frame += self._frame_gap -- GitLab