13
|
1 from io import BytesIO
|
|
2 import os
|
|
3 import struct
|
|
4 from itertools import chain
|
|
5
|
|
6 from pytouhou.utils.interpolator import Interpolator
|
15
|
7 from pytouhou.game.sprite import Sprite
|
13
|
8
|
|
9
|
|
10 class Background(object):
|
15
|
11 def __init__(self, stage, anim):
|
|
12 self.stage = stage
|
|
13 self.anim = anim
|
13
|
14 self.objects = []
|
|
15 self.object_instances = []
|
|
16 self._uvs = b''
|
|
17 self._vertices = b''
|
15
|
18 self.nb_vertices = 0
|
|
19
|
13
|
20 self.build_objects()
|
|
21 self.build_object_instances()
|
|
22
|
|
23
|
|
24 def build_object_instances(self):
|
|
25 self.object_instances = []
|
|
26 for obj, ox, oy, oz in self.stage.object_instances:
|
|
27 obj_id = self.stage.objects.index(obj)
|
|
28
|
|
29 obj_instance = []
|
|
30 for face_vertices, face_uvs in self.objects[obj_id]:
|
|
31 obj_instance.append((tuple((x + ox, y + oy, z + oz)
|
|
32 for x, y, z in face_vertices),
|
|
33 face_uvs))
|
|
34 self.object_instances.append(obj_instance)
|
|
35 # Z-sorting
|
|
36 def keyfunc(obj):
|
|
37 return min(z for face in obj for x, y, z in face[0])
|
|
38 self.object_instances.sort(key=keyfunc, reverse=True)
|
|
39
|
|
40
|
|
41 def object_instances_to_vertices_uvs(self):
|
|
42 vertices = tuple(vertex for obj in self.object_instances
|
|
43 for face in obj for vertex in face[0])
|
|
44 uvs = tuple(uv for obj in self.object_instances
|
|
45 for face in obj for uv in face[1])
|
|
46 return vertices, uvs
|
|
47
|
|
48
|
|
49 def build_objects(self):
|
|
50 self.objects = []
|
|
51 for i, obj in enumerate(self.stage.objects):
|
|
52 faces = []
|
15
|
53 for script_index, ox, oy, oz, width_override, height_override in obj.quads:
|
|
54 sprite = Sprite(self.anim, script_index)
|
|
55 sprite.update(0, width_override, height_override)
|
|
56 uvs, vertices = sprite._uvs, tuple((x + ox, y + oy, z + oz) for x, y, z in sprite._vertices)
|
13
|
57 faces.append((vertices, uvs))
|
|
58 self.objects.append(faces)
|
|
59
|
|
60
|
|
61 def update(self, frame):
|
|
62 if not self._uvs or not self._vertices:
|
|
63 vertices, uvs = self.object_instances_to_vertices_uvs()
|
|
64 self.nb_vertices = len(vertices)
|
|
65 vertices_format = 'f' * (3 * self.nb_vertices)
|
|
66 uvs_format = 'f' * (2 * self.nb_vertices)
|
|
67 self._vertices = struct.pack(vertices_format, *chain(*vertices))
|
|
68 self._uvs = struct.pack(uvs_format, *chain(*uvs))
|
|
69
|
|
70 self.position_interpolator = Interpolator((0, 0, 0))
|
|
71 self.fog_interpolator = Interpolator((0, 0, 0, 0, 0))
|
|
72 self.position2_interpolator = Interpolator((0, 0, 0))
|
|
73
|
|
74 for frame_num, message_type, args in self.stage.script:
|
|
75 if frame_num == frame:
|
14
|
76 if message_type == 0:
|
|
77 self.position_interpolator.set_interpolation_start(frame_num, args)
|
|
78 elif message_type == 1:
|
13
|
79 self.fog_interpolator.set_interpolation_end_values(args)
|
14
|
80 elif message_type == 2:
|
|
81 self.position2_interpolator.set_interpolation_end_values(args)
|
13
|
82 elif message_type == 3:
|
|
83 duration, = args
|
|
84 self.position2_interpolator.set_interpolation_end_frame(frame_num + duration)
|
|
85 elif message_type == 4:
|
|
86 duration, = args
|
|
87 self.fog_interpolator.set_interpolation_end_frame(frame_num + duration)
|
|
88 if frame_num > frame and message_type == 0:
|
|
89 self.position_interpolator.set_interpolation_end(frame_num, args)
|
|
90 break
|
|
91
|
|
92 self.position2_interpolator.update(frame)
|
|
93 self.fog_interpolator.update(frame)
|
|
94 self.position_interpolator.update(frame)
|
|
95
|