changeset 503:c622eaf64428

Optimize GameRunner some more, fix replay, and remove Window dependency in Renderer.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 04 Oct 2013 14:27:11 +0200
parents 3d3285918ba1
children 69c73023f7a0
files eosd pytouhou/games/eosd.py pytouhou/ui/gamerenderer.pxd pytouhou/ui/gamerenderer.pyx pytouhou/ui/gamerunner.pyx pytouhou/ui/renderer.pxd pytouhou/ui/renderer.pyx pytouhou/ui/window.pxd pytouhou/ui/window.pyx
diffstat 9 files changed, 63 insertions(+), 62 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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)
 
 
 
--- 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 *
--- 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):
--- 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
--- 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:
--- 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)
 
--- 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
--- 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