Exemplo n.º 1
0
class SoundDecorator(FrameDecorator):
    def __init__(self, parent_component=NullComponent(), sound_file_path=''):
        self.sound_file_path = sound_file_path
        self.parent = parent_component
        self.sound = Sound(sound_file_path)
        self.start_time = 0

    def get_parent(self):
        return self.parent

    def set_parent(self, new_parent):
        self.parent = new_parent

    def get_landmarks(self):
        self.parent.get_landmarks()

    def get_image(self):
        self.play()
        return self.parent.get_image()

    def play(self):
        if not self.is_playing():
            self.start_time = time()
            self.sound.play()

    def is_playing(self):
        now = time()
        return self.sound.get_length() > now - self.start_time

    def stop(self):
        self.sound.stop()
        self.start_time = 0

    def copy(self):
        return SoundDecorator(parent_component=self.parent.copy(), sound_file_path=self.sound_file_path)
Exemplo n.º 2
0
    def thunder(self, inc):
        wait = random.randint(0, 2+inc)

        while (self._last == wait):
            wait = random.randint(0, 2+inc)

        self._last = wait
        print "intensity:", wait
        thunder = Sound("%s/thunder_0%d.wav" % (self._data_folder, wait))
        if wait < 6:
            self.lightning.set_C(ON)
            self.lightning.send()
            time.sleep(random.uniform(0.5, 1.5))
            self.lightning.set_C(OFF)
            self.lightning.send()
            time.sleep(wait)

        if wait < 6:
            self.lightning.set_B(OFF)
            self.lightning.send()
        thunder.play()
        if wait < 6:
            time.sleep(0.3)
            self.lightning.set_B(ON)
            self.lightning.send()
        time.sleep(thunder.get_length()-0.3)
        thunder.fadeout(200)
        time.sleep(wait)
Exemplo n.º 3
0
class SoundDecorator(FrameDecorator):
    def __init__(self, parent_component=NullComponent(), sound_file_path=''):
        self.sound_file_path = sound_file_path
        self.parent = parent_component
        self.sound = Sound(sound_file_path)
        self.start_time = 0

    def get_parent(self):
        return self.parent

    def set_parent(self, new_parent):
        self.parent = new_parent

    def get_landmarks(self):
        self.parent.get_landmarks()

    def get_image(self):
        self.play()
        return self.parent.get_image()

    def play(self):
        if not self.is_playing():
            self.start_time = time()
            self.sound.play()

    def is_playing(self):
        now = time()
        return self.sound.get_length() > now - self.start_time

    def stop(self):
        self.sound.stop()
        self.start_time = 0

    def copy(self):
        return SoundDecorator(parent_component=self.parent.copy(),
                              sound_file_path=self.sound_file_path)
Exemplo n.º 4
0
def prep_startup_sound():
    if STARTUP_FILENAME:
        global STARTUP_SOUND
        global STARTUP_DUR
        STARTUP_SOUND = Sound(STARTUP_PATH)
        STARTUP_DUR = STARTUP_SOUND.get_length()
Exemplo n.º 5
0
def prep_shutdown_sound():
    global SHUTDOWN_SOUND
    global SHUTDOWN_DUR
    SHUTDOWN_SOUND = Sound(SHUTDOWN_PATH)
    SHUTDOWN_SOUND.set_volume(.1)
    SHUTDOWN_DUR = SHUTDOWN_SOUND.get_length()
Exemplo n.º 6
0
class Sound(object):
    """
		todo is to wrap all the channel methods so they only work on the sound. This could happen either by checking if the sound is playing on the channel or possibly by calling methods on the sound itself.
		mixer documentation:
		https://www.pygame.org/docs/ref/mixer.html

		This class ads support for 3D positioning. Just pass the position of the sound in a tuple of (x,y) coordinates after the path of the file.
	"""
    def __init__(self, filename, position=None, single_channel=True):
        self.name = filename
        self.pos = position  # should be a tuple (x, y)
        self.channel = None
        self.paused = False
        self.playing = False
        self.stopped = False  # this is to tell a callback if the sound was stopped by a stop function or not.
        self.single_channel = single_channel
        self.callback = lambda e: None  # the callback is passed this object as an argument and is triggered at the end of the sound
        self._id = "sound-%s-%s" % (self.name, id(self))

        try:
            self.sound = Mixer_sound(filename)
        except:
            raise Exception("Unable to open file %r" % filename)

    def play(self, loops=0, maxtime=0, fade_ms=0):
        self.playing = True
        self.stopped = False
        if not self.channel or (
            (not self.single_channel or self.channel.get_sound() != self.sound)
                and self.channel.get_busy()):
            self.channel = find_channel() or self.channel
        self.channel.play(self.sound, loops, maxtime, fade_ms)
        if self.pos:
            playing_sounds.append(self)
            self.set_volume()
        event_queue.schedule(
            function=self.check_if_finished,
            repeats=-1,
            delay=0,
            name=self._id
        )  # this uses the channel.get_busy to figure out if the sound has finished playing.


#		event_queue.schedule(function=self.finish, repeats=1, delay=self.get_length()-0.09, name=self._id) # This does the same as above, but uses the length of the sound to schedule an end event. The problem with this is that if one pauses the sound, the event still runs. The pro is that the end event can be faster than the actual sound.

    def get_volume(self):
        return self.channel.get_volume()

    def move_pos(self, x=0, y=0):
        cx, cy = self.pos
        self.set_pos(cx + x, cy + y)
        return self.pos

    def set_pos(self, x, y):
        self.pos = (float(x), float(y))
        if (self.channel):
            self.channel.set_volume(*position.stereo(*self.pos))

    def get_pos(self):
        return self.pos

    def get_length(self):
        return self.sound.get_length()

    def toggle_pause(self):
        """This function can be called to pause and unpause a sound without the script needing to handle the check for paused and unpaused. If the sound is paused when this function is called, then the sound is unpaused and if the sound is playing when this function is called, then the sound is paused. It's very good for buttons to play and pause sounds."""
        if not self.channel or not self.playing:
            self.play()
        elif self.paused:
            self.unpause()
        else:
            self.pause()

    def unpause(self):
        if not self.channel: return False
        self.channel.unpause()
        self.paused = False

    def is_paused(self):
        return self.paused

    def pause(self):
        if not self.channel: return False
        self.channel.pause()
        self.paused = True

    def stop(self):
        """This stops the channel from playing."""
        event_queue.unschedule(self._id)
        if self in playing_sounds:
            playing_sounds.remove(self)
        self.playing = False
        self.paused = False
        self.stopped = True
        self.unpause()
        if self.channel:
            self.channel.stop()
        self.finish()

    def stop_sound(self):
        """This stops the sound object from playing rather than the channel"""
        self.sound.stop()
        self.unpaws()
        self.playing = False
        mixer_queue.remove(self.channel)
        if self in playing_sounds:
            playing_sounds.remove(self)

    def get_busy(self):
        """Returns if the channel is active. This is used for triggering the callback"""
        if self.channel:
            return self.channel.get_busy()
        return False

    def check_if_finished(self):
        """This runs every tick to see if the channel is done. if it is done, then it runs the finish method and removes itself from the event_queue."""
        if not self.get_busy():
            self.finish()
            event_queue.unschedule(self._id)

    def toggle_playing(self):
        if self.playing:
            self.stop()
        else:
            self.play()

    def set_volume(self, volume=1, right=None):
        """Sets the volume if there is a channel. If there is a position, then volume is adjusted to be that position. If no arguments are passed, then it will update the volume to be the current pos, or set volume back to 1."""
        if not self.channel:
            return 0
        if volume > 1:
            volume = 1
        elif volume <= 0:
            self.channel.set_volume(0)
            return 0
        if not self.pos and not right:
            self.channel.set_volume(volume)
        elif right:
            self.channel.set_volume(volume, right)
        else:
            x, y = self.pos
            if x == 0 and y == 0:
                self.channel.set_volume(volume)
                return 0
            self.channel.set_volume(*position.stereo(x / volume, y / volume))

    def finish(self):
        self.playing = False
        self.paused = False
        self.callback(self)
Exemplo n.º 7
0
class IntroAnimator(object):
    """This class is in charge of animating the Title Screen's
    introductory animation.

    Attributes:
        is_running: A Boolean indicating whether the animation is
            currently being shown.
        voice: A PyGame Sound with the announcer stating the game's
            title.
        voice_timer: An integer counter that keeps track of how many
            update cycles have passed since the voice clip started
            playing.
        voice_has_played: A Boolean indicating whether the voice clip
            has already played.
        voice_duration: An integer for the duration of the voice clip,
            in update cycles.
    """
    def __init__(self):
        """Declare and initialize instance variables."""
        self.is_running = False
        self.voice = Sound(VOICE_PATH)
        self.voice_duration = (self.voice.get_length() * FRAME_RATE)
        self.voice_timer = 0
        self.voice_has_played = False

    def update(self, time, bg, logo, sound_channel):
        """Update the animation's processes.

        The animation will proceed as follows:
            1. Scroll the background up from the bottom edge until it
               fills the screen.
            2. Fade in the logo.
            3. As it fades in, play the voice clip.
            4. Once the voice clip finishes, play the title theme and
               activate the logo's animation.

        Args:
            time: A float for the time elapsed, in seconds, since the
                last update cycle.
            bg: The Title Screen's background Animation.
            logo: The game logo Animation.
            sound_channel: The PyGame Channel that will be used to
                play the announcer's voice.
        """
        if bg.exact_pos[1] > 0.0:
            self.move_background_up(bg, time)
        elif logo.image.get_alpha() < 255:
            self.fade_in_logo(logo)

        if (logo.image.get_alpha() >= FADE_DELAY
                and (not self.voice_has_played)):
            sound_channel.play(self.voice)
            self.voice_has_played = True
        elif (self.voice_has_played and
              self.voice_timer < self.voice_duration):
            self.voice_timer += 1
        elif self.voice_timer >= self.voice_duration:
            pygame.mixer.music.play(-1)
            logo.is_animated = True
            self.is_running = False

    def move_background_up(self, bg, time):
        """Move the background up at a set speed.

        The background will not move past the top edge of the screen.

        Args:
            bg: The Title Screen's background Animation.
            time: A float for the amount of time, in seconds, elapsed
                since the last update cycle.
        """
        distance = -1 * BG_SCROLL_SPEED * time
        bg.move(0, distance)

        if bg.exact_pos[1] < 0.0:
            distance = 0.0 - bg.exact_pos[1]
            bg.move(0, distance)

    def fade_in_logo(self, logo):
        """Gradually increase the opacity of the game logo.

        Args:
            logo: The game logo Animation.
        """
        old_alpha = logo.image.get_alpha()
        logo.image.set_alpha(old_alpha + FADE_LOGO_RATE)

    def skip_intro(self, bg, logo, sound_channel):
        """Skip to the end of animation immediately.

        Args:
            bg: The Title Screen's background Animation.
            logo: The game logo Animation.
            sound_channel: The PyGame Channel that will be used to
                play the announcer's voice.
        """
        if not self.voice_has_played:
            sound_channel.play(self.voice)

        bg.move(0, -1 * bg.rect[1])
        pygame.mixer.music.play(-1)
        logo.image.set_alpha(255)
        logo.is_animated = True
        self.is_running = False

    def reset(self, bg, logo):
        """Prepare the animation to be shown.

        This method must be called before the first call to update()
        to ensure that all components are ready for use.
        If not, bad things will happen... (maybe)

        Args:
            bg: The Title Screen's background Animation.
            logo: The game logo Animation.
        """
        pygame.mixer.stop()
        pygame.mixer.music.load(MUSIC_PATH)
        self.voice_timer = 0
        self.voice_has_played = False
        bg.exact_pos = (0.0, SCREEN_SIZE[1] + BG_OFFSET)
        logo.is_animated = False
        logo.image.set_alpha(0)
        self.is_running = True