# HG changeset patch # User Emmanuel Gil Peyrot # Date 1380889631 -7200 # Node ID c622eaf64428eaa1c08deab6e1c2ed50590ee997 # Parent 3d3285918ba1df85eb713847f1fc953ce6ff993c Optimize GameRunner some more, fix replay, and remove Window dependency in Renderer. diff --git a/eosd b/eosd --- a/eosd +++ b/eosd @@ -166,7 +166,8 @@ def main(window, path, data, stage_num, game_class = GameBossRush if boss_rush else Game common = Common(resource_loader, characters, continues, stage_num - 1) - runner = GameRunner(window, resource_loader, skip=skip_replay, con=con) + runner = GameRunner(window, common, resource_loader, skip_replay, con) + window.set_runner(runner) while True: first_player = common.players[0] @@ -206,8 +207,7 @@ def main(window, path, data, stage_num, hints_stage = hints.stages[stage_num - 1] if hints else None game = game_class(resource_loader, stage_num, rank, difficulty, - common, prng=prng, hints=hints_stage, - friendly_fire=friendly_fire) + common, prng, hints_stage, friendly_fire) if not enable_particles: def new_particle(pos, anim, amp, number=1, reverse=False, duration=24): @@ -219,7 +219,6 @@ def main(window, path, data, stage_num, # Main loop runner.load_game(game, background, bgms, replay, save_keystates) - window.set_runner(runner) try: window.run() break diff --git a/pytouhou/games/eosd.py b/pytouhou/games/eosd.py --- a/pytouhou/games/eosd.py +++ b/pytouhou/games/eosd.py @@ -28,7 +28,10 @@ from pytouhou.vm.eclrunner import ECLMai class EoSDCommon(object): - def __init__(self, resource_loader, player_characters, continues, stage): + def __init__(self, resource_loader, player_characters, continues, stage, + width=384, height=448): + self.width, self.height = width, height + self.etama = resource_loader.get_multi_anm(('etama3.anm', 'etama4.anm')) self.bullet_types = [BulletType(self.etama[0], 0, 11, 14, 15, 16, hitbox_size=2, type_id=0), @@ -99,8 +102,8 @@ class EoSDCommon(object): class EoSDGame(Game): def __init__(self, resource_loader, stage, rank, difficulty, - common, nb_bullets_max=640, width=384, height=448, prng=None, - hints=None, friendly_fire=True): + common, prng=None, hints=None, friendly_fire=True, + nb_bullets_max=640): self.etama = common.etama #XXX try: @@ -135,12 +138,11 @@ class EoSDGame(Game): common.interface.start_stage(self, stage) self.native_texts = [common.interface.stage_name, common.interface.song_name] - self.resource_loader = resource_loader #XXX: currently used for texture preload in pytouhou.ui.gamerunner. Wipe it! - Game.__init__(self, common.players, stage, rank, difficulty, common.bullet_types, common.laser_types, - common.item_types, nb_bullets_max, width, height, prng, - common.interface, hints, friendly_fire) + common.item_types, nb_bullets_max, common.width, + common.height, prng, common.interface, hints, + friendly_fire) diff --git a/pytouhou/ui/gamerenderer.pxd b/pytouhou/ui/gamerenderer.pxd --- a/pytouhou/ui/gamerenderer.pxd +++ b/pytouhou/ui/gamerenderer.pxd @@ -3,7 +3,6 @@ from pytouhou.game.game cimport Game from .background cimport BackgroundRenderer from .renderer cimport Renderer, Framebuffer from .shader cimport Shader -from .window cimport Window cdef class GameRenderer(Renderer): cdef Matrix game_mvp, interface_mvp, proj @@ -12,8 +11,8 @@ cdef class GameRenderer(Renderer): cdef BackgroundRenderer background_renderer cdef void load_background(self, background) except * - cdef void start(self, Game game) except * - cdef void render(self, Game game, Window window) except * + cdef void start(self, common) except * + cdef void render(self, Game game) except * cdef void render_game(self, Game game) except * cdef void render_text(self, texts) except * cdef void render_interface(self, interface, game_boss) except * diff --git a/pytouhou/ui/gamerenderer.pyx b/pytouhou/ui/gamerenderer.pyx --- a/pytouhou/ui/gamerenderer.pyx +++ b/pytouhou/ui/gamerenderer.pyx @@ -53,15 +53,16 @@ cdef class GameRenderer(Renderer): self.background_renderer = None - cdef void start(self, Game game): - self.proj = perspective(30, float(game.width) / float(game.height), + cdef void start(self, common): + self.proj = perspective(30, float(common.width) / float(common.height), 101010101./2010101., 101010101./10101.) game_view = setup_camera(0, 0, 1) self.game_mvp = game_view * self.proj - self.interface_mvp = ortho_2d(0., float(game.interface.width), float(game.interface.height), 0.) + self.interface_mvp = ortho_2d(0., float(common.interface.width), + float(common.interface.height), 0.) - cdef void render(self, Game game, Window window): + cdef void render(self, Game game): if not self.use_fixed_pipeline: self.framebuffer.bind() @@ -72,7 +73,7 @@ cdef class GameRenderer(Renderer): if not self.use_fixed_pipeline: self.passthrough_shader.bind() self.passthrough_shader.uniform_matrix('mvp', self.interface_mvp) - self.render_framebuffer(self.framebuffer, window) + self.render_framebuffer(self.framebuffer) cdef void render_game(self, Game game): diff --git a/pytouhou/ui/gamerunner.pyx b/pytouhou/ui/gamerunner.pyx --- a/pytouhou/ui/gamerunner.pyx +++ b/pytouhou/ui/gamerunner.pyx @@ -12,38 +12,44 @@ ## GNU General Public License for more details. ## +cimport cython + from pytouhou.lib cimport sdl from .window cimport Window, Runner from .gamerenderer cimport GameRenderer from .music import MusicPlayer, SFXPlayer, NullPlayer +from pytouhou.game.game cimport Game cdef class GameRunner(Runner): - cdef object game, background, con + cdef object background, con, resource_loader, keys, replay_level, common + cdef Game game cdef GameRenderer renderer cdef Window window - cdef object replay_level, save_keystates + cdef list save_keystates cdef bint skip - def __init__(self, Window window, resource_loader, bint skip=False, + def __init__(self, Window window, common, resource_loader, bint skip=False, con=None): self.renderer = GameRenderer(resource_loader, window.use_fixed_pipeline) + self.common = common + self.resource_loader = resource_loader self.window = window self.replay_level = None self.skip = skip self.con = con - self.width = window.width #XXX - self.height = window.height #XXX + self.width = common.interface.width + self.height = common.interface.height - def load_game(self, game=None, background=None, bgms=None, replay=None, save_keystates=None): + def load_game(self, Game game, background=None, bgms=None, replay=None, save_keystates=None): self.game = game self.background = background - self.renderer.texture_manager.load(game.resource_loader.instanced_anms.values()) + self.renderer.texture_manager.load(self.resource_loader.instanced_anms.values()) self.renderer.load_background(background) self.set_input(replay) @@ -57,15 +63,15 @@ cdef class GameRunner(Runner): null_player = NullPlayer() if bgms: - game.music = MusicPlayer(game.resource_loader, bgms) + game.music = MusicPlayer(self.resource_loader, bgms) game.music.play(0) else: game.music = null_player - game.sfx_player = SFXPlayer(game.resource_loader) if not self.skip else null_player + game.sfx_player = SFXPlayer(self.resource_loader) if not self.skip else null_player - def set_input(self, replay=None): + cdef void set_input(self, replay=None) except *: if not replay or not replay.levels[self.game.stage-1]: self.replay_level = None else: @@ -73,14 +79,24 @@ cdef class GameRunner(Runner): self.keys = self.replay_level.iter_keystates() + @cython.cdivision(True) + cdef void set_renderer_size(self, long width, long height) nogil: + runner_width = float(self.width) + runner_height = float(self.height) + + scale = min(width / runner_width, + height / runner_height) + + self.renderer.width = int(runner_width * scale) + self.renderer.height = int(runner_height * scale) + + self.renderer.x = (width - self.renderer.width) // 2 + self.renderer.y = (height - self.renderer.height) // 2 + + cdef void start(self) except *: - cdef long width, height - width = self.game.interface.width if self.game is not None else 640 - height = self.game.interface.height if self.game is not None else 480 - if width != self.width or height != self.height: - self.window.set_size(width, height) - - self.renderer.start(self.game) + self.set_renderer_size(self.width, self.height) + self.renderer.start(self.common) cdef bint update(self) except *: @@ -99,6 +115,7 @@ cdef class GameRunner(Runner): elif type_ == sdl.WINDOWEVENT: event_ = event[1] if event_ == sdl.WINDOWEVENT_RESIZED: + self.set_renderer_size(event[2], event[3]) self.window.set_size(event[2], event[3]) if self.game: if self.replay_level is None: @@ -129,7 +146,7 @@ cdef class GameRunner(Runner): if self.skip: self.set_input() self.skip = False - self.game.sfx_player = SFXPlayer(self.game.resource_loader) + self.game.sfx_player = SFXPlayer(self.resource_loader) if self.save_keystates is not None: self.save_keystates.append(keystate) @@ -141,5 +158,5 @@ cdef class GameRunner(Runner): self.game.interface.labels['framerate'].set_text('%.2ffps' % self.window.get_fps()) if not self.skip: - self.renderer.render(self.game, self.window) + self.renderer.render(self.game) return True diff --git a/pytouhou/ui/renderer.pxd b/pytouhou/ui/renderer.pxd --- a/pytouhou/ui/renderer.pxd +++ b/pytouhou/ui/renderer.pxd @@ -1,5 +1,4 @@ from cpython cimport PyObject -from .window cimport Window from pytouhou.lib.opengl cimport GLuint cdef struct Vertex: @@ -17,6 +16,7 @@ cdef class Renderer: cdef public texture_manager, font_manager cdef GLuint vbo, framebuffer_vbo cdef Vertex *vertex_buffer + cdef long x, y, width, height cdef bint use_fixed_pipeline #XXX @@ -26,7 +26,7 @@ cdef class Renderer: cdef void render_elements(self, elements) except * cdef void render_quads(self, rects, colors, texture) except * - cdef void render_framebuffer(self, Framebuffer fb, Window window) except * + cdef void render_framebuffer(self, Framebuffer fb) except * cdef class Framebuffer: diff --git a/pytouhou/ui/renderer.pyx b/pytouhou/ui/renderer.pyx --- a/pytouhou/ui/renderer.pyx +++ b/pytouhou/ui/renderer.pyx @@ -217,7 +217,7 @@ cdef class Renderer: glBindBuffer(GL_ARRAY_BUFFER, 0) - cdef void render_framebuffer(self, Framebuffer fb, Window window): + cdef void render_framebuffer(self, Framebuffer fb): cdef PassthroughVertex[4] buf cdef unsigned short indices[6] indices[:] = [0, 1, 2, 2, 3, 0] @@ -225,7 +225,7 @@ cdef class Renderer: assert not self.use_fixed_pipeline glBindFramebuffer(GL_FRAMEBUFFER, 0) - glViewport(window.x, window.y, window.width, window.height) + glViewport(self.x, self.y, self.width, self.height) glBlendFunc(GL_ONE, GL_ZERO) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) diff --git a/pytouhou/ui/window.pxd b/pytouhou/ui/window.pxd --- a/pytouhou/ui/window.pxd +++ b/pytouhou/ui/window.pxd @@ -1,4 +1,5 @@ from pytouhou.lib cimport sdl +from .gamerenderer cimport GameRenderer cdef class Clock: @@ -22,7 +23,6 @@ cdef class Runner: cdef class Window: cdef sdl.Window win cdef long fps_limit - cdef public long x, y, width, height cdef public bint use_fixed_pipeline cdef Runner runner cdef Clock clock diff --git a/pytouhou/ui/window.pyx b/pytouhou/ui/window.pyx --- a/pytouhou/ui/window.pyx +++ b/pytouhou/ui/window.pyx @@ -12,8 +12,6 @@ ## GNU General Public License for more details. ## -cimport cython - from pytouhou.lib.opengl cimport \ (glEnable, glHint, glEnableClientState, GL_TEXTURE_2D, GL_BLEND, GL_PERSPECTIVE_CORRECTION_HINT, GL_FOG_HINT, GL_NICEST, @@ -88,7 +86,7 @@ cdef class Runner: cdef class Window: - def __init__(self, tuple size=None, bint double_buffer=True, long fps_limit=-1, + def __init__(self, bint double_buffer=True, long fps_limit=-1, bint fixed_pipeline=False, bint sound=True): self.fps_limit = fps_limit self.use_fixed_pipeline = fixed_pipeline @@ -99,15 +97,13 @@ cdef class Window: sdl.gl_set_attribute(sdl.GL_DOUBLEBUFFER, int(double_buffer)) sdl.gl_set_attribute(sdl.GL_DEPTH_SIZE, 24) - self.width, self.height = size if size is not None else (640, 480) - flags = sdl.WINDOW_OPENGL | sdl.WINDOW_SHOWN if not self.use_fixed_pipeline: flags |= sdl.WINDOW_RESIZABLE self.win = sdl.Window('PyTouhou', sdl.WINDOWPOS_CENTERED, sdl.WINDOWPOS_CENTERED, - self.width, self.height, + 640, 480, #XXX flags) self.win.gl_create_context() @@ -128,22 +124,9 @@ cdef class Window: self.clock = Clock(self.fps_limit) - @cython.cdivision(True) cdef void set_size(self, int width, int height) nogil: self.win.set_window_size(width, height) - runner_width = float(self.runner.width) - runner_height = float(self.runner.height) - - scale = min(width / runner_width, - height / runner_height) - - self.width = int(runner_width * scale) - self.height = int(runner_height * scale) - - self.x = (width - self.width) // 2 - self.y = (height - self.height) // 2 - cpdef set_runner(self, Runner runner=None): self.runner = runner