From ea0183ae9159200f0657e2babf4231b49f9ca3be Mon Sep 17 00:00:00 2001 From: Jeremy Thurgood Date: Sun, 11 May 2014 11:00:58 +0200 Subject: [PATCH] Some more boilerplate. --- naja/resources.py | 103 ++++++++++++++++++++++++++++++++++++++++++++++ naja/sound.py | 93 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 naja/resources.py create mode 100644 naja/sound.py diff --git a/naja/resources.py b/naja/resources.py new file mode 100644 index 0000000..00ebe1c --- /dev/null +++ b/naja/resources.py @@ -0,0 +1,103 @@ +import os +import sys + +try: + from pkg_resources import resource_filename +except ImportError: + # OK, we're most likely running under py2exe, so this is safe + # (for values of safe that are unconcerned about py2exe being involved) + def resource_filename(mod, path): + # There are better ways of doing this, but I've spent too much + # time going down this rabbithole already + return os.path.join(os.path.dirname(__file__), '..', 'data', path) +import pygame + + +class ResourceNotFound(Exception): + pass + + +class Resources(object): + CONVERT_ALPHA = True + + def __init__(self, resource_module, language=None): + self.resource_module = resource_module + self.lang_dialect = language + self.language = language.split('_', 1)[0] if language else None + self._cache = {} + + def create_resource_path(self, *path_fragments): + return resource_filename(self.resource_module, + os.path.join(*path_fragments)) + + def get_resource_path(self, *path_fragments): + for mod, full_path_fragments in self.lang_locations(path_fragments): + path = resource_filename(mod, os.path.join(*full_path_fragments)) + if os.path.exists(path): + return path + raise ResourceNotFound(os.path.join(*path_fragments)) + + def lang_locations(self, path_fragments): + ''' + For each resource module, yield: + * (, (_, )) + * (, (, )) + * (, (, )) + ''' + for module in (self.resource_module,): + if self.lang_dialect: + yield (module, (self.lang_dialect,) + path_fragments) + if self.language != self.lang_dialect: + yield (module, (self.language,) + path_fragments) + yield (module, path_fragments) + + def get_file(self, *path_fragments, **kw): + mode = kw.get('mode', "rU") + try: + path = self.get_resource_path(*path_fragments) + except ResourceNotFound: + if 'w' in mode: + path = self.create_resource_path(*path_fragments) + else: + raise + return file(path, mode) + + def get_image(self, *name_fragments, **kw): + transforms = kw.get('transforms', ()) + basedir = kw.get('basedir', 'images') + + path = (basedir,) + name_fragments + + if path not in self._cache: + fn = self.get_resource_path(*path) + image = pygame.image.load(fn) + if self.CONVERT_ALPHA: + if not pygame.display.get_init(): + print >> sys.stderr, ("Display not initialized, " + "image '%s' not loaded." + % os.path.join(*path)) + return + image = image.convert_alpha(pygame.display.get_surface()) + self._cache[path] = image + + key = (path, transforms) + if key not in self._cache: + image = self._cache[path] + for mutator in transforms: + image = mutator(image) + self._cache[key] = image + + return self._cache[key] + + def get_font(self, file_name, font_size): + basedir = 'fonts' + key = (basedir, file_name, font_size) + + if key not in self._cache: + fn = self.get_resource_path(basedir, file_name) + self._cache[key] = pygame.font.Font(fn, font_size) + + return self._cache[key] + + +resources = Resources('data') diff --git a/naja/sound.py b/naja/sound.py new file mode 100644 index 0000000..3115865 --- /dev/null +++ b/naja/sound.py @@ -0,0 +1,93 @@ +"""Sound utilities.""" + +from pygame import mixer + +from naja.options import options +from naja.resources import resources +from naja.constants import ( + FREQ, BITSIZE, CHANNELS, BUFFER, DEFAULT_SOUND_VOLUME, + DEFAULT_MUSIC_VOLUME) + + +class DummySound(object): + def init(self): + pass + + def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME): + pass + + def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME): + pass + + def pause_music(self): + pass + + def resume_music(self): + pass + + def stop(self): + pass + + +class PygameSound(object): + def __init__(self): + self._sounds = {} + + def init(self): + mixer.init(FREQ, BITSIZE, CHANNELS, BUFFER) + silence = self.load_sound("silence.ogg") + if silence.get_length() < 1: + raise RuntimeError("Sound load error - silence.ogg too short") + self.play_sound("silence.ogg") + + def load_sound(self, name): + track_name = resources.get_resource_path("sounds", name) + sound = self._sounds.get(track_name) + if sound is None: + sound = self._sounds[track_name] = mixer.Sound(track_name) + return sound + + def play_sound(self, name, volume=DEFAULT_SOUND_VOLUME): + sound = self.load_sound(name) + if sound is not None: + sound.set_volume(volume) + sound.play() + + def play_music(self, name, volume=DEFAULT_MUSIC_VOLUME): + if not options.music: + return + track_name = resources.get_resource_path("music", name) + mixer.music.load(track_name) + mixer.music.set_volume(volume) + mixer.music.play(-1) # loop sound + + def pause_music(self): + mixer.music.pause() + + def unpause_music(self): + mixer.music.unpause() + + def stop(self): + mixer.fadeout(1000) + mixer.music.stop() + + +class SoundProxy(object): + def __init__(self): + self._sound = DummySound() + + def init(self): + """Attempt to initialize the sound system.""" + if options.sound: + try: + pyg_sound = PygameSound() + pyg_sound.init() + self._sound = pyg_sound + except Exception, err: + print "Failed to enable sound: %r" % (err,) + + def __getattr__(self, name): + return getattr(self._sound, name) + + +sound = SoundProxy() -- 2.34.1