Mercurial > touhou
view pytouhou/game/background.py @ 14:07a7f28c8aaa
Minor refactoring
author | Thibaut Girka <thib@sitedethib.com> |
---|---|
date | Fri, 05 Aug 2011 14:54:32 +0200 |
parents | 58bc264aba38 |
children | 07fba4e1da65 |
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))) 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 == 0: self.position_interpolator.set_interpolation_start(frame_num, args) elif message_type == 1: self.fog_interpolator.set_interpolation_end_values(args) elif message_type == 2: self.position2_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) 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)