comparison pytouhou/ui/gamerunner.pyx @ 423:d8630c086926

Replace Pyglet with our own Cython OpenGL wrapper.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Tue, 16 Jul 2013 21:07:15 +0200
parents pytouhou/ui/gamerunner.py@52829ebe2561
children f4d76d3d6f2a
comparison
equal deleted inserted replaced
422:52829ebe2561 423:d8630c086926
1 # -*- encoding: utf-8 -*-
2 ##
3 ## Copyright (C) 2011 Thibaut Girka <thib@sitedethib.com>
4 ##
5 ## This program is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published
7 ## by the Free Software Foundation; version 3 only.
8 ##
9 ## This program is distributed in the hope that it will be useful,
10 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ## GNU General Public License for more details.
13 ##
14
15 from pytouhou.lib import sdl
16
17 from pytouhou.lib.opengl cimport \
18 (glMatrixMode, glEnable, glDisable, glViewport, glScissor,
19 glLoadMatrixf, glGenBuffers, glDeleteBuffers, GL_MODELVIEW,
20 GL_FOG, GL_SCISSOR_TEST)
21
22 from pytouhou.utils.helpers import get_logger
23 from pytouhou.utils.maths cimport perspective, setup_camera, ortho_2d
24 from pytouhou.utils.matrix cimport matrix_to_floats
25
26 from .gamerenderer import GameRenderer
27 from .background import BackgroundRenderer
28 from .music import MusicPlayer, SFXPlayer, NullPlayer
29 from .shaders.eosd import GameShader, BackgroundShader
30
31
32 logger = get_logger(__name__)
33
34
35 class GameRunner(GameRenderer):
36 def __init__(self, window, resource_loader, replay=None, skip=False):
37 self.use_fixed_pipeline = window.use_fixed_pipeline #XXX
38
39 GameRenderer.__init__(self, resource_loader)
40
41 self.window = window
42 self.replay_level = None
43 self.skip = skip
44 self.keystate = 0
45
46 self.width = window.width #XXX
47 self.height = window.height #XXX
48
49 if not self.use_fixed_pipeline:
50 self.game_shader = GameShader()
51 self.background_shader = BackgroundShader()
52 self.interface_shader = self.game_shader
53
54
55 def load_game(self, game=None, background=None, bgms=None, replay=None, save_keystates=None):
56 self.game = game
57 self.background = background
58
59 self.texture_manager.preload(game.resource_loader.instanced_anms.values())
60
61 if background:
62 self.background_renderer = BackgroundRenderer(self.texture_manager, self.use_fixed_pipeline)
63 self.background_renderer.prerender(background)
64
65 self.set_input(replay)
66 if replay and replay.levels[game.stage - 1]:
67 game.players[0].state.lives = self.replay_level.lives
68 game.players[0].state.power = self.replay_level.power
69 game.players[0].state.bombs = self.replay_level.bombs
70 game.difficulty = self.replay_level.difficulty
71
72 self.save_keystates = save_keystates
73
74 game.music = MusicPlayer(game.resource_loader, bgms)
75 game.music.play(0)
76 game.sfx_player = SFXPlayer(game.resource_loader) if not self.skip else NullPlayer()
77
78
79 def set_input(self, replay=None):
80 if not replay or not replay.levels[self.game.stage-1]:
81 self.replay_level = None
82 else:
83 self.replay_level = replay.levels[self.game.stage-1]
84 self.keys = self.replay_level.iter_keystates()
85
86
87 def start(self):
88 width = self.game.interface.width if self.game else 640
89 height = self.game.interface.height if self.game else 480
90 if (width, height) != (self.width, self.height):
91 self.window.set_size(width, height)
92
93 self.proj = perspective(30, float(self.game.width) / float(self.game.height),
94 101010101./2010101., 101010101./10101.)
95 game_view = setup_camera(0, 0, 1)
96 self.game_mvp = game_view * self.proj
97 self.interface_mvp = ortho_2d(0., float(self.width), float(self.height), 0.)
98
99
100 def finish(self):
101 #TODO: actually clean after buffers are not needed anymore.
102 #if not self.use_fixed_pipeline:
103 # vbo_array = (c_uint * 2)(self.vbo, self.back_vbo)
104 # glDeleteBuffers(2, vbo_array)
105 pass
106
107
108 def update(self):
109 if self.background:
110 self.background.update(self.game.frame)
111 for event in sdl.poll_events():
112 type_ = event[0]
113 if type_ == sdl.KEYDOWN:
114 scancode = event[1]
115 if scancode == sdl.SCANCODE_ESCAPE:
116 return False #TODO: implement the pause.
117 elif type_ == sdl.QUIT:
118 return False
119 if self.game:
120 if not self.replay_level:
121 #TODO: allow user settings
122 keys = sdl.get_keyboard_state()
123 keystate = 0
124 if keys[sdl.SCANCODE_Z]:
125 keystate |= 1
126 if keys[sdl.SCANCODE_X]:
127 keystate |= 2
128 if keys[sdl.SCANCODE_LSHIFT]:
129 keystate |= 4
130 if keys[sdl.SCANCODE_UP]:
131 keystate |= 16
132 if keys[sdl.SCANCODE_DOWN]:
133 keystate |= 32
134 if keys[sdl.SCANCODE_LEFT]:
135 keystate |= 64
136 if keys[sdl.SCANCODE_RIGHT]:
137 keystate |= 128
138 if keys[sdl.SCANCODE_LCTRL]:
139 keystate |= 256
140 else:
141 try:
142 keystate = self.keys.next()
143 except StopIteration:
144 keystate = 0
145 if self.skip:
146 self.set_input()
147 self.skip = False
148 self.game.sfx_player = SFXPlayer(self.game.resource_loader)
149
150 if self.save_keystates is not None:
151 self.save_keystates.append(keystate)
152
153 self.game.run_iter(keystate)
154 if not self.skip:
155 self.render_game()
156 self.render_interface()
157 return True
158
159
160 def render_game(self):
161 # Switch to game projection
162 #TODO: move that to GameRenderer?
163 x, y = self.game.interface.game_pos
164 glViewport(x, y, self.game.width, self.game.height)
165 glScissor(x, y, self.game.width, self.game.height)
166 glEnable(GL_SCISSOR_TEST)
167
168 GameRenderer.render(self)
169
170 glDisable(GL_SCISSOR_TEST)
171
172
173 def render_interface(self):
174 interface = self.game.interface
175 interface.labels['framerate'].set_text('%.2ffps' % self.window.clock.get_fps())
176
177 if self.use_fixed_pipeline:
178 glMatrixMode(GL_MODELVIEW)
179 glLoadMatrixf(matrix_to_floats(self.interface_mvp))
180 glDisable(GL_FOG)
181 else:
182 self.interface_shader.bind()
183 #self.interface_shader.uniform_matrixf('mvp', matrix_to_floats(self.interface_mvp))
184 self.interface_shader.uniform_matrixf('mvp', self.interface_mvp.get_c_data())
185 glViewport(0, 0, self.width, self.height)
186
187 items = [item for item in interface.items if item.anmrunner and item.anmrunner.running]
188 labels = interface.labels.values()
189
190 if items:
191 # Redraw all the interface
192 self.render_elements(items)
193 else:
194 # Redraw only changed labels
195 labels = [label for label in labels if label.changed]
196
197 self.render_elements(interface.level_start)
198
199 if self.game.boss:
200 self.render_elements(interface.boss_items)
201
202 self.render_elements(labels)
203 for label in labels:
204 label.changed = False
205