comparison pytouhou/opengl/gamerenderer.py @ 108:2a03940deea3

Move everything graphical to pytouhou.opengl!
author Thibaut Girka <thib@sitedethib.com>
date Tue, 06 Sep 2011 00:26:13 +0200
parents
children 340fcda8e64a
comparison
equal deleted inserted replaced
107:5d9052b9a4e8 108:2a03940deea3
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 import struct
16 from itertools import chain
17
18 import pygame
19
20 import OpenGL
21 OpenGL.FORWARD_COMPATIBLE_ONLY = True
22 from OpenGL.GL import *
23 from OpenGL.GLU import *
24
25
26 from pytouhou.opengl.texture import TextureManager
27 from pytouhou.opengl.sprite import get_sprite_rendering_data
28 from pytouhou.opengl.background import get_background_rendering_data
29
30
31 class GameRenderer(object):
32 def __init__(self, resource_loader, game=None, background=None):
33 self.texture_manager = TextureManager(resource_loader)
34
35 self.game = game
36 self.background = background
37
38 self.window = None
39
40
41 def start(self, width=384, height=448):
42 # Initialize pygame
43 pygame.init()
44 self.window = pygame.display.set_mode((width, height),
45 pygame.OPENGL | pygame.DOUBLEBUF)
46
47 # Initialize OpenGL
48 glMatrixMode(GL_PROJECTION)
49 glLoadIdentity()
50 gluPerspective(30, float(width)/float(height),
51 101010101./2010101., 101010101./10101.)
52
53 glEnable(GL_BLEND)
54 glEnable(GL_TEXTURE_2D)
55 glEnable(GL_FOG)
56 glHint(GL_FOG_HINT, GL_NICEST)
57 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
58 glEnableClientState(GL_COLOR_ARRAY)
59 glEnableClientState(GL_VERTEX_ARRAY)
60 glEnableClientState(GL_TEXTURE_COORD_ARRAY)
61
62
63 def render_elements(self, elements):
64 texture_manager = self.texture_manager
65 objects_by_texture = {}
66 for element in elements:
67 sprite = element._sprite
68 if sprite:
69 ox, oy = element.x, element.y
70 key, (vertices, uvs, colors) = get_sprite_rendering_data(sprite)
71 rec = objects_by_texture.setdefault(key, ([], [], []))
72 vertices = ((x + ox, y + oy, z) for x, y, z in vertices)
73 rec[0].extend(vertices)
74 rec[1].extend(uvs)
75 rec[2].extend(colors)
76
77 for (texture_key, blendfunc), (vertices, uvs, colors) in objects_by_texture.items():
78 nb_vertices = len(vertices)
79 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc])
80 glBindTexture(GL_TEXTURE_2D, texture_manager[texture_key])
81 glVertexPointer(3, GL_FLOAT, 0, struct.pack(str(3 * nb_vertices) + 'f', *chain(*vertices)))
82 glTexCoordPointer(2, GL_FLOAT, 0, struct.pack(str(2 * nb_vertices) + 'f', *chain(*uvs)))
83 glColorPointer(4, GL_UNSIGNED_BYTE, 0, struct.pack(str(4 * nb_vertices) + 'B', *chain(*colors)))
84 glDrawArrays(GL_QUADS, 0, nb_vertices)
85
86
87 def render(self):
88 glClear(GL_DEPTH_BUFFER_BIT)
89
90 back = self.background
91 game = self.game
92 texture_manager = self.texture_manager
93
94 if back is not None:
95 fog_b, fog_g, fog_r, _, fog_start, fog_end = back.fog_interpolator.values
96 x, y, z = back.position_interpolator.values
97 dx, dy, dz = back.position2_interpolator.values
98
99 glFogi(GL_FOG_MODE, GL_LINEAR)
100 glFogf(GL_FOG_START, fog_start)
101 glFogf(GL_FOG_END, fog_end)
102 glFogfv(GL_FOG_COLOR, (fog_r / 255., fog_g / 255., fog_b / 255., 1.))
103
104 glMatrixMode(GL_MODELVIEW)
105 glLoadIdentity()
106 # Some explanations on the magic constants:
107 # 192. = 384. / 2. = width / 2.
108 # 224. = 448. / 2. = height / 2.
109 # 835.979370 = 224./math.tan(math.radians(15)) = (height/2.)/math.tan(math.radians(fov/2))
110 # This is so that objects on the (O, x, y) plane use pixel coordinates
111 gluLookAt(192., 224., - 835.979370 * dz,
112 192. + dx, 224. - dy, 0., 0., -1., 0.)
113 glTranslatef(-x, -y, -z)
114
115 glEnable(GL_DEPTH_TEST)
116 for (texture_key, blendfunc), (nb_vertices, vertices, uvs, colors) in get_background_rendering_data(back):
117 glBlendFunc(GL_SRC_ALPHA, (GL_ONE_MINUS_SRC_ALPHA, GL_ONE)[blendfunc])
118 glBindTexture(GL_TEXTURE_2D, texture_manager[texture_key])
119 glVertexPointer(3, GL_FLOAT, 0, vertices)
120 glTexCoordPointer(2, GL_FLOAT, 0, uvs)
121 glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors)
122 glDrawArrays(GL_QUADS, 0, nb_vertices)
123 glDisable(GL_DEPTH_TEST)
124 else:
125 glClear(GL_COLOR_BUFFER_BIT)
126
127
128 if game is not None:
129 glMatrixMode(GL_MODELVIEW)
130 glLoadIdentity()
131 # Some explanations on the magic constants:
132 # 192. = 384. / 2. = width / 2.
133 # 224. = 448. / 2. = height / 2.
134 # 835.979370 = 224./math.tan(math.radians(15)) = (height/2.)/math.tan(math.radians(fov/2))
135 # This is so that objects on the (O, x, y) plane use pixel coordinates
136 gluLookAt(192., 224., - 835.979370,
137 192., 224., 0., 0., -1., 0.)
138
139 glDisable(GL_FOG)
140 self.render_elements(game.enemies)
141 self.render_elements(game.game_state.bullets)
142 glEnable(GL_FOG)
143