Mercurial > touhou
diff pytouhou/interfaces/eosd.py @ 548:1e9ea6519f3c
Make EoSDInterface separate from EoSD game.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Wed, 21 May 2014 20:56:53 +0200 |
parents | |
children | e15672733c93 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/pytouhou/interfaces/eosd.py @@ -0,0 +1,156 @@ +# -*- encoding: utf-8 -*- +## +## Copyright (C) 2014 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +from pytouhou.game.effect import Effect +from pytouhou.game.text import Text, Counter, Gauge, NativeText + + +class EoSDInterface(object): + def __init__(self, resource_loader, player_state): + self.game = None + self.player_state = player_state + front = resource_loader.get_single_anm('front.anm') + self.ascii_anm = resource_loader.get_single_anm('ascii.anm') + + self.width = 640 + self.height = 480 + self.game_pos = (32, 16) + + self.highscore = 1000000 #TODO: read score.dat + self.items = ([Effect((0, 32 * i), 6, front) for i in range(15)] + + [Effect((416 + 32 * i, 32 * j), 6, front) for i in range(7) for j in range(15)] + + [Effect((32 + 32 * i, 0), 7, front) for i in range(12)] + + [Effect((32 + 32 * i, 464), 8, front) for i in range(12)] + + [Effect((0, 0), i, front) for i in reversed(range(6))] + + [Effect((0, 0), i, front) for i in range(9, 16)]) + for item in self.items: + item.sprite.allow_dest_offset = True #XXX + + self.level_start = [] + + self.labels = { + 'highscore': Text((500, 58), self.ascii_anm, front, text='0'), + 'score': Text((500, 82), self.ascii_anm, front, text='0'), + 'player': Counter((500, 122), front, front, script=16, value=0), + 'bombs': Counter((500, 146), front, front, script=17, value=0), + 'power': Text((500, 186), self.ascii_anm, front, text='0'), + 'graze': Text((500, 206), self.ascii_anm, front, text='0'), + 'points': Text((500, 226), self.ascii_anm, front, text='0'), + 'framerate': Text((512, 464), self.ascii_anm, front), + 'debug?': Text((0, 464), self.ascii_anm, front), + + # Only when there is a boss. + 'boss_lives': Text((80, 16), self.ascii_anm), + 'timeout': Text((384, 16), self.ascii_anm), + } + self.labels['boss_lives'].set_color('yellow') + + self.boss_items = [ + Effect((0, 0), 19, front), # Enemy + Gauge((100, 24), front), # Gauge + Gauge((100, 24), front), # Spellcard gauge + ] + for item in self.boss_items: + item.sprite.allow_dest_offset = True #XXX + + + def start_stage(self, game, stage): + self.game = game + if stage < 6: + text = 'STAGE %d' % stage + elif stage == 6: + text = 'FINAL STAGE' + elif stage == 7: + text = 'EXTRA STAGE' + + self.stage_name = NativeText((192, 200), unicode(game.std.name), shadow=True, align='center') + self.stage_name.set_timeout(240, effect='fadeout', duration=60, start=120) + + self.set_song_name(game.std.bgms[0][0]) + + self.level_start = [Text((16+384/2, 200), self.ascii_anm, text=text, align='center')] #TODO: find the exact location. + self.level_start[0].set_timeout(240, effect='fadeout', duration=60, start=120) + self.level_start[0].set_color('yellow') + + + def set_song_name(self, name): + #TODO: use the correct animation. + self.song_name = NativeText((384, 432), u'♪ ' + name, shadow=True, align='right') + self.song_name.set_timeout(240, effect='fadeout', duration=60, start=120) + + + def set_boss_life(self): + if not self.game.boss: + return + self.boss_items[1].maximum = self.game.boss.life or 1 + self.boss_items[2].maximum = self.game.boss.life or 1 + + + def set_spell_life(self): + self.boss_items[2].set_value(self.game.boss.low_life_trigger if self.game.boss else 0) + + + def update(self): + for elem in self.items: + elem.update() + + for elem in self.level_start: + elem.update() + if elem.removed: #XXX + self.level_start = [] + + player_state = self.player_state + + self.highscore = max(self.highscore, player_state.effective_score) + self.labels['highscore'].set_text('%09d' % self.highscore) + self.labels['score'].set_text('%09d' % player_state.effective_score) + self.labels['power'].set_text('%d' % player_state.power) + self.labels['graze'].set_text('%d' % player_state.graze) + self.labels['points'].set_text('%d' % player_state.points) + self.labels['player'].set_value(player_state.lives) + self.labels['bombs'].set_value(player_state.bombs) + + if self.game.boss: + boss = self.game.boss + + life_gauge = self.boss_items[1] + life_gauge.set_value(boss.life) + + spell_gauge = self.boss_items[2] + spell_gauge.sprite.color = (255, 192, 192) + if boss.life < spell_gauge.value: + spell_gauge.set_value(boss.life) + + for item in self.boss_items: + item.update() + + self.labels['boss_lives'].set_text('%d' % boss.remaining_lives) + self.labels['boss_lives'].changed = True + + timeout = min((boss.timeout - boss.frame) // 60, 99) + timeout_label = self.labels['timeout'] + if timeout >= 20: + timeout_label.set_color('blue') + elif timeout >= 10: + timeout_label.set_color('darkblue') + else: + if timeout >= 5: + timeout_label.set_color('purple') + else: + timeout_label.set_color('red') + if (boss.timeout - boss.frame) % 60 == 0 and boss.timeout != 0: + self.game.sfx_player.set_volume('timeout.wav', 1.) + self.game.sfx_player.play('timeout.wav') + timeout_label.set_text('%02d' % (timeout if timeout >= 0 else 0)) + timeout_label.changed = True