Mercurial > touhou
view pytouhou/game/background.py @ 13:58bc264aba38
Refactor
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Fri, 05 Aug 2011 13:23:33 +0200 |
parents | |
children | 07a7f28c8aaa |
line wrap: on
line source
from io import BytesIO import os import struct from itertools import chain from pytouhou.utils.matrix import Matrix from pytouhou.utils.interpolator import Interpolator from pytouhou.formats.std import Stage from pytouhou.formats.anm0 import Animations class Background(object): def __init__(self, archive, stage_num): self.stage = Stage.read(BytesIO(archive.extract('stage%d.std' % stage_num))) self.anim = Animations.read(BytesIO(archive.extract('stg%dbg.anm' % stage_num))) texture_components = [None, None] for i, component_name in ((0, self.anim.first_name), (1, self.anim.secondary_name)): if component_name: texture_components[i] = BytesIO(archive.extract(os.path.basename(component_name))) self.texture_components = texture_components self.objects = [] self.object_instances = [] self._uvs = b'' self._vertices = b'' self.build_objects() self.build_object_instances() def build_object_instances(self): self.object_instances = [] for obj, ox, oy, oz in self.stage.object_instances: obj_id = self.stage.objects.index(obj) obj_instance = [] for face_vertices, face_uvs in self.objects[obj_id]: obj_instance.append((tuple((x + ox, y + oy, z + oz) for x, y, z in face_vertices), face_uvs)) self.object_instances.append(obj_instance) # Z-sorting def keyfunc(obj): return min(z for face in obj for x, y, z in face[0]) self.object_instances.sort(key=keyfunc, reverse=True) def object_instances_to_vertices_uvs(self): vertices = tuple(vertex for obj in self.object_instances for face in obj for vertex in face[0]) uvs = tuple(uv for obj in self.object_instances for face in obj for uv in face[1]) return vertices, uvs def build_objects(self): self.objects = [] for i, obj in enumerate(self.stage.objects): faces = [] for script_index, x, y, z, width_override, height_override in obj.quads: #TODO: refactor vertices = [] uvs = [] vertmat = Matrix() vertmat.data[0][0] = -.5 vertmat.data[1][0] = -.5 vertmat.data[0][1] = .5 vertmat.data[1][1] = -.5 vertmat.data[0][2] = .5 vertmat.data[1][2] = .5 vertmat.data[0][3] = -.5 vertmat.data[1][3] = .5 for i in range(4): vertmat.data[2][i] = 0. vertmat.data[3][i] = 1. properties = {} for time, instr_type, data in self.anim.scripts[script_index]: if instr_type == 15: properties[15] = b'' break elif time == 0: #TODO properties[instr_type] = data #if 15 not in properties: #TODO: Skip properties # continue #TODO: properties 3 and 4 if 1 in properties: tx, ty, tw, th = self.anim.sprites[struct.unpack('<I', properties[1])[0]] width, height = 1., 1. if 2 in properties: width, height = struct.unpack('<ff', properties[2]) width = width_override or width * tw height = height_override or height * th transform = Matrix.get_scaling_matrix(width, height, 1.) if 7 in properties: transform = Matrix.get_scaling_matrix(-1., 1., 1.).mult(transform) if 9 in properties: rx, ry, rz = struct.unpack('<fff', properties[9]) transform = Matrix.get_rotation_matrix(-rx, 'x').mult(transform) transform = Matrix.get_rotation_matrix(ry, 'y').mult(transform) transform = Matrix.get_rotation_matrix(-rz, 'z').mult(transform) #TODO: minus, really? if 23 in properties: # Reposition transform = Matrix.get_translation_matrix(width / 2., height / 2., 0.).mult(transform) vertmat = transform.mult(vertmat) uvs = [(tx / self.anim.size[0], 1. - (ty / self.anim.size[1])), ((tx + tw) / self.anim.size[0], 1. - (ty / self.anim.size[1])), ((tx + tw) / self.anim.size[0], 1. - ((ty + th) / self.anim.size[1])), (tx / self.anim.size[0], 1. - ((ty + th) / self.anim.size[1]))] for i in xrange(4): w = vertmat.data[3][i] vertices.append((vertmat.data[0][i] / w + x, vertmat.data[1][i] / w + y, vertmat.data[2][i] / w + z)) faces.append((vertices, uvs)) self.objects.append(faces) def update(self, frame): if not self._uvs or not self._vertices: vertices, uvs = self.object_instances_to_vertices_uvs() self.nb_vertices = len(vertices) vertices_format = 'f' * (3 * self.nb_vertices) uvs_format = 'f' * (2 * self.nb_vertices) self._vertices = struct.pack(vertices_format, *chain(*vertices)) self._uvs = struct.pack(uvs_format, *chain(*uvs)) self.position_interpolator = Interpolator((0, 0, 0)) self.fog_interpolator = Interpolator((0, 0, 0, 0, 0)) self.position2_interpolator = Interpolator((0, 0, 0)) for frame_num, message_type, args in self.stage.script: if frame_num == frame: if message_type == 1: self.fog_interpolator.set_interpolation_end_values(args) elif message_type == 3: duration, = args self.position2_interpolator.set_interpolation_end_frame(frame_num + duration) elif message_type == 4: duration, = args self.fog_interpolator.set_interpolation_end_frame(frame_num + duration) elif message_type == 2: self.position2_interpolator.set_interpolation_end_values(args) if frame_num <= frame and message_type == 0: self.position_interpolator.set_interpolation_start(frame_num, args) if frame_num > frame and message_type == 0: self.position_interpolator.set_interpolation_end(frame_num, args) break self.position2_interpolator.update(frame) self.fog_interpolator.update(frame) self.position_interpolator.update(frame)