Mercurial > touhou
comparison eclviewer.py @ 18:ca26a84916cb
Add preliminary ECL viewer/interpreter.
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Tue, 09 Aug 2011 11:40:48 +0200 |
parents | |
children | ca7886296d4a |
comparison
equal
deleted
inserted
replaced
17:d940d004b840 | 18:ca26a84916cb |
---|---|
1 #!/usr/bin/env python | |
2 | |
3 import sys | |
4 import os | |
5 | |
6 import struct | |
7 from math import degrees, radians | |
8 from io import BytesIO | |
9 from itertools import chain | |
10 | |
11 import pygame | |
12 | |
13 from pytouhou.formats.pbg3 import PBG3 | |
14 from pytouhou.formats.std import Stage | |
15 from pytouhou.formats.ecl import ECL | |
16 from pytouhou.formats.anm0 import Animations | |
17 from pytouhou.game.background import Background | |
18 from pytouhou.game.enemymanager import EnemyManager | |
19 from pytouhou.opengl.texture import TextureManager | |
20 | |
21 import OpenGL | |
22 OpenGL.FORWARD_COMPATIBLE_ONLY = True | |
23 from OpenGL.GL import * | |
24 from OpenGL.GLU import * | |
25 | |
26 | |
27 def main(path, stage_num): | |
28 # Initialize pygame | |
29 pygame.init() | |
30 window = pygame.display.set_mode((384, 448), pygame.OPENGL | pygame.DOUBLEBUF) | |
31 | |
32 # Initialize OpenGL | |
33 glMatrixMode(GL_PROJECTION) | |
34 glLoadIdentity() | |
35 gluPerspective(30, float(window.get_width())/window.get_height(), 101010101./2010101., 101010101./10101.) | |
36 | |
37 glEnable(GL_BLEND) | |
38 glEnable(GL_TEXTURE_2D) | |
39 glEnable(GL_FOG) | |
40 glHint(GL_FOG_HINT, GL_NICEST) | |
41 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST) | |
42 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) | |
43 glEnableClientState(GL_VERTEX_ARRAY) | |
44 glEnableClientState(GL_TEXTURE_COORD_ARRAY) | |
45 | |
46 # Load data | |
47 with open(path, 'rb') as file: | |
48 archive = PBG3.read(file) | |
49 texture_manager = TextureManager(archive) | |
50 | |
51 stage = Stage.read(BytesIO(archive.extract('stage%d.std' % stage_num)), stage_num) | |
52 | |
53 ecl = ECL.read(BytesIO(archive.extract('ecldata%d.ecl' % stage_num))) | |
54 enemies_anim = Animations.read(BytesIO(archive.extract('stg%denm.anm' % stage_num))) | |
55 anims = [enemies_anim] | |
56 try: | |
57 enemies2_anim = Animations.read(BytesIO(archive.extract('stg%denm2.anm' % stage_num))) | |
58 except KeyError: | |
59 pass | |
60 else: | |
61 anims.append(enemies_anim) | |
62 enemy_manager = EnemyManager(stage, anims, ecl) | |
63 | |
64 background_anim = Animations.read(BytesIO(archive.extract('stg%dbg.anm' % stage_num))) | |
65 background = Background(stage, background_anim) | |
66 | |
67 print(enemy_manager.stage.name) | |
68 | |
69 frame = 0 | |
70 | |
71 # Main loop | |
72 clock = pygame.time.Clock() | |
73 while True: | |
74 # Check events | |
75 for event in pygame.event.get(): | |
76 if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key in (pygame.K_ESCAPE, pygame.K_q)): | |
77 sys.exit(0) | |
78 elif event.type == pygame.KEYDOWN: | |
79 if event.key == pygame.K_RETURN and event.mod & pygame.KMOD_ALT: | |
80 pygame.display.toggle_fullscreen() | |
81 | |
82 # Update game | |
83 enemy_manager.update(frame) | |
84 background.update(frame) | |
85 | |
86 # Draw everything | |
87 glClear(GL_COLOR_BUFFER_BIT) | |
88 | |
89 fog_b, fog_g, fog_r, _, fog_start, fog_end = background.fog_interpolator.values | |
90 x, y, z = background.position_interpolator.values | |
91 unknownx, dy, dz = background.position2_interpolator.values | |
92 | |
93 glFogi(GL_FOG_MODE, GL_LINEAR) | |
94 glFogf(GL_FOG_START, fog_start) | |
95 glFogf(GL_FOG_END, fog_end) | |
96 glFogfv(GL_FOG_COLOR, (fog_r / 255., fog_g / 255., fog_b / 255., 1.)) | |
97 | |
98 #TODO | |
99 glMatrixMode(GL_MODELVIEW) | |
100 glLoadIdentity() | |
101 # Some explanations on the magic constants: | |
102 # 192. = 384. / 2. = width / 2. | |
103 # 224. = 448. / 2. = height / 2. | |
104 # 835.979370 = 224./math.tan(math.radians(15)) = (height/2.)/math.tan(math.radians(fov/2)) | |
105 # This is so that objects on the (O, x, y) plane use pixel coordinates | |
106 gluLookAt(192., 224., - 835.979370 * dz, | |
107 192., 224. - dy, 750 - 835.979370 * dz, 0., -1., 0.) #TODO: 750 might not be accurate | |
108 #print(glGetFloat(GL_MODELVIEW_MATRIX)) | |
109 glTranslatef(-x, -y, -z) | |
110 | |
111 for texture_key, (nb_vertices, vertices, uvs) in background.objects_by_texture.items(): | |
112 glBindTexture(GL_TEXTURE_2D, texture_manager[texture_key]) | |
113 glVertexPointer(3, GL_FLOAT, 0, vertices) | |
114 glTexCoordPointer(2, GL_FLOAT, 0, uvs) | |
115 glDrawArrays(GL_QUADS, 0, nb_vertices) | |
116 | |
117 #TODO | |
118 glMatrixMode(GL_MODELVIEW) | |
119 glLoadIdentity() | |
120 # Some explanations on the magic constants: | |
121 # 192. = 384. / 2. = width / 2. | |
122 # 224. = 448. / 2. = height / 2. | |
123 # 835.979370 = 224./math.tan(math.radians(15)) = (height/2.)/math.tan(math.radians(fov/2)) | |
124 # This is so that objects on the (O, x, y) plane use pixel coordinates | |
125 gluLookAt(192., 224., - 835.979370, | |
126 192., 224., 750 - 835.979370, 0., -1., 0.) #TODO: 750 might not be accurate | |
127 | |
128 glDisable(GL_FOG) | |
129 for texture_key, (nb_vertices, vertices, uvs) in enemy_manager.objects_by_texture.items(): | |
130 glBindTexture(GL_TEXTURE_2D, texture_manager[texture_key]) | |
131 glVertexPointer(3, GL_FLOAT, 0, vertices) | |
132 glTexCoordPointer(2, GL_FLOAT, 0, uvs) | |
133 glDrawArrays(GL_QUADS, 0, nb_vertices) | |
134 glEnable(GL_FOG) | |
135 | |
136 pygame.display.flip() | |
137 clock.tick(120) | |
138 frame += 1 | |
139 | |
140 | |
141 | |
142 try: | |
143 file_path, stage_num = sys.argv[1:] | |
144 stage_num = int(stage_num) | |
145 except ValueError: | |
146 print('Usage: %s std_dat_path stage_num' % sys.argv[0]) | |
147 else: | |
148 main(file_path, stage_num) | |
149 |