Mercurial > touhou
comparison pytouhou/vm/msgrunner.py @ 286:4838e9bab0f9
Implement dialogs (MSG files).
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sun, 12 Feb 2012 16:06:03 +0100 |
parents | |
children | 61adb5453e46 |
comparison
equal
deleted
inserted
replaced
285:2100276c289d | 286:4838e9bab0f9 |
---|---|
1 # -*- encoding: utf-8 -*- | |
2 ## | |
3 ## Copyright (C) 2012 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | |
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 | |
16 from pytouhou.utils.helpers import get_logger | |
17 | |
18 from pytouhou.vm.common import MetaRegistry, instruction | |
19 from pytouhou.game.face import Face | |
20 | |
21 logger = get_logger(__name__) | |
22 | |
23 | |
24 class MSGRunner(object): | |
25 __metaclass__ = MetaRegistry | |
26 __slots__ = ('_msg', '_game', 'frame', 'sleep_time', 'allow_skip', | |
27 'frozen', 'faces', 'ended', 'instruction_pointer') | |
28 | |
29 def __init__(self, msg, script, game): | |
30 self._msg = msg.msgs[script + 10 * (game.players[0].state.character // 2)] | |
31 self._game = game | |
32 self.frame = 0 | |
33 self.sleep_time = 0 | |
34 self.allow_skip = True | |
35 self.frozen = False | |
36 | |
37 self.faces = [None, None] | |
38 game.msg_sprites = self.objects | |
39 self.ended = False | |
40 | |
41 self.instruction_pointer = 0 | |
42 | |
43 | |
44 def objects(self): | |
45 return [face for face in self.faces if face] if not self.ended else [] | |
46 | |
47 | |
48 def run_iteration(self): | |
49 while True: | |
50 if self.ended: | |
51 return False | |
52 | |
53 try: | |
54 frame, instr_type, args = self._msg[self.instruction_pointer] | |
55 except IndexError: | |
56 self.end() | |
57 return False | |
58 | |
59 if frame > self.frame: | |
60 break | |
61 else: | |
62 self.instruction_pointer += 1 | |
63 | |
64 if frame == self.frame: | |
65 try: | |
66 callback = self._handlers[instr_type] | |
67 except KeyError: | |
68 logger.warn('unhandled msg opcode %d (args: %r)', instr_type, args) | |
69 else: | |
70 callback(self, *args) | |
71 | |
72 if not self.frozen: | |
73 if self.sleep_time > 0: | |
74 self.sleep_time -= 1 | |
75 else: | |
76 self.frame += 1 | |
77 | |
78 for face in self.faces: | |
79 if face: | |
80 face.update() | |
81 | |
82 return True | |
83 | |
84 | |
85 def skip(self): | |
86 self.sleep_time = 0 | |
87 | |
88 | |
89 def end(self): | |
90 self._game.msg_runner = None | |
91 self._game.msg_wait = False | |
92 self.ended = True | |
93 | |
94 | |
95 @instruction(0) | |
96 def unknown0(self): | |
97 if self.allow_skip: | |
98 raise Exception #TODO: seems to crash the game, but why? | |
99 self.end() | |
100 | |
101 | |
102 @instruction(1) | |
103 def enter(self, side, effect): | |
104 self.faces[side] = Face(self._game.msg_anm_wrapper, effect, side) | |
105 | |
106 | |
107 @instruction(2) | |
108 def change_face(self, side, index): | |
109 face = self.faces[side] | |
110 if face: | |
111 face.load(index) | |
112 | |
113 | |
114 @instruction(4) | |
115 def pause(self, duration): | |
116 self.sleep_time = duration | |
117 | |
118 | |
119 @instruction(5) | |
120 def animate(self, side, effect): | |
121 face = self.faces[side] | |
122 if face: | |
123 face.animate(effect) | |
124 | |
125 | |
126 @instruction(6) | |
127 def spawn_enemy_sprite(self): | |
128 self._game.msg_wait = False | |
129 | |
130 | |
131 @instruction(10) | |
132 def freeze(self): | |
133 self.frozen = True | |
134 | |
135 | |
136 @instruction(13) | |
137 def set_allow_skip(self, boolean): | |
138 self.allow_skip = bool(boolean) |