Mercurial > touhou
view pytouhou/ui/window.pyx @ 792:11bc22bad1bf
python: Replace the image crate with png
We weren’t using any of its features anyway, so the png crate is exactly what
we need, without the many heavy dependencies of image.
https://github.com/image-rs/image-png/pull/670 will eventually make it even
faster to build.
| author | Link Mauve <linkmauve@linkmauve.fr> |
|---|---|
| date | Sat, 17 Jan 2026 22:22:25 +0100 |
| parents | 80687f258001 |
| children |
line wrap: on
line source
# -*- encoding: utf-8 -*- ## ## Copyright (C) 2013 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published ## by the Free Software Foundation; version 3 only. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## cimport cython cimport pytouhou.lib.sdl as sdl cdef class Clock: def __init__(self, long fps=-1): self._target_fps = 0 self._ref_tick = 0 self._ref_frame = 0 self._fps_tick = 0 self._fps_frame = 0 self.fps = 0 self.set_target_fps(fps) cdef void set_target_fps(self, long fps) nogil: self._target_fps = fps self._ref_tick = 0 self._fps_tick = 0 @cython.cdivision(True) cdef bint tick(self) nogil except True: current = sdl.get_ticks() if not self._ref_tick: self._ref_tick = current self._ref_frame = 0 if self._fps_frame >= (self._target_fps if self._target_fps > 0 else 60): self.fps = self._fps_frame * 1000. / (current - self._fps_tick) self._fps_tick = current self._fps_frame = 0 # If we are relying on vsync, but vsync doesn't work or is higher # than 60 fps, limit ourselves to 60 fps. if self._target_fps < 0 and self.fps > 64.: self._target_fps = 60 self._ref_frame += 1 self._fps_frame += 1 target_tick = self._ref_tick if self._target_fps > 0: target_tick += <unsigned long>(self._ref_frame * 1000 / self._target_fps) if current <= target_tick: sdl.delay(target_tick - current) else: self._ref_tick = current self._ref_frame = 0 cdef class Runner: cdef bint start(self) except True: pass cdef bint finish(self) except True: pass cpdef bint update(self, bint render) except -1: return False cdef class Window: def __init__(self, backend, int width=640, int height=480, long fps_limit=-1, frameskip=1): if backend is not None: self.win = backend.create_window( 'PyTouhou', sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, width, height, frameskip) self.clock = Clock(fps_limit) self.frame = 0 self.frameskip = frameskip self.width = width self.height = height cdef void set_size(self, int width, int height) nogil: self.win.set_window_size(width, height) cpdef set_runner(self, Runner runner=None): self.runner = runner if runner is not None: runner.start() cpdef run(self): try: while self.run_frame(): pass finally: if self.runner is not None: self.runner.finish() @cython.cdivision(True) cdef bint run_frame(self) except -1: cdef bint render = (self.win is not None and (self.frameskip <= 1 or not self.frame % self.frameskip)) running = False if self.runner is not None: running = self.runner.update(render) if render: self.win.present() self.clock.tick() self.frame += 1 return running cdef double get_fps(self) nogil: return self.clock.fps cdef list get_events(self): return self.win.get_events() cdef int get_keystate(self) nogil: return self.win.get_keystate() cdef void toggle_fullscreen(self) nogil: self.win.toggle_fullscreen()
