Mercurial > touhou
comparison pytouhou/games/eosd/game.py @ 597:244c99c568c8
Don’t hardcode the available games and interfaces, and relocation them.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sat, 25 Oct 2014 18:52:16 +0200 |
parents | pytouhou/games/eosd.py@1e9ea6519f3c |
children | 2cf518129725 |
comparison
equal
deleted
inserted
replaced
596:ab131d04987d | 597:244c99c568c8 |
---|---|
1 # -*- encoding: utf-8 -*- | |
2 ## | |
3 ## Copyright (C) 2011 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 from pytouhou.utils.interpolator import Interpolator | |
16 | |
17 from pytouhou.game.game import Game as GameBase | |
18 from pytouhou.game.bullettype import BulletType | |
19 from pytouhou.game.lasertype import LaserType | |
20 from pytouhou.game.itemtype import ItemType | |
21 from pytouhou.game.player import Player as PlayerBase | |
22 from pytouhou.game.orb import Orb | |
23 from pytouhou.game.background import Background | |
24 | |
25 from pytouhou.vm import ECLMainRunner | |
26 | |
27 | |
28 class Common(object): | |
29 def __init__(self, resource_loader, player_characters, continues, stage, | |
30 width=384, height=448): | |
31 self.width, self.height = width, height | |
32 | |
33 self.etama = resource_loader.get_multi_anm(('etama3.anm', 'etama4.anm')) | |
34 self.bullet_types = [BulletType(self.etama[0], 0, 11, 14, 15, 16, hitbox_size=2, | |
35 type_id=0), | |
36 BulletType(self.etama[0], 1, 12, 17, 18, 19, hitbox_size=3, | |
37 type_id=1), | |
38 BulletType(self.etama[0], 2, 12, 17, 18, 19, hitbox_size=2, | |
39 type_id=2), | |
40 BulletType(self.etama[0], 3, 12, 17, 18, 19, hitbox_size=3, | |
41 type_id=3), | |
42 BulletType(self.etama[0], 4, 12, 17, 18, 19, hitbox_size=2.5, | |
43 type_id=4), | |
44 BulletType(self.etama[0], 5, 12, 17, 18, 19, hitbox_size=2, | |
45 type_id=5), | |
46 BulletType(self.etama[0], 6, 13, 20, 20, 20, hitbox_size=8, | |
47 launch_anim_offsets=(0, 1, 1, 2, 2, 3, 4, 0), | |
48 type_id=6), | |
49 BulletType(self.etama[0], 7, 13, 20, 20, 20, hitbox_size=5.5, | |
50 launch_anim_offsets=(1, 1, 1, 1), | |
51 type_id=7), | |
52 BulletType(self.etama[0], 8, 13, 20, 20, 20, hitbox_size=4.5, | |
53 launch_anim_offsets=(0, 1, 1, 2, 2, 3, 4, 0), | |
54 type_id=8), | |
55 BulletType(self.etama[1], 0, 1, 2, 2, 2, hitbox_size=16, | |
56 launch_anim_offsets=(0, 1, 2, 3), | |
57 type_id=9)] | |
58 | |
59 self.laser_types = [LaserType(self.etama[0], 9), | |
60 LaserType(self.etama[0], 10)] | |
61 | |
62 self.item_types = [ItemType(self.etama[0], 0, 7), #Power | |
63 ItemType(self.etama[0], 1, 8), #Point | |
64 ItemType(self.etama[0], 2, 9), #Big power | |
65 ItemType(self.etama[0], 3, 10), #Bomb | |
66 ItemType(self.etama[0], 4, 11), #Full power | |
67 ItemType(self.etama[0], 5, 12), #1up | |
68 ItemType(self.etama[0], 6, 13)] #Star | |
69 | |
70 self.enemy_face = [('face03a.anm', 'face03b.anm'), | |
71 ('face05a.anm',), | |
72 ('face06a.anm', 'face06b.anm'), | |
73 ('face08a.anm', 'face08b.anm'), | |
74 ('face09a.anm', 'face09b.anm'), | |
75 ('face09b.anm', 'face10a.anm', 'face10b.anm'), | |
76 ('face08a.anm', 'face12a.anm', 'face12b.anm', 'face12c.anm')] | |
77 | |
78 default_power = [0, 64, 128, 128, 128, 128, 0][stage] | |
79 | |
80 eosd_characters = resource_loader.get_eosd_characters() | |
81 self.first_character = player_characters[0] // 2 | |
82 self.player_anms = {} | |
83 self.players = [None] * len(player_characters) | |
84 for i, player_character in enumerate(player_characters): | |
85 character = player_character // 2 | |
86 if character not in self.player_anms: | |
87 face = resource_loader.get_multi_anm(('face0%da.anm' % character, | |
88 'face0%db.anm' % character, | |
89 'face0%dc.anm' % character)) | |
90 anm = resource_loader.get_single_anm('player0%d.anm' % character) | |
91 self.player_anms[character] = (anm, face) | |
92 | |
93 self.players[i] = Player(i, self.player_anms[character][0], | |
94 eosd_characters[player_character], | |
95 character, default_power, continues) | |
96 | |
97 | |
98 | |
99 class Game(GameBase): | |
100 def __init__(self, resource_loader, stage, rank, difficulty, | |
101 common, prng, hints=None, friendly_fire=True, | |
102 nb_bullets_max=640): | |
103 | |
104 self.etama = common.etama #XXX | |
105 try: | |
106 self.enm_anm = resource_loader.get_multi_anm(('stg%denm.anm' % stage, | |
107 'stg%denm2.anm' % stage)) | |
108 except KeyError: | |
109 self.enm_anm = resource_loader.get_anm('stg%denm.anm' % stage) | |
110 ecl = resource_loader.get_ecl('ecldata%d.ecl' % stage) | |
111 self.ecl_runners = [ECLMainRunner(main, ecl.subs, self) for main in ecl.mains] | |
112 | |
113 self.spellcard_effect_anm = resource_loader.get_single_anm('eff0%d.anm' % stage) | |
114 | |
115 self.msg = resource_loader.get_msg('msg%d.dat' % stage) | |
116 msg_anm = [common.player_anms[common.first_character][1], #TODO: does it break bomb face of non-first player? | |
117 resource_loader.get_multi_anm(common.enemy_face[stage - 1])] | |
118 | |
119 self.msg_anm = [[], []] | |
120 for i, anms in enumerate(msg_anm): | |
121 for anm in anms: | |
122 for sprite in anm.sprites.values(): | |
123 self.msg_anm[i].append((anm, sprite)) | |
124 | |
125 for player in common.players: | |
126 player._game = self | |
127 | |
128 # Load stage data | |
129 self.std = resource_loader.get_stage('stage%d.std' % stage) | |
130 | |
131 background_anm = resource_loader.get_single_anm('stg%dbg.anm' % stage) | |
132 self.background = Background(self.std, background_anm) | |
133 | |
134 common.interface.start_stage(self, stage) | |
135 | |
136 GameBase.__init__(self, common.players, stage, rank, difficulty, | |
137 common.bullet_types, common.laser_types, | |
138 common.item_types, nb_bullets_max, common.width, | |
139 common.height, prng, common.interface, hints, | |
140 friendly_fire) | |
141 | |
142 try: | |
143 self.texts['stage_name'] = common.interface.stage_name | |
144 except AttributeError: | |
145 pass | |
146 | |
147 try: | |
148 self.texts['song_name'] = common.interface.song_name | |
149 except AttributeError: | |
150 pass | |
151 | |
152 | |
153 | |
154 class Player(PlayerBase): | |
155 def __init__(self, number, anm, shts, character, power, continues): | |
156 self.sht = shts[0] | |
157 self.focused_sht = shts[1] | |
158 | |
159 PlayerBase.__init__(self, number, anm, character, power, continues) | |
160 | |
161 self.orbs = [Orb(anm, 128, self), | |
162 Orb(anm, 129, self)] | |
163 | |
164 self.orbs[0].offset_x = -24 | |
165 self.orbs[1].offset_x = 24 | |
166 | |
167 self.orb_dx_interpolator = None | |
168 self.orb_dy_interpolator = None | |
169 | |
170 | |
171 def start_focusing(self): | |
172 self.orb_dx_interpolator = Interpolator((24,), self._game.frame, | |
173 (8,), self._game.frame + 8, | |
174 lambda x: x ** 2) | |
175 self.orb_dy_interpolator = Interpolator((0,), self._game.frame, | |
176 (-32,), self._game.frame + 8) | |
177 self.focused = True | |
178 | |
179 | |
180 def stop_focusing(self): | |
181 self.orb_dx_interpolator = Interpolator((8,), self._game.frame, | |
182 (24,), self._game.frame + 8, | |
183 lambda x: x ** 2) | |
184 self.orb_dy_interpolator = Interpolator((-32,), self._game.frame, | |
185 (0,), self._game.frame + 8) | |
186 self.focused = False | |
187 | |
188 | |
189 @property | |
190 def objects(self): | |
191 return [self] + (self.orbs if self.power >= 8 else []) | |
192 | |
193 | |
194 def update(self, keystate): | |
195 PlayerBase.update(self, keystate) | |
196 | |
197 if self.death_time == 0 or self._game.frame - self.death_time > 60: | |
198 if self.orb_dx_interpolator: | |
199 self.orb_dx_interpolator.update(self._game.frame) | |
200 dx, = self.orb_dx_interpolator.values | |
201 self.orbs[0].offset_x = -dx | |
202 self.orbs[1].offset_x = dx | |
203 if self.orb_dy_interpolator: | |
204 self.orb_dy_interpolator.update(self._game.frame) | |
205 dy, = self.orb_dy_interpolator.values | |
206 self.orbs[0].offset_y = dy | |
207 self.orbs[1].offset_y = dy | |
208 | |
209 for orb in self.orbs: | |
210 orb.update() |