示例#1
0
    def __init__(self, **kwargs):
        super(LevelSelectScreen, self).__init__(**kwargs)

        Window.clearcolor = colors['grey'].rgba

        self.anim_group = AnimGroup()
        self.canvas.add(self.anim_group)

        self.label = Label(text='Play it by Gear',
                           font_name='./fonts/PassionOne-Regular',
                           color=(.165, .718, .792, 1))
        self.add_widget(self.label)

        self.buttons = []
        self.id_counter = 0

        self.audio = Audio(2)
        self.mixer = Mixer()
        self.audio.set_generator(self.mixer)
        self.start_time = None
        self.switch_level = None

        self.border_color = colors['dark_grey']
        self.border = Line(rectangle=(0, 0, Window.width, Window.height),
                           width=Window.width * 0.03)
        self.anim_group.add(self.border_color)
        self.anim_group.add(self.border)

        self.on_layout((Window.width, Window.height))
示例#2
0
    def __init__(self,
                 notes,
                 bank=0,
                 preset=0,
                 loop=False,
                 simon_says=False,
                 bass_puzzle=False):
        super().__init__()
        self.audio = Audio(2)
        self.synth = Synth("./data/FluidR3_GM.sf2")

        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)
        self.sched.set_generator(self.synth)
        self.audio.set_generator(self.sched)

        self.notes = notes
        self.bank = bank
        self.preset = preset
        self.loop = loop
        self.simon_says = simon_says
        self.bass_puzzle = bass_puzzle

        self.note_seq = NoteSequencer(
            sched=self.sched,
            synth=self.synth,
            channel=1,
            program=(self.bank, self.preset),
            notes=self.notes,
            loop=self.loop,
        )
示例#3
0
    def __init__(self):
        super(MainWidget, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # Note Sequencers
        self.seq1 = NoteSequencer(self.sched, self.synth, 1, (0, 65),
                                  kYesterday, False)
        self.seq2 = NoteSequencer(self.sched, self.synth, 2, (0, 52),
                                  kSomewhere, True)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)
示例#4
0
class MainWidget1(BaseWidget) :
    def __init__(self):
        super(MainWidget1, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map  = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # create the arpeggiator:
        self.arpeg = Arpeggiator(self.sched, self.synth, channel = 1, program = (0,0) )

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

    def on_key_down(self, keycode, modifiers):
        if keycode[1] == 'm':
            self.metro.toggle()

        if keycode[1] == 'a':
            self.arpeg.start()

        pitches = lookup(keycode[1], 'qwe', ((60, 64, 67, 72), (55, 59, 62, 65, 67, 71), (60, 65, 69)))
        if pitches:
            self.arpeg.set_pitches(pitches)

        rhythm = lookup(keycode[1], 'uiop', ((120, 1), (160, 1), (240, 0.75), (480, 0.25)))
        if rhythm:
            self.arpeg.set_rhythm(*rhythm)

        direction = lookup(keycode[1], '123', ('up', 'down', 'updown'))
        if direction:
            self.arpeg.set_direction(direction)

    def on_key_up(self, keycode):
        if keycode[1] == 'a':
            self.arpeg.stop()

    def on_update(self) :
        self.audio.on_update()
        self.label.text = self.sched.now_str() + '\n'
        self.label.text += 'tempo:%d\n' % self.tempo_map.get_tempo()
        self.label.text += 'm: toggle Metronome\n'
        self.label.text += 'a: Enable Arpeggiator\n'
        self.label.text += 'q w e: Changes pitches\n'
        self.label.text += 'u i o p: Change Rhythm\n'
        self.label.text += '1 2 3: Change Direction\n'
示例#5
0
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)

        mode = 'mac' if (len(sys.argv) == 2) and (sys.argv[1]
                                                  == 'mac') else 'pc'
        self.norm = Normalizer(mode)

        self.info = topleft_label()
        self.add_widget(self.info)

        self.writer = AudioWriter('recordings/song')
        self.audio = Audio(2, self.writer.add_audio)
        self.mixer = Mixer()
        self.mixer.set_gain(1.0)
        self.audio.set_generator(self.mixer)

        self.sandbox = Sandbox(canvas=self.canvas,
                               pos=self.norm.nt((580, 50)),
                               size=self.norm.nt((1000, 1000)))

        # since putting all our sound module code in MainScreen would be a nightmare, we've
        # modularized our modules into separate files. each module has two classes, the sound
        # module itself and its handler class. the handler class is essentially a wrapper of
        # many of MainScreen's important event functions (e.g. on_touch_down) that keeps track
        # of all variables related to that sound module for every connected client.
        self.module_dict = {
            'PhysicsBubble': PhysicsBubble,
            'SoundBlock': SoundBlock,
            'TempoCursor': TempoCursor
        }
        block = SoundBlockHandler(self.norm, self.sandbox, self.mixer, client,
                                  client_id)
        self.module_handlers = {
            'SoundBlock':
            block,
            'PhysicsBubble':
            PhysicsBubbleHandler(self.norm, self.sandbox, self.mixer, client,
                                 client_id, block),
            'TempoCursor':
            TempoCursorHandler(self.norm, self.sandbox, self.mixer, client,
                               client_id, block)
        }

        # name a default starting module and handler
        self.module = PhysicsBubble
        self.module_handler = self.module_handlers[self.module.name]
        self.sandbox.add(self.module_handler.gui)

        # sync with existing server state
        client.emit('sync_module_state', {'module': 'PhysicsBubble'})
        client.emit('sync_module_state', {'module': 'SoundBlock'})
        client.emit('sync_module_state', {'module': 'TempoCursor'})
        client.emit('update_norm', {'norm': {client_id: self.norm.mode}})
    def __init__(self, level=0, prev_room=None, on_finished_puzzle=None):
        super().__init__()
        self.create_objects()
        self.place_objects()
        self.blocks_placed = 0
        self.create_treasure_popup((Window.width, Window.height))

        self.audio = Audio(2)
        self.mixer = Mixer()
        self.mixer.set_gain(0.2)
        self.audio.set_generator(self.mixer)
        self.wave_file_gen = WaveGenerator(
            WaveFile("./data/treasure_music.wav"))
示例#7
0
    def __init__(self,
                 level,
                 goal_music_seq,
                 duration,
                 edit_goal_play_status=None):
        super(LevelOptions, self).__init__()
        self.level = level  # level number
        self.audio = Audio(2)
        self.mixer = Mixer()
        self.audio.set_generator(self.mixer)

        self.options_bar = Rectangle(pos=(0, 0))
        self.home_button = Rectangle(
            texture=CoreImage('images/home.png').texture)
        self.play_button = Rectangle(
            texture=CoreImage('images/play.png').texture)
        self.reset_button = Rectangle(
            texture=CoreImage('images/reset.png').texture)
        self.check_button = Rectangle(
            texture=CoreImage('images/check.png').texture)
        self.on_layout((Window.width, Window.height))

        self.add(colors['grey'])
        self.add(self.options_bar)
        self.add(colors['green'])
        self.add(self.home_button)
        self.add(self.play_button)
        self.add(self.reset_button)
        self.add(self.check_button)

        self.is_playing = False
        self.start_time = None
        self.duration = 0
        self.goal_music_seq = None

        self.duration_circle = Line()
        self.add(self.duration_circle)

        # true iff you recently lost or won the game
        self.win_or_lose = False

        self.win_gen = WaveGenerator(WaveFile("./data/win_sound.wav"))
        self.lose_gen = WaveGenerator(WaveFile("./data/lose_sound.wav"))

        self.goal_music_seq = goal_music_seq
        self.duration = duration

        self.button_press_time = None

        self.edit_goal_play_status = edit_goal_play_status
示例#8
0
class MainWidget(BaseWidget):
    def __init__(self):
        super(MainWidget, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # Note Sequencers
        self.seq1 = NoteSequencer(self.sched, self.synth, 1, (0, 65),
                                  kYesterday, False)
        self.seq2 = NoteSequencer(self.sched, self.synth, 2, (0, 52),
                                  kSomewhere, True)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

    def on_key_down(self, keycode, modifiers):

        obj = lookup(keycode[1], 'mas', (self.metro, self.seq1, self.seq2))
        if obj is not None:
            obj.toggle()

        bpm_adj = lookup(keycode[1], ('up', 'down'), (10, -10))
        if bpm_adj:
            new_tempo = self.tempo_map.get_tempo() + bpm_adj
            self.tempo_map.set_tempo(new_tempo, self.sched.get_time())

    def on_update(self):
        self.audio.on_update()
        self.label.text = self.sched.now_str() + '\n'
        self.label.text += 'tempo:%d\n' % self.tempo_map.get_tempo()
        self.label.text += 'm: toggle Metronome\n'
        self.label.text += 'a: toggle Sequence 1\n'
        self.label.text += 's: toggle Sequence 2\n'
        self.label.text += 'up/down: change speed\n'
示例#9
0
class MainWidget4(BaseWidget):
    def __init__(self):
        super(MainWidget4, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')
        self.audio.set_generator(self.synth)

        # create clock, tempo_map, scheduler
        self.clock = Clock()
        self.tempo_map = SimpleTempoMap(120)
        self.sched = Scheduler(self.clock, self.tempo_map)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

    def on_key_down(self, keycode, modifiers):
        if keycode[1] == 'c':
            self.clock.toggle()

        if keycode[1] == 'm':
            self.metro.toggle()

        bpm_adj = lookup(keycode[1], ('up', 'down'), (10, -10))
        if bpm_adj:
            new_tempo = self.tempo_map.get_tempo() + bpm_adj
            self.tempo_map.set_tempo(new_tempo, self.sched.get_time())

    def on_update(self):
        # scheduler and audio get poked every frame
        self.sched.on_update()
        self.audio.on_update()

        bpm = self.tempo_map.get_tempo()

        self.label.text = self.sched.now_str() + '\n'
        self.label.text += 'Metronome:' + ("ON" if self.metro.playing else
                                           "OFF") + '\n'
        self.label.text += 'tempo:{}\n'.format(bpm)
        self.label.text += 'm: toggle Metronome\n'
        self.label.text += 'up/down: change speed\n'
示例#10
0
    def __init__(self):
        super(MainWidget4, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')
        self.audio.set_generator(self.synth)

        # create clock, tempo_map, scheduler
        self.clock = Clock()
        self.tempo_map = SimpleTempoMap(120)
        self.sched = Scheduler(self.clock, self.tempo_map)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)
示例#11
0
    def __init__(self):
        super(MainWidget2, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map  = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # create the arpeggiator:
        self.arpeg = Arpeggiator(self.sched, self.synth, channel = 1, program = (0,0) )
        self.arpeg.set_direction('updown')
        
        #size of the notes sent to the arpeggiator
        self.arpegSize = 3 
        #all of the notes this program can make. However, only self.arpegSize notes are sent to the arpegiator at a time
        self.allNotes = [50, 53, 55, 56, 57, 60, 62, 65, 67, 68, 69, 72, 74]

        self.lastPitchIndex = None
        self.lastPulseIndex = None

        self.noteLengths = [240, 210, 180, 150, 120, 90, 60]
        self.articulation = .75

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

        self.objects = AnimGroup()
        self.canvas.add(self.objects)

        self.add_lines()
示例#12
0
class MainWidget1(BaseWidget):
    def __init__(self):
        super(MainWidget1, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')
        self.audio.set_generator(self.synth)

        self.label = topleft_label()
        self.add_widget(self.label)

        cc_range = range(0, 128, 8)
        self.modifier = Modifier()
        self.modifier.add('a', "program", range(128),
                          lambda x: self.synth.program_change(0, x))
        self.modifier.add('s', "vibrato", cc_range,
                          lambda x: self.synth.cc(0, 1, x))
        self.modifier.add('d', "volume", cc_range,
                          lambda x: self.synth.cc(0, 7, x))
        self.modifier.add('f', "sustain", (0, 127),
                          lambda x: self.synth.cc(0, 64, x))
        self.modifier.add('z', "bend", range(-8192, 8192, 256),
                          lambda x: self.synth.pitch_bend(0, int(x)))

    def on_key_down(self, keycode, modifiers):
        self.modifier.on_key_down(keycode[1])

        pitch = lookup(keycode[1], kKeys, kPitches)
        if pitch:
            self.synth.noteon(0, pitch, 100)

    def on_key_up(self, keycode):
        self.modifier.on_key_up(keycode[1])

        pitch = lookup(keycode[1], kKeys, kPitches)
        if pitch:
            self.synth.noteoff(0, pitch)

    def on_update(self):
        self.audio.on_update()
        self.modifier.on_update()
        self.label.text = self.modifier.get_txt() + '\n'
示例#13
0
    def __init__(self):
        super(MainWidget5, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)
示例#14
0
    def __init__(self):
        super(MainWidget1, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')
        self.audio.set_generator(self.synth)

        self.label = topleft_label()
        self.add_widget(self.label)

        cc_range = range(0, 128, 8)
        self.modifier = Modifier()
        self.modifier.add('a', "program", range(128),
                          lambda x: self.synth.program_change(0, x))
        self.modifier.add('s', "vibrato", cc_range,
                          lambda x: self.synth.cc(0, 1, x))
        self.modifier.add('d', "volume", cc_range,
                          lambda x: self.synth.cc(0, 7, x))
        self.modifier.add('f', "sustain", (0, 127),
                          lambda x: self.synth.cc(0, 64, x))
        self.modifier.add('z', "bend", range(-8192, 8192, 256),
                          lambda x: self.synth.pitch_bend(0, int(x)))
示例#15
0
class MainWidget5(BaseWidget):
    def __init__(self):
        super(MainWidget5, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

    def on_key_down(self, keycode, modifiers):
        if keycode[1] == 'm':
            self.metro.toggle()

        bpm_adj = lookup(keycode[1], ('up', 'down'), (10, -10))
        if bpm_adj:
            new_tempo = self.tempo_map.get_tempo() + bpm_adj
            self.tempo_map.set_tempo(new_tempo, self.sched.get_time())

    def on_update(self):
        self.audio.on_update()
        bpm = self.tempo_map.get_tempo()

        self.label.text = self.sched.now_str() + '\n'
        self.label.text += 'tempo:{}\n'.format(bpm)
        self.label.text += 'm: toggle Metronome\n'
        self.label.text += 'up/down: change speed\n'
示例#16
0
    def __init__(self):
        super(MainWidget, self).__init__()

        self.writer = AudioWriter('song')
        self.audio = Audio(2, self.writer.add_audio)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(95*2)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # variables to store options
        self.transposition = 0
        self.style = None
        self.melody = None
        self.chords = None
        self.chord_option = None
        self.perc = None
        self.perc_option = None

        # variables to store screen options
        self.style_selection = StyleSelection(self.update_style_screen)    # screen index 0
        self.key_selection = KeySelection(self.update_key_screen)          # screen index 1
        self.chord_selection = None                                 # screen index 2
        self.perc_selection = None                                  # screen index 3
        self.melody_selection = None                                # screen index 4

        self.active_screen = self.style_selection
        self.screen_index = 0
        self.add_widget(self.active_screen)
示例#17
0
class MainWidget2(BaseWidget) :
    def __init__(self):
        super(MainWidget2, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map  = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # create the arpeggiator:
        self.arpeg = Arpeggiator(self.sched, self.synth, channel = 1, program = (0,0) )
        self.arpeg.set_direction('updown')
        
        #size of the notes sent to the arpeggiator
        self.arpegSize = 3 
        #all of the notes this program can make. However, only self.arpegSize notes are sent to the arpegiator at a time
        self.allNotes = [50, 53, 55, 56, 57, 60, 62, 65, 67, 68, 69, 72, 74]

        self.lastPitchIndex = None
        self.lastPulseIndex = None

        self.noteLengths = [240, 210, 180, 150, 120, 90, 60]
        self.articulation = .75

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

        # and text to display our status
        self.label = topleft_label()
        self.add_widget(self.label)

        self.objects = AnimGroup()
        self.canvas.add(self.objects)

        self.add_lines()
    
    def add_lines(self):
        w = Window.width
        h = Window.height
        numBuckets = len(self.allNotes) - self.arpegSize
        sizeOfBucket = w / numBuckets

        for i in range(numBuckets):
            xVal = i * sizeOfBucket
            line = Line(points=[xVal, 0, xVal, h], width=2)
            self.objects.add(line)

        

        numBuckets = len(self.noteLengths)
        sizeOfBucket = h / numBuckets

        for i in range(numBuckets):
            yVal = i * sizeOfBucket
            line = Line(points=[0, yVal, w, yVal], width=2)
            self.objects.add(line)



    def on_touch_down(self, touch):
        p = touch.pos
        self.update_pitches(p)
        self.update_pulse(p)
        self.arpeg.start()
        

    def on_touch_up(self, touch):
        self.arpeg.stop()

    def on_touch_move(self, touch):
        p = touch.pos
        self.update_pitches(p)
        self.update_pulse(p)

    def update_pitches(self, pos=(0,0)):
        mouseX = pos[0]
        w = Window.width

        numBuckets = len(self.allNotes) - self.arpegSize
        sizeOfBucket = w / numBuckets

        noteBucket = int(mouseX // sizeOfBucket)

        if noteBucket != self.lastPitchIndex:

            arpegNotes = self.allNotes[noteBucket:noteBucket+self.arpegSize]
            self.lastSlice = arpegNotes

            self.arpeg.set_pitches(arpegNotes)
            self.lastPitchIndex = noteBucket

    def update_pulse(self, pos=(0,0)):
        mouseY = pos[1]
        h = Window.height

        numBuckets = len(self.noteLengths)
        sizeOfBucket = h / numBuckets

        pulseBucket = int(mouseY // sizeOfBucket)

        if pulseBucket < len(self.noteLengths) and pulseBucket != self.lastPulseIndex:

            length = self.noteLengths[pulseBucket]
            self.arpeg.set_rhythm(length, self.articulation)
            self.lastPulseIndex = pulseBucket



    def on_update(self) :
        self.audio.on_update()
        self.label.text = self.sched.now_str() + '\n'
示例#18
0
class TreasureRoom(Puzzle):
    def __init__(self, level=0, prev_room=None, on_finished_puzzle=None):
        super().__init__()
        self.create_objects()
        self.place_objects()
        self.blocks_placed = 0
        self.create_treasure_popup((Window.width, Window.height))

        self.audio = Audio(2)
        self.mixer = Mixer()
        self.mixer.set_gain(0.2)
        self.audio.set_generator(self.mixer)
        self.wave_file_gen = WaveGenerator(
            WaveFile("./data/treasure_music.wav"))

    """ Mandatory Puzzle methods """

    def is_game_over(self):
        pass

    def create_objects(self):
        self.objects = {}

        size = (self.grid.tile_side_len, self.grid.tile_side_len)
        icons = [
            "./data/guitar.png",
            "./data/bass.png",
            "./data/drums.png",
            "./data/piano.png",
        ]
        init_positions = [(1, 1), (1, 7), (7, 1), (7, 7)]
        final_positions = [(2, 4), (3, 4), (5, 4), (6, 4)]
        colors = [
            Color(hsv=(0, 0.5, 1)),  # Green
            Color(hsv=(0.15, 0.5, 1)),  # Red
            Color(hsv=(0.25, 0.5, 1)),  # Yellow
            Color(hsv=(0.5, 0.5, 1)),  # Blue
        ]
        for i in range(len(icons)):
            self.objects[init_positions[i]] = MovingBlock(
                size,
                self.grid.grid_to_pixel(init_positions[i]),
                ((1, 1), (8, 8)),
                colors[i],
                icons[i],
                final_positions[i],
            )
            self.grid.get_tile(final_positions[i]).set_color(colors[i])

    def place_objects(self):
        self.create_objects()
        self.add(PushMatrix())
        self.add(Translate(*self.grid.pos))

        for pos, obj in self.objects.items():
            self.add(obj)

        self.add(PopMatrix())

    def valid_block_move(self, pos, move_range):
        return (move_range[0][0] <= pos[0] < move_range[1][0]
                and move_range[0][1] <= pos[1] < move_range[1][1])

    def move_block(self, new_location, x, y):
        obj_loc = (new_location[0] + x, new_location[1] + y)

        if self.is_valid_pos(obj_loc) and self.valid_block_move(
                obj_loc, self.objects[new_location].move_range):
            self.remove(self.objects[new_location])
            obj = MovingBlock(
                self.objects[new_location].size,
                self.grid.grid_to_pixel(obj_loc),
                self.objects[new_location].move_range,
                self.objects[new_location].color,
                self.objects[new_location].icon_source,
                self.objects[new_location].final_position,
            )
            del self.objects[new_location]

            self.add(PushMatrix())
            self.add(Translate(*self.grid.pos))
            self.add(obj)
            self.add(PopMatrix())

            self.objects[obj_loc] = obj
            self.blocks_placed += self.objects[obj_loc].on_block_placement(
                obj_loc)
            return True
        else:
            return False

    def on_player_input(self, button):
        if button in [Button.UP, Button.DOWN, Button.LEFT, Button.RIGHT]:
            move_possible = True
            x, y = button.value
            cur_location = self.character.grid_pos
            new_location = (cur_location[0] + x, cur_location[1] + y)
            self.character.change_direction(button.value)
            if new_location in self.objects:
                if self.objects[new_location].moveable:
                    move_possible = self.move_block(new_location, x, y)
            if move_possible:
                self.character.move_player(new_location)
            if self.character.grid_pos in self.objects:
                if isinstance(self.objects[self.character.grid_pos], DoorTile):
                    if not isinstance(
                            self.objects[self.character.grid_pos].other_room,
                            Puzzle):
                        # instantiate class when we enter the door
                        self.objects[
                            self.character.grid_pos].other_room = self.objects[
                                self.character.grid_pos].other_room(
                                    self, self.level + 1)
                    return self.objects[self.character.grid_pos].other_room
            if self.blocks_placed == 4:
                self.on_game_over()
                self.mixer.add(self.wave_file_gen)

    def create_treasure_popup(self, win_size):
        self.game_over_window_color = Color(rgba=(1, 1, 1, 1))
        self.game_over_window = CRectangle(
            cpos=(win_size[0] // 2, win_size[1] // 2),
            csize=(win_size[0] // 2, win_size[1] // 5),
        )
        self.game_over_text_color = Color(rgba=(0, 0, 0, 1))
        self.game_over_text = CLabelRect(
            (win_size[0] // 2, win_size[1] // 2),
            "You unlocked the pharaoh's treasure!\nYou WIN!", 40)
        self.treasure = CRectangle(cpos=(win_size[0] // 2, win_size[1] // 4),
                                   csize=(win_size[0] // 4, win_size[1] // 4),
                                   source='./data/treasure.png')

    def on_game_over(self):
        self.game_over = True
        self.add(self.game_over_window_color)
        self.add(self.game_over_window)
        self.add(self.game_over_text_color)
        self.add(self.game_over_text)
        self.add(self.game_over_window_color)
        self.add(self.treasure)

    def on_update(self):
        self.audio.on_update()

    def on_layout(self, win_size):
        self.remove(self.character)
        self.remove(self.grid)
        self.grid.on_layout(win_size)
        for pos, obj in self.objects.items():
            self.remove(obj)

        self.add(self.grid)
        self.place_objects()
        self.character.on_layout(win_size)
        self.add(self.character)
        self.create_treasure_popup(win_size)
        if self.game_over:
            self.remove(self.game_over_window_color)
            self.remove(self.game_over_window)
            self.remove(self.game_over_text_color)
            self.remove(self.game_over_text)
            self.remove(self.treasure)

            self.on_game_over()
示例#19
0
class LevelOptions(InstructionGroup):
    def __init__(self,
                 level,
                 goal_music_seq,
                 duration,
                 edit_goal_play_status=None):
        super(LevelOptions, self).__init__()
        self.level = level  # level number
        self.audio = Audio(2)
        self.mixer = Mixer()
        self.audio.set_generator(self.mixer)

        self.options_bar = Rectangle(pos=(0, 0))
        self.home_button = Rectangle(
            texture=CoreImage('images/home.png').texture)
        self.play_button = Rectangle(
            texture=CoreImage('images/play.png').texture)
        self.reset_button = Rectangle(
            texture=CoreImage('images/reset.png').texture)
        self.check_button = Rectangle(
            texture=CoreImage('images/check.png').texture)
        self.on_layout((Window.width, Window.height))

        self.add(colors['grey'])
        self.add(self.options_bar)
        self.add(colors['green'])
        self.add(self.home_button)
        self.add(self.play_button)
        self.add(self.reset_button)
        self.add(self.check_button)

        self.is_playing = False
        self.start_time = None
        self.duration = 0
        self.goal_music_seq = None

        self.duration_circle = Line()
        self.add(self.duration_circle)

        # true iff you recently lost or won the game
        self.win_or_lose = False

        self.win_gen = WaveGenerator(WaveFile("./data/win_sound.wav"))
        self.lose_gen = WaveGenerator(WaveFile("./data/lose_sound.wav"))

        self.goal_music_seq = goal_music_seq
        self.duration = duration

        self.button_press_time = None

        self.edit_goal_play_status = edit_goal_play_status

    def on_layout(self, winsize):
        size_dim = min(Window.width / 6, Window.height / 6)
        self.options_bar.size = (Window.width, size_dim + Window.height / 25)
        self.home_button.pos = (Window.width - 5 * size_dim,
                                Window.height / 50)
        self.home_button.size = (size_dim, size_dim)
        self.play_button.pos = (Window.width - 3.75 * size_dim,
                                Window.height / 50)
        self.play_button.size = (size_dim, size_dim)
        self.reset_button.pos = (Window.width - 2.5 * size_dim,
                                 Window.height / 50)
        self.reset_button.size = (size_dim, size_dim)
        self.check_button.pos = (Window.width - 1.25 * size_dim,
                                 Window.height / 50)
        self.check_button.size = (size_dim, size_dim)

    def on_touch_up(self, switch_screen, gear_music_seq, level_complete,
                    win_particle, you_win_label, lose_particle, you_lose_label,
                    reset_fn, touch):

        self.switch_screen = switch_screen

        def reset():
            reset_fn()
            win_particle.stop()
            you_win_label.text = ' '
            lose_particle.stop()
            you_lose_label.text = ' '
            if self.win_gen in self.mixer.generators:
                self.mixer.remove(self.win_gen)
            elif self.lose_gen in self.mixer.generators:
                self.mixer.remove(self.lose_gen)

        # When you win/you lose is displayed, clicking anywhere on the
        # screen should bring you back to the home screen
        if self.win_or_lose:
            reset()
            switch_screen('level_select')
            self.win_or_lose = False

        elif self.is_clicked(self.home_button, touch):
            # play button press sound
            self.mixer.add(WaveGenerator(WaveFile("./data/button_press.wav")))
            self.button_press_time = time.time()
            # go back to level select screen
            reset()

        elif self.is_clicked(self.play_button, touch):
            # play button press sound
            self.mixer.add(WaveGenerator(WaveFile("./data/button_press.wav")))

            if self.edit_goal_play_status:
                self.edit_goal_play_status('started')

            # play/stop goal music
            self.is_playing = not self.is_playing
            if self.is_playing:
                self.goal_music_seq.start()
                self.start_time = time.time()
                self.play_button.texture = CoreImage('images/stop.png').texture
            else:
                self.goal_music_seq.stop()
                self.start_time = None
                self.play_button.texture = CoreImage('images/play.png').texture

        elif self.is_clicked(self.reset_button, touch):
            # play button press sound
            self.mixer.add(WaveGenerator(WaveFile("./data/button_press.wav")))
            # reset gear positions
            reset()

        elif self.is_clicked(self.check_button, touch):
            # play button press sound
            self.mixer.add(WaveGenerator(WaveFile("./data/button_press.wav")))

            # if gear placement is correct
            self.win_or_lose = True

            self.goal_music_seq.stop()
            if gear_music_seq:
                gear_music_seq.stop()

            if level_complete:
                # show particle effect, you win label, and play sound
                win_particle.start()
                you_win_label.text = 'YOU WIN'
                edit_progress_file(self.level, 'g')
                # generate and play winning music
                self.win_gen = WaveGenerator(WaveFile("./data/win_sound.wav"))
                self.mixer.add(self.win_gen)
            else:
                lose_particle.start()
                you_lose_label.text = 'YOU LOSE'
                edit_progress_file(self.level, 'r')
                self.lose_gen = WaveGenerator(
                    WaveFile("./data/lose_sound.wav"))
                self.mixer.add(self.lose_gen)

    def on_update(self):
        self.audio.on_update()

        if self.button_press_time and time.time(
        ) - self.button_press_time > 0.13:
            self.button_press_time = None
            self.switch_screen('level_select')

        # if goal sound played completely, switch back to play icon
        if self.start_time and time.time() - self.start_time >= self.duration:
            self.goal_music_seq.stop()
            self.is_playing = False
            self.play_button.texture = CoreImage('images/play.png').texture
            self.duration_circle.width = 0.01

            if self.edit_goal_play_status:
                self.edit_goal_play_status('finished')

        elif self.start_time and self.is_playing:
            size_dim = min(Window.width / 6, Window.height / 6)
            self.duration_circle.width = 10
            self.duration_circle.circle = (
                Window.width - 3.25 * size_dim,
                Window.height / 50 + size_dim / 2, size_dim / 2, 0,
                (self.start_time and time.time() - self.start_time) /
                self.duration * 360)
        else:
            self.duration_circle.width = 0.01

    def is_clicked(self, button, touch):
        return button.pos[0] < touch.x < button.pos[0] + button.size[0] \
        and button.pos[1] < touch.y < button.pos[1] + button.size[1]
示例#20
0
class LevelEasyMediumScreen(Screen):
    def __init__(self, level, notes, goal_values, gear_values, **kwargs):
        super(LevelEasyMediumScreen, self).__init__(**kwargs)

        # set up notes for the level
        self.notes = notes

        # set up gear values for the levels
        self.goal_values = goal_values

        # set up gear values for the levels
        self.gear_values = gear_values

        self.level = level

        # only turn on tutorial for level 1
        if self.level == 1:
            self.use_tutorial = True
            self.tutorial_screen = 'A'
            self.goal_play_status = None
            self.gear_play_status = None
            self.size_dim = min(Window.width / 6, Window.height / 6)
            self.tutorial_full_overlay = CRectangle(cpos=(Window.width / 2,
                                                          Window.height / 2),
                                                    csize=(Window.width,
                                                           Window.height))
            self.tutorial_options_overlay = Rectangle(
                pos=(0, 0),
                size=(Window.width, self.size_dim + Window.height / 25))
            self.tutorial_musicbox_overlay = Rectangle(
                pos=(Window.width // 2, self.size_dim + Window.height / 25),
                size=(Window.width / 2,
                      Window.height - (self.size_dim + Window.height / 25)))
            self.tutorial_gearbox_overlay = Rectangle(
                pos=(0, self.size_dim + Window.height / 25),
                size=(Window.width / 2,
                      Window.height - (self.size_dim + Window.height / 25)))
            self.skip_image = CoreImage('images/skip_tutorial.png')
            self.tutorial_skip_button = Rectangle(
                pos=(0.98 * Window.width -
                     (self.skip_image.width * self.size_dim / 300),
                     0.98 * Window.height -
                     self.skip_image.height * self.size_dim / 300),
                size=(self.skip_image.width * self.size_dim / 300,
                      self.skip_image.height * self.size_dim / 300),
                texture=self.skip_image.texture)
        else:
            self.use_tutorial = False

        ############################################
        ###              GOAL MUSIC              ###
        ############################################
        self.goal_audio = Audio(2)
        self.goal_synth = Synth('./data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.goal_tempo_map = SimpleTempoMap(120)
        self.goal_sched = AudioScheduler(self.goal_tempo_map)

        # connect scheduler into audio system
        self.goal_audio.set_generator(self.goal_sched)
        self.goal_sched.set_generator(self.goal_synth)

        # generate goal music
        self.goal_music = MusicPlayer(notes=self.notes,
                                      sched=self.goal_sched,
                                      synth=self.goal_synth,
                                      channel=1,
                                      tempo_map=self.goal_tempo_map)
        self.goal_music.update_tempo(self.goal_values[0])
        self.goal_music.update_instrument(self.goal_values[1])
        self.goal_music.update_pitch(self.goal_values[2])
        self.goal_music.update_volume(self.goal_values[3])

        self.goal_music_seq = self.goal_music.generate()

        ############################################
        ###              GEAR MUSIC              ###
        ############################################
        self.gear_audio = Audio(2)
        self.gear_synth = Synth('./data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.gear_tempo_map = SimpleTempoMap(120)
        self.gear_sched = AudioScheduler(self.gear_tempo_map)

        # connect scheduler into audio system
        self.gear_audio.set_generator(self.gear_sched)
        self.gear_sched.set_generator(self.gear_synth)

        # generate gear music
        self.gear_music = MusicPlayer(notes=self.notes,
                                      sched=self.gear_sched,
                                      synth=self.gear_synth,
                                      channel=1,
                                      tempo_map=self.gear_tempo_map)
        self.gear_music_seq = None

        ############################################
        ###       BACKGROUND UI COMPONENTS       ###
        ############################################
        self.gear_area = GearArea()
        self.canvas.add(self.gear_area)

        self.music_box_area = MusicBoxArea()
        self.canvas.add(self.music_box_area)

        self.options = LevelOptions(
            level=level,
            goal_music_seq=self.goal_music_seq,
            duration=self.goal_music.duration,
            edit_goal_play_status=self.edit_goal_play_status)
        self.canvas.add(self.options)

        self.label = Label(text=kwargs['name'],
                           font_name='./fonts/PassionOne-Regular',
                           color=(.165, .718, .792, 1))
        self.add_widget(self.label)

        ###########################################
        ###             GEAR LABELS             ###
        ###########################################
        self.tempo_label = Label(text='Tempo (bpm)',
                                 font_name='./fonts/PassionOne-Regular',
                                 color=(0.7254901960784313, 0.5529411764705883,
                                        0.8196078431372549, 1),
                                 center_x=(Window.width / 4),
                                 center_y=(Window.height / 5.25 * (0.5 + 0.5) +
                                           self.gear_area.position[1]),
                                 font_size=str(Window.width // 50) + 'sp')
        self.instrument_label = Label(
            text='Instrument',
            font_name='./fonts/PassionOne-Regular',
            color=(0.996078431372549, 0.8431372549019608, 0.4, 1),
            center_x=(Window.width / 4),
            center_y=(Window.height / 5.25 * (1.5 + 0.5) +
                      self.gear_area.position[1]),
            font_size=str(Window.width // 50) + 'sp')
        self.pitch_label = Label(text='Pitch (semitones)',
                                 font_name='./fonts/PassionOne-Regular',
                                 color=(1.0, 0.6509803921568628,
                                        0.09019607843137255, 1),
                                 center_x=(Window.width / 4),
                                 center_y=(Window.height / 5.25 * (2.5 + 0.5) +
                                           self.gear_area.position[1]),
                                 font_size=str(Window.width // 50) + 'sp')
        self.volume_label = Label(
            text='Volume',
            font_name='./fonts/PassionOne-Regular',
            color=(0.9254901960784314, 0.32941176470588235, 0.3176470588235294,
                   1),
            center_x=(Window.width / 4),
            center_y=(Window.height / 5.25 * (3.5 + 0.5) +
                      self.gear_area.position[1]),
            font_size=str(Window.width // 50) + 'sp')
        self.add_widget(self.volume_label)
        self.add_widget(self.pitch_label)
        self.add_widget(self.instrument_label)
        self.add_widget(self.tempo_label)

        ###########################################
        ###          GEAR CONSTRUCTION          ###
        ###########################################

        self.gears = []
        self.gear_centers = []
        self.gears_group = AnimGroup()
        self.canvas.add(self.gears_group)

        ###########################################
        ###                GEARS                ###
        ###########################################
        self.gear_storage_locations = []
        self.gear_music_locations = []
        self.gear_labels = []
        self.set_up_gears()

        ###########################################
        ###           PARTICLE EFFECT           ###
        ###########################################
        self.win_ps = ParticleSystem('particles/star_particle.pex')
        self.win_ps.emitter_x = Window.width / 2
        self.win_ps.emitter_y = Window.height / 2
        self.add_widget(self.win_ps)
        self.you_win_label = Label(text=' ',
                                   font_name='./fonts/PassionOne-Regular',
                                   color=(0.5843137254901961,
                                          0.796078431372549,
                                          0.37254901960784315, 1),
                                   center_x=Window.width / 2,
                                   center_y=Window.height / 2,
                                   font_size=str(Window.width // 10) + 'sp')
        self.add_widget(self.you_win_label)

        self.lose_ps = ParticleSystem('particles/lose_particle.pex')
        self.lose_ps.emitter_x = Window.width / 2
        self.lose_ps.emitter_y = Window.height / 2
        self.add_widget(self.lose_ps)
        self.you_lose_label = Label(text=' ',
                                    font_name='./fonts/PassionOne-Regular',
                                    color=(0.9254901960784314,
                                           0.32941176470588235,
                                           0.3176470588235294, 1),
                                    center_x=Window.width / 2,
                                    center_y=Window.height / 2,
                                    font_size=str(Window.width // 10) + 'sp')
        self.add_widget(self.you_lose_label)

        ###########################################
        ###            ERROR MESSAGE            ###
        ###########################################
        self.error_msg = Label(text=' ',
                               font_name='./fonts/PassionOne-Regular',
                               color=(0.9254901960784314, 0.32941176470588235,
                                      0.3176470588235294, 1),
                               center_x=Window.width / 2,
                               center_y=Window.height / 2,
                               font_size=str(Window.width // 20) + 'sp')
        self.add_widget(self.error_msg)

        # ###########################################
        # ###        ADD TUTORIAL OVERLAYS        ###
        # ###########################################
        if self.use_tutorial:
            self.canvas.add(Color(rgba=(0, 0, 0, 0.85)))
            self.canvas.add(self.tutorial_full_overlay)
            self.tutorial_label = Label(
                markup=True,
                text=
                "[font=./fonts/lato-bold]Welcome to the\n[/font] [font=./fonts/options-icons]|[/font] [font=./fonts/PassionOne-Regular]Play It By Gear Tutorial[/font] [font=./fonts/options-icons]|[/font] [font=./fonts/lato-bold]\n\nThe goal of this game is to make the \n goal song match the song you create by \nplacing the correct gears in a music box \n\n[/font] [font=./fonts/lato-light] (click to see the next \nstep of the tutorial)[/font]",
                color=(86 / 255, 189 / 255, 205 / 255, 1),
                center_x=Window.width / 2,
                center_y=Window.height / 2,
                font_size=str(Window.width // 40) + 'sp',
                halign='center')
            self.add_widget(self.tutorial_label)
            self.canvas.add(self.tutorial_skip_button)

        self.on_layout((Window.width, Window.height))

    def clear_overlays(self):
        if self.tutorial_full_overlay in self.canvas.children:
            self.canvas.remove(self.tutorial_full_overlay)
        if self.tutorial_options_overlay in self.canvas.children:
            self.canvas.remove(self.tutorial_options_overlay)
        if self.tutorial_gearbox_overlay in self.canvas.children:
            self.canvas.remove(self.tutorial_gearbox_overlay)
        if self.tutorial_musicbox_overlay in self.canvas.children:
            self.canvas.remove(self.tutorial_musicbox_overlay)
        while self.tutorial_skip_button in self.canvas.children:
            self.canvas.remove(self.tutorial_skip_button)

    def activate_overlays(self, overlay_names):
        self.clear_overlays()
        self.canvas.add(Color(rgba=(0, 0, 0, 0.85)))
        if 'full' in overlay_names:
            self.canvas.add(self.tutorial_full_overlay)
        if 'options' in overlay_names:
            self.canvas.add(self.tutorial_options_overlay)
        if 'gearbox' in overlay_names:
            self.canvas.add(self.tutorial_gearbox_overlay)
        if 'musicbox' in overlay_names:
            self.canvas.add(self.tutorial_musicbox_overlay)

    def get_scaled_x_y(self, winsize, x, y):
        width, height = winsize
        # scaled_x = width/8 * (x+1)
        scaled_x = width / (len(self.gear_values) // 4 * 2) * (x + 0.5)
        scaled_y = height / 5.25 * (y + 0.5) + self.gear_area.position[1]

        return scaled_x, scaled_y

    def set_up_gears(self):
        self.gears = []
        self.gears_group.remove_all()
        center_gear_location = (Window.width / 6 * 4.5,
                                Window.height / 4 * 2.5)
        center_gear_size = min(Window.width / 10, Window.height / 10)
        self.center_gear = Gear(None, None, center_gear_size, 10, 'center', 0,
                                center_gear_location, center_gear_location, 1,
                                colors['dark_grey'])
        self.canvas.add(self.center_gear.color)
        self.gears_group.add(self.center_gear)

        self.center_gear_center = GearCenter(None, None, center_gear_location,
                                             center_gear_location, 'center',
                                             center_gear_size / 2,
                                             colors['dark_grey'])
        self.canvas.add(colors['dark_grey'])
        self.canvas.add(self.center_gear_center)

        self.play_center_gear = False

        self.music_gears = []

        tempo_location = (center_gear_location[0], center_gear_location[1] +
                          center_gear_size + center_gear_size / 5)
        instrument_location = (center_gear_location[0],
                               center_gear_location[1] - center_gear_size -
                               center_gear_size / 5)
        pitch_location = (center_gear_location[0] + center_gear_size +
                          center_gear_size / 5, center_gear_location[1])
        volume_location = (center_gear_location[0] - center_gear_size -
                           center_gear_size / 5, center_gear_location[1])

        self.music_box_gear_locations = [
            tempo_location, instrument_location, pitch_location,
            volume_location
        ]

        counter = 0

        label_font_size = min(Window.width // 80, Window.height // 80)
        for y in range(0, 4):
            for x in range(len(self.gear_values) // 4):
                gear_type = gear_type_map[y]
                size = min(Window.width / 10, Window.height / 10)

                music_pos = self.music_box_gear_locations[y]
                scaled_x, scaled_y = self.get_scaled_x_y(
                    (Window.width, Window.height), x, y)

                gear = Gear(x, y, size, 8, gear_type,
                            self.gear_values[counter], (scaled_x, scaled_y),
                            music_pos, 0, colors['dark_grey'])
                self.gears.append(gear)
                self.canvas.add(gear.color)
                self.gears_group.add(gear)

                gear_center = GearCenter(x, y, (scaled_x, scaled_y), music_pos,
                                         gear_type, size / 2,
                                         colors['dark_grey'])
                self.gear_centers.append(gear_center)
                self.canvas.add(gear_center)

                ## white dots for storage purposes
                gear_loc = GearLocation((scaled_x, scaled_y), size / 2, x, y,
                                        gear_type)
                self.gear_storage_locations.append(gear_loc)
                self.canvas.add(gear_loc)

                text = str(self.gear_values[counter])
                font_name = './fonts/PassionOne-Regular'
                if y == 3:
                    # get volume as percent
                    text = str(100 * self.gear_values[counter] // 127) + '%'
                if y == 1:
                    # get icon for instrument
                    font_name = './fonts/music-instruments'
                    text = instruments[self.gear_values[counter]]

                label = Label(text=text,
                              font_name=font_name,
                              color=(0, 0, 0, 1),
                              center_x=scaled_x,
                              center_y=scaled_y,
                              font_size=str(label_font_size) + 'sp')
                self.gear_labels.append(label)
                self.add_widget(label)

                counter += 1

        for indx, loc in enumerate(self.music_box_gear_locations):
            gear_type = gear_type_map[indx % 4]
            gear_loc = GearLocation(loc, center_gear_size / 2, None, None,
                                    gear_type)
            self.gear_music_locations.append(gear_loc)
            self.canvas.add(gear_loc)

    def edit_goal_play_status(self, value):
        if self.use_tutorial:
            if self.goal_play_status == None and value == 'started':
                self.goal_play_status = 'started'
            elif self.goal_play_status == 'started' and value == 'finished':
                self.goal_play_status = 'finished'

    def _can_add_gear(self, new_gear):
        for gear in self.music_gears:
            if gear.type == new_gear.type:
                return False
        return True

    def _check_music_gears(self):
        all_types = ['volume', 'pitch', 'tempo', 'instrument']
        for gear in self.music_gears:
            if gear.type in all_types:
                all_types.remove(gear.type)
        return len(all_types) == 0

    def update_center_gear_on_layout(self, winsize):
        width, height = winsize
        center_gear_location = (width / 6 * 4.5, height / 4 * 2.5)
        center_gear_size = min(Window.width / 10, Window.height / 10)

        self.center_gear_center.update_storage_pos(center_gear_location)
        self.center_gear_center.update_music_pos(center_gear_location)
        self.center_gear.update_storage_pos(center_gear_location)
        self.center_gear.update_music_pos(center_gear_location)

        self.center_gear.on_layout(center_gear_location, center_gear_size)
        self.center_gear_center.on_layout(center_gear_location,
                                          center_gear_size / 2)

        tempo_location = (center_gear_location[0], center_gear_location[1] +
                          center_gear_size + center_gear_size / 5)
        instrument_location = (center_gear_location[0],
                               center_gear_location[1] - center_gear_size -
                               center_gear_size / 5)
        pitch_location = (center_gear_location[0] + center_gear_size +
                          center_gear_size / 5, center_gear_location[1])
        volume_location = (center_gear_location[0] - center_gear_size -
                           center_gear_size / 5, center_gear_location[1])

        self.music_box_gear_locations = [
            tempo_location, instrument_location, pitch_location,
            volume_location
        ]

        for indx, loc in enumerate(self.gear_music_locations):
            loc.on_layout(self.music_box_gear_locations[indx],
                          center_gear_size / 2)

    def on_enter(self):
        if not self.use_tutorial and self.level == 1:
            while self.tutorial_skip_button in self.canvas.children:
                self.canvas.remove(self.tutorial_skip_button)

    def on_layout(self, winsize):
        mapped_dic = {'tempo': 0, 'instrument': 1, 'pitch': 2, 'volume': 3}
        self.update_center_gear_on_layout(winsize)

        self.size_dim = min(Window.width / 6, Window.height / 6)
        size = min(Window.width / 10, Window.height / 10)
        label_font_size = min(Window.width // 80, Window.height // 80)

        for loc in self.gear_storage_locations:
            scaled_x, scaled_y = self.get_scaled_x_y(winsize, loc.x, loc.y)
            loc.on_layout((scaled_x, scaled_y), size / 2)

        for indx, gear in enumerate(self.gears):
            scaled_x, scaled_y = self.get_scaled_x_y(winsize, gear.x, gear.y)
            gear.update_storage_pos((scaled_x, scaled_y))
            gear.update_music_pos(
                self.music_box_gear_locations[mapped_dic[gear.type]])
            gear.on_layout((scaled_x, scaled_y), size)

            self.gear_labels[indx].center_x = scaled_x
            self.gear_labels[indx].center_y = scaled_y
            self.gear_labels[indx].font_size = str(label_font_size) + 'sp'

        for center in self.gear_centers:
            scaled_x, scaled_y = self.get_scaled_x_y(winsize, center.x,
                                                     center.y)
            center.update_storage_pos((scaled_x, scaled_y))
            center.update_music_pos(
                self.music_box_gear_locations[mapped_dic[center.type]])
            center.on_layout((scaled_x, scaled_y), size / 2)

        # update level label
        self.label.center_x = self.size_dim * 1.5
        self.label.center_y = self.size_dim * 3 / 5
        self.label.font_size = str(Window.width // 20) + 'sp'

        # update you win label
        self.you_win_label.center_x = (Window.width / 2)
        self.you_win_label.center_y = (Window.height / 2)
        self.you_win_label.font_size = str(Window.width // 10) + 'sp'

        self.tempo_label.center_x = (Window.width / 4)
        self.tempo_label.center_y = (Window.height / 5.25 * (0.5 + 0.5) +
                                     self.gear_area.position[1])
        self.tempo_label.font_size = str(Window.width // 50) + 'sp'
        self.instrument_label.center_x = (Window.width / 4)
        self.instrument_label.center_y = (Window.height / 5.25 * (1.5 + 0.5) +
                                          self.gear_area.position[1])
        self.instrument_label.font_size = str(Window.width // 50) + 'sp'
        self.pitch_label.center_x = (Window.width / 4)
        self.pitch_label.center_y = (Window.height / 5.25 * (2.5 + 0.5) +
                                     self.gear_area.position[1])
        self.pitch_label.font_size = str(Window.width // 50) + 'sp'
        self.volume_label.center_x = (Window.width / 4)
        self.volume_label.center_y = (Window.height / 5.25 * (3.5 + 0.5) +
                                      self.gear_area.position[1])
        self.volume_label.font_size = str(Window.width // 50) + 'sp'

        # update child components
        self.gear_area.on_layout((Window.width, Window.height))
        self.music_box_area.on_layout((Window.width, Window.height))
        self.options.on_layout((Window.width, Window.height))

        # update particle effect and win/lose labels
        self.win_ps.emitter_x = Window.width / 2
        self.win_ps.emitter_y = Window.height / 2
        self.you_win_label.center_x = Window.width / 2
        self.you_win_label.center_y = Window.height / 2
        self.you_win_label.font_size = str(Window.width // 10) + 'sp'

        self.lose_ps.emitter_x = Window.width / 2
        self.lose_ps.emitter_y = Window.height / 2
        self.you_lose_label.center_x = Window.width / 2
        self.you_lose_label.center_y = Window.height / 2
        self.you_lose_label.font_size = str(Window.width // 10) + 'sp'

        # update error message location
        self.error_msg.center_x = Window.width / 2
        self.error_msg.center_y = Window.height / 2
        self.error_msg.font_size = str(Window.width // 20) + 'sp'

        # update tutorial overlays, label, and skip button
        if self.use_tutorial:
            self.update_tutorial_screen(self.tutorial_screen)
            self.tutorial_full_overlay.cpos = (Window.width / 2,
                                               Window.height / 2)
            self.tutorial_full_overlay.csize = (Window.width, Window.height)
            self.tutorial_options_overlay.size = (Window.width, self.size_dim +
                                                  Window.height / 25)
            self.tutorial_musicbox_overlay.pos = (Window.width // 2,
                                                  self.size_dim +
                                                  Window.height / 25)
            self.tutorial_musicbox_overlay.size = (
                Window.width / 2,
                Window.height - (self.size_dim + Window.height / 25))
            self.tutorial_gearbox_overlay.pos = (0, self.size_dim +
                                                 Window.height / 25)
            self.tutorial_gearbox_overlay.size = (
                Window.width / 2,
                Window.height - (self.size_dim + Window.height / 25))
            self.tutorial_skip_button.pos = (
                0.98 * Window.width -
                (self.skip_image.width * self.size_dim / 300),
                0.98 * Window.height -
                self.skip_image.height * self.size_dim / 300)
            self.tutorial_skip_button.size = (self.skip_image.width *
                                              self.size_dim / 300,
                                              self.skip_image.height *
                                              self.size_dim / 300)

    def reset(self):
        for gear in self.gears:
            # reset gear position
            gear.reset()
            # stop gear from rotating
            gear.stop()
        # stop center gear from rotating
        self.center_gear.stop()
        # stop music
        self.goal_music_seq.stop()
        if self.gear_music_seq:
            self.gear_music_seq.stop()

        # end tutorial
        if self.use_tutorial:
            self.tutorial_label.text = ''
            self.use_tutorial = False
            self.clear_overlays()
            while self.tutorial_skip_button in self.canvas.children:
                self.canvas.remove(self.tutorial_skip_button)

    def skip_tutorial_pressed(self, touch):
        if self.use_tutorial:
            if 0.98 * Window.width - (
                    self.skip_image.width * self.size_dim / 300
            ) < touch.pos[
                    0] < 0.98 * Window.width and 0.98 * Window.height - self.skip_image.height * self.size_dim / 300 < touch.pos[
                        1] < 0.98 * Window.height:
                return True
        return False

    def on_touch_up(self, touch):
        # if click is on one of the lower menu buttons, perform the appropriate action
        self.options.on_touch_up(self.switch_to, self.gear_music_seq,
                                 self.check_level_complete(), self.win_ps,
                                 self.you_win_label, self.lose_ps,
                                 self.you_lose_label, self.reset, touch)

        for index, gear in enumerate(self.gears):
            # response is true if you click the current gear
            response = gear.on_touch_up(touch.pos, self.gear_area.max_x,
                                        self._can_add_gear)
            self.gear_centers[index].on_touch_up(touch.pos,
                                                 self.gear_area.max_x,
                                                 self._can_add_gear)

            if response:
                if gear not in self.music_gears:
                    self.music_gears.append(gear)
                    # update the gear music based on the gear that is selected
                    function = 'self.gear_music.update_' + gear.type + '(' + str(
                        gear.value) + ')'
                    eval(function)

            else:
                if gear in self.music_gears:
                    self.music_gears.remove(gear)

        self.center_gear.on_touch_up(touch.pos, self.gear_area.max_x,
                                     self._can_add_gear)

        if self.use_tutorial:
            # if skip button pressed, quit out of tutorial mode
            if self.skip_tutorial_pressed(touch):
                self.use_tutorial = False
                self.remove_widget(self.tutorial_label)
                self.clear_overlays()
                while self.tutorial_skip_button in self.canvas.children:
                    self.canvas.remove(self.tutorial_skip_button)

            elif self.tutorial_screen == 'A':
                # show screen B (musicbox and gearbox covered)
                self.tutorial_screen = 'B'
                self.update_tutorial_screen('B')

            elif self.tutorial_screen == 'B':
                # show screen C (musicbox and options covered)
                self.tutorial_screen = 'C'
                self.update_tutorial_screen('C')

            elif self.tutorial_screen == 'C':
                # show screen D (gearbox and options covered)
                self.tutorial_screen = 'D'
                self.update_tutorial_screen('D')

            elif self.tutorial_screen == 'D':
                # show screen E (options covered)
                self.tutorial_screen = 'E'
                self.update_tutorial_screen('E')

            elif self.tutorial_screen == 'E' and self._check_music_gears():
                # if all gears have been placed, show screen F (gearbox covered)
                self.tutorial_screen = 'F'
                self.update_tutorial_screen('F')

            elif self.tutorial_screen == 'F' and self.gear_play_status == 'finished' and self.goal_play_status == 'finished':
                # if both tunes have been played show screen G (gearbox and musicbox covered)
                self.tutorial_screen = 'G'
                self.update_tutorial_screen('G')

            elif self.tutorial_screen == 'G':
                # end tutorial
                self.use_tutorial = False
                self.remove_widget(self.tutorial_label)
                self.clear_overlays()
                while self.tutorial_skip_button in self.canvas.children:
                    self.canvas.remove(self.tutorial_skip_button)

    def update_tutorial_screen(self, screen):
        if not self.use_tutorial:
            return

        self.remove_widget(self.tutorial_label)

        if self.tutorial_screen == 'A':
            self.activate_overlays(['full'])
            self.tutorial_label.center_x = Window.width / 2
            self.tutorial_label.center_y = Window.height / 2
            self.tutorial_label.text = "[font=./fonts/lato-bold]Welcome to the\n[/font] [font=./fonts/options-icons]|[/font] [font=./fonts/PassionOne-Regular]Play It By Gear Tutorial[/font] [font=./fonts/options-icons]|[/font] [font=./fonts/lato-bold]\n\nThe goal of this game is to make the \n goal song match the song you create by \nplacing the correct gears in a music box \n\n[/font] [font=./fonts/lato-light] (click to see the next \nstep of the tutorial)[/font]"
            self.tutorial_label.font_size = font_size = str(
                Window.width // 40) + 'sp'

        if self.tutorial_screen == 'B':
            self.activate_overlays(['musicbox', 'gearbox'])
            self.tutorial_label.center_x = 1 / 2 * Window.width
            self.tutorial_label.center_y = Window.height / 2 + (min(
                Window.width / 6, Window.height / 6) + Window.height / 25) / 2
            self.tutorial_label.text = "[font=./fonts/lato-bold]\nAt the bottom of the screen is the menu\nbar which contains some helpful buttons\n\nthe [/font] [font=./fonts/options-icons]^[/font] [font=./fonts/lato-bold] button brings\nyou back to the level select menu\n\nthe [/font] [font=./fonts/options-icons]`[/font] [font=./fonts/lato-bold] button resets the level\n\n[/font]  [font=./fonts/lato-light](click to continue)[/font]"
            self.tutorial_label.font_size = font_size = str(
                Window.width // 50) + 'sp'

        elif self.tutorial_screen == 'C':
            self.activate_overlays(['musicbox', 'options'])
            self.tutorial_label.center_x = 3 / 4 * Window.width
            self.tutorial_label.center_y = Window.height / 2 + (min(
                Window.width / 6, Window.height / 6) + Window.height / 25) / 2
            self.tutorial_label.text = "[font=./fonts/lato-bold]The left side of the screen\nhas all the gears you can choose\nfrom in order to make the\nmusic box sound correct\n\n[/font] [font=./fonts/lato-light](click to continue)[/font]"
            self.tutorial_label.font_size = font_size = str(
                Window.width // 60) + 'sp'

        elif self.tutorial_screen == 'D':
            self.activate_overlays(['gearbox', 'options'])
            self.tutorial_label.center_x = 1 / 4 * Window.width
            self.tutorial_label.center_y = Window.height / 2 + (min(
                Window.width / 6, Window.height / 6) + Window.height / 25) / 2
            self.tutorial_label.text = "[font=./fonts/lato-bold]The right side of the screen\nis the music box.  Gears in\nthe music box modify the song.\n\nYou need one gear of each\ntype/color in the music box in\norder for the song to play. \n\n[/font] [font=./fonts/lato-light](click to continue)[/font]"
            self.tutorial_label.font_size = font_size = str(
                Window.width // 60) + 'sp'

        elif self.tutorial_screen == 'E':
            self.activate_overlays(['options'])
            self.tutorial_label.center_x = Window.width / 2
            self.tutorial_label.center_y = (min(
                Window.width / 6, Window.height / 6) + Window.height / 25) / 2
            self.tutorial_label.text = "[font=./fonts/lato-bold]Now drag one gear of each type/color into the music box\n[/font] [font=./fonts/lato-light](when there are 4 gears in the music box, the tutorial will continue)[/font]"
            self.tutorial_label.font_size = font_size = str(
                Window.width // 60) + 'sp'

        elif self.tutorial_screen == 'F':
            self.activate_overlays(['gearbox'])
            self.tutorial_label.center_x = 1 / 4 * Window.width
            self.tutorial_label.center_y = Window.height / 2 + (min(
                Window.width / 6, Window.height / 6) + Window.height / 25) / 2
            self.tutorial_label.text = "[font=./fonts/lato-bold]Play the goal sound by pressing\nthe [/font] [font=./fonts/options-icons]_[/font] [font=./fonts/lato-bold] button, then press\nthe [/font] [font=./fonts/options-icons]~[/font] [font=./fonts/lato-bold] in the center gear to\nplay the song you created\nwith the gears\n\n[/font] [font=./fonts/lato-light](after you play both songs,\nclick again to continue)[/font]"
            self.tutorial_label.font_size = font_size = str(
                Window.width // 60) + 'sp'

        elif self.tutorial_screen == 'G':
            self.activate_overlays(['musicbox', 'gearbox'])
            self.tutorial_label.center_x = 1 / 2 * Window.width
            self.tutorial_label.center_y = Window.height / 2 + (min(
                Window.width / 6, Window.height / 6) + Window.height / 25) / 2
            self.tutorial_label.text = "[font=./fonts/lato-bold]Did the two songs sound the same?\n\nIf yes, you can press the [/font] [font=./fonts/options-icons]{[/font] [font=./fonts/lato-bold] button\n to see if you're correct\n\n If no, you can switch the gears in the music box\nuntil you think both songs sound the same\n\n[/font] [font=./fonts/lato-light](click to exit the tutorial)[/font]"
            self.tutorial_label.font_size = font_size = str(
                Window.width // 55) + 'sp'

        self.add_widget(self.tutorial_label)
        self.canvas.add(self.tutorial_skip_button)

    def on_touch_down(self, touch):
        other_gears = False
        for index, gear in enumerate(self.gears):
            cur_gear = gear.on_touch_down(touch.pos)
            other_gears = other_gears or cur_gear
            self.gear_centers[index].on_touch_down(touch.pos)

        if other_gears:
            if self.gear_music_seq:
                for gear in self.music_gears:
                    gear.stop()
                self.center_gear.stop()
                self.gear_music_seq.stop()
                self.gear_music_seq = None

        else:
            response = self.center_gear.on_touch_down(touch.pos)

            if response:
                if self._check_music_gears():
                    for gear in self.music_gears:
                        gear.toggle_rotate()

                    is_rotating = self.center_gear.toggle_rotate()

                    if is_rotating:
                        self.gear_music_seq = self.gear_music.generate()
                        self.gear_music_seq.start()
                        if self.use_tutorial and self.gear_play_status == None:
                            self.gear_play_status = 'started'
                    else:
                        if self.gear_music_seq:
                            self.gear_music_seq.stop()
                            self.gear_music_seq = None
                else:
                    if not self.use_tutorial:
                        self.error_msg.text = 'Place all 4 gears'

            else:
                self.error_msg.text = ' '
            return

        self.error_msg.text = ' '

    def on_touch_move(self, touch):
        for index, gear in enumerate(self.gears):
            gear.on_touch_move(touch.pos)
            self.gear_centers[index].on_touch_move(touch.pos)

    def on_update(self):
        self.goal_audio.on_update()
        self.gear_audio.on_update()
        self.options.on_update()
        for gear in self.gears:
            gear.on_update(1)
        self.center_gear.on_update(1)

        if self.gear_music_seq and not self.gear_music_seq.playing:
            for gear in self.music_gears:
                gear.stop()
            self.center_gear.stop()
            self.gear_music_seq = None
            if self.use_tutorial and self.gear_play_status == 'started':
                self.gear_play_status = 'finished'

    def check_level_complete(self):
        return self.goal_music.is_equal(self.gear_music)
示例#21
0
    def __init__(self):
        super(MainWidget3, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map  = SimpleTempoMap(104)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)        

        percNotes = [(480,35), (360,42), (120,35), (480,35), (480,42)]

        
        self.base1Notes = [(240,43), (240,43), (240,43), (120,47), (240,41), (240,41), (360,41), (120,40),
                      (360,41), (240,41), (240,41), (120,40), (120,36), (480,-1), (120,40), (240,41), (120,43)]

        self.base2Notes = [(120,-1), (120,45), (240,43), (120,-1), (240,43), (120,40), (480,43), (120,-1), (120,45), (120,45), (120,48),
                      (240,-1), (240,41), (120,-1), (240,41), (120,40), (480,41), (120,-1), (120,45), (120,45), (120,48),
                      (240,-1), (240,45), (120,-1), (240,45), (120,45), (480,45), (240,43), (120,-1), (120,45),
                      (240,-1), (240,45), (120,-1), (240,45), (120,45), (480,45), (120,-1), (120,45), (120,45), (120,48)]  
        
        self.baseNotes = self.base2Notes
        #[40, 41, 43, 45 48,]


        #changes / pitch sutff
        self.changes = [ (1920, [72, 74, 76, 79, 81, 84]),
                    (1920, [69, 72, 74, 81]),
                    (3840, [69, 72, 74, 76, 79, 81, 84])]

        self.changesIndex = 0
        self.curChanges = []
        self.selectSize = 2
        self.lastPitchIndex = None
        self.lastTouch = None


        #Note length stuff
        self.noteLengths = [480, 240, 120]
        self.articulation = 1
        self.lastPulseIndex = 0

        #Declare the players
        self.perc = NoteSequencer(self.sched, self.synth, 1, (128,0), percNotes)
        self.base1 = NoteSequencer(self.sched, self.synth, 2, (0,33), self.base1Notes, callback = self.graphic_callback)
        self.base2 = NoteSequencer(self.sched, self.synth, 2, (0,33), self.base2Notes, callback = self.graphic_callback)
        self.lead = Arpeggiator(self.sched, self.synth, channel = 3, program = (0,65), callback = self.graphic_callback)
        self.lead.set_direction('updown')
        #Start the non-interactive stuff
        now = self.sched.get_tick()
        next_beat = quantize_tick_up(now, 480)
        self.perc.toggle()
        self.base2.toggle()
        self.sched.post_at_tick(self._updateChanges, next_beat) #Update changes as music starts
        self.sched.post_at_tick(self._spawnCrossBar, next_beat)


        # and text to display our status
        #self.label = topleft_label()
        #self.add_widget(self.label)

        #Graphics stuff
        self.objects = AnimGroup()
        self.canvas.add(self.objects)
        #self.allNotes = [40, 41, 43, 45, 48, 900, 69, 72, 74, 76, 79, 81, 84]
        self.allNotes = [36, 40, 41, 43, 45, 47, 48, 900, 69, 72, 74, 76, 79, 81, 84]
示例#22
0
class MainWidget(BaseWidget):
    def __init__(self):
        super(MainWidget, self).__init__()

        self.writer = AudioWriter('song')
        self.audio = Audio(2, self.writer.add_audio)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(95*2)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)

        # variables to store options
        self.transposition = 0
        self.style = None
        self.melody = None
        self.chords = None
        self.chord_option = None
        self.perc = None
        self.perc_option = None

        # variables to store screen options
        self.style_selection = StyleSelection(self.update_style_screen)    # screen index 0
        self.key_selection = KeySelection(self.update_key_screen)          # screen index 1
        self.chord_selection = None                                 # screen index 2
        self.perc_selection = None                                  # screen index 3
        self.melody_selection = None                                # screen index 4

        self.active_screen = self.style_selection
        self.screen_index = 0
        self.add_widget(self.active_screen)

    def update_style_screen(self, option):
        self.style = option
        Window.clearcolor = stylcol[self.style][0]
        self.change_screens(self.key_selection)
        self.screen_index = 1

    def update_key_screen(self, instance):
        self.transposition = key_to_transpose[instance]

        # can now set up melody, chord, percussion settings
        self.melody = transpose_melody(self.style, 1, self.transposition)

        self.chords = transpose_instrument(self.style, "chords", self.transposition)
        self.chord_selection = ChordSelection(self.update_chord_screen, self.sched, self.synth, self.chords, stylcol[self.style][1])

        self.perc = transpose_instrument(self.style, "percussion", 0)
        self.perc_selection = PercSelection(self.update_perc_screen, self.sched, self.synth, self.perc, stylcol[self.style][1])

        self.change_screens(self.chord_selection)
        self.screen_index = 2

    def update_chord_screen(self, option):
        self.chord_option = option

        self.change_screens(self.perc_selection)
        self.screen_index = 3
    
    def update_perc_screen(self, option):
        self.perc_option = option

        # can now update our composition screen
        self.melody_selection = MelodySelection(
            self.synth, 
            self.sched, 
            self.chords[self.chord_option], 
            self.perc[self.perc_option],
            self.melody,
            self.change_key_button,
            self.change_chord_button,
            self.change_perc_button,
            self.writer
            )
        self.change_screens(self.melody_selection)
        self.screen_index = 4

    def change_key_button(self, instance):
        self.transposition = key_to_transpose[instance]
        self.melody = transpose_melody(self.style, 1, self.transposition)
        self.chords = transpose_instrument(self.style, "chords", self.transposition)

        self.melody_selection.stop()
        self.remove_widget(self.melody_selection)
        self.melody_selection = MelodySelection(
            self.synth, 
            self.sched, 
            self.chords[self.chord_option], 
            self.perc[self.perc_option],
            self.melody,
            self.change_key_button,
            self.change_chord_button,
            self.change_perc_button,
            self.writer
            )
        self.add_widget(self.melody_selection)
        self.active_screen = self.melody_selection

    def change_chord_button(self, instance):
        if self.chord_option == 1:
            option = 2
        else:
            option = 1

        self.chord_option = option

        self.melody_selection.change_chords(self.chords[self.chord_option])

    def change_perc_button(self, instance):
        if self.perc_option == 1:
            option = 2
        else:
            option = 1

        self.perc_option = option

        self.melody_selection.change_perc(self.perc[self.perc_option])

    def change_screens(self, screen):
        self.remove_widget(self.active_screen)
        self.active_screen = screen
        self.add_widget(self.active_screen)

    def on_touch_down(self, touch):
        self.active_screen.on_touch_down(touch)

    def on_touch_move(self, touch):
        self.active_screen.on_touch_move(touch)
    
    def on_key_down(self, keycode, modifiers):
        self.active_screen.on_key_down(keycode, modifiers)
        
        if keycode[1] == 'r':
            self.writer.toggle()

    def on_layout(self, winsize):
        if self.style_selection != None:
            self.style_selection.on_layout(winsize)

        if self.key_selection != None:
            self.key_selection.on_layout(winsize)

        if self.chord_selection != None:
            self.chord_selection.on_layout(winsize)

        if self.perc_selection != None:
            self.perc_selection.on_layout(winsize)

        if self.melody_selection != None:
            self.melody_selection.on_layout(winsize)

    def on_update(self):
        self.audio.on_update()
        self.active_screen.on_update()
示例#23
0
class MainWidget3(BaseWidget) :
    def __init__(self):
        super(MainWidget3, self).__init__()

        self.audio = Audio(2)
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map  = SimpleTempoMap(104)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.audio.set_generator(self.sched)
        self.sched.set_generator(self.synth)

        # create the metronome:
        self.metro = Metronome(self.sched, self.synth)        

        percNotes = [(480,35), (360,42), (120,35), (480,35), (480,42)]

        
        self.base1Notes = [(240,43), (240,43), (240,43), (120,47), (240,41), (240,41), (360,41), (120,40),
                      (360,41), (240,41), (240,41), (120,40), (120,36), (480,-1), (120,40), (240,41), (120,43)]

        self.base2Notes = [(120,-1), (120,45), (240,43), (120,-1), (240,43), (120,40), (480,43), (120,-1), (120,45), (120,45), (120,48),
                      (240,-1), (240,41), (120,-1), (240,41), (120,40), (480,41), (120,-1), (120,45), (120,45), (120,48),
                      (240,-1), (240,45), (120,-1), (240,45), (120,45), (480,45), (240,43), (120,-1), (120,45),
                      (240,-1), (240,45), (120,-1), (240,45), (120,45), (480,45), (120,-1), (120,45), (120,45), (120,48)]  
        
        self.baseNotes = self.base2Notes
        #[40, 41, 43, 45 48,]


        #changes / pitch sutff
        self.changes = [ (1920, [72, 74, 76, 79, 81, 84]),
                    (1920, [69, 72, 74, 81]),
                    (3840, [69, 72, 74, 76, 79, 81, 84])]

        self.changesIndex = 0
        self.curChanges = []
        self.selectSize = 2
        self.lastPitchIndex = None
        self.lastTouch = None


        #Note length stuff
        self.noteLengths = [480, 240, 120]
        self.articulation = 1
        self.lastPulseIndex = 0

        #Declare the players
        self.perc = NoteSequencer(self.sched, self.synth, 1, (128,0), percNotes)
        self.base1 = NoteSequencer(self.sched, self.synth, 2, (0,33), self.base1Notes, callback = self.graphic_callback)
        self.base2 = NoteSequencer(self.sched, self.synth, 2, (0,33), self.base2Notes, callback = self.graphic_callback)
        self.lead = Arpeggiator(self.sched, self.synth, channel = 3, program = (0,65), callback = self.graphic_callback)
        self.lead.set_direction('updown')
        #Start the non-interactive stuff
        now = self.sched.get_tick()
        next_beat = quantize_tick_up(now, 480)
        self.perc.toggle()
        self.base2.toggle()
        self.sched.post_at_tick(self._updateChanges, next_beat) #Update changes as music starts
        self.sched.post_at_tick(self._spawnCrossBar, next_beat)


        # and text to display our status
        #self.label = topleft_label()
        #self.add_widget(self.label)

        #Graphics stuff
        self.objects = AnimGroup()
        self.canvas.add(self.objects)
        #self.allNotes = [40, 41, 43, 45, 48, 900, 69, 72, 74, 76, 79, 81, 84]
        self.allNotes = [36, 40, 41, 43, 45, 47, 48, 900, 69, 72, 74, 76, 79, 81, 84]


    def graphic_callback(self, pitch, length):
        w = Window.width
        numBuckets = len(self.allNotes)
        bucket = self.allNotes.index(pitch)

        widthOfBucket = w/numBuckets
        width = widthOfBucket - 10

        leftX = bucket*widthOfBucket + 5

        height = length/480 * 100

        shape = NoteShape((leftX,0), height, width)
        self.objects.add(shape)

    def _spawnCrossBar(self, tick, ignore):

        shape = CrossBar()
        self.objects.add(shape)

        self.sched.post_at_tick(self._spawnCrossBar, tick+480)

    
    def _updateChanges(self, tick, ignore):
        timeTillNextChange = self.changes[self.changesIndex][0]
        self.curChanges = self.changes[self.changesIndex][1]

        #print("CHANGE OCCURED: ", self.curChanges)

        self.changesIndex = (self.changesIndex + 1) % len(self.changes)

        self.sched.post_at_tick(self._updateChanges, tick+timeTillNextChange)
        self.lastPitchIndex = None

        if self.lastTouch != None:
            self.update_pitches(self.lastTouch)
    
    def changeBaseLine(self):
        self.base1.toggle()
        self.base2.toggle()


    def on_key_down(self, keycode, modifiers):
        obj = lookup(keycode[1], 'm', (self.metro))
        if obj is not None:
            obj.toggle()
        
        if keycode[1] == 'q':
            self.changeBaseLine()

    def on_key_up(self, keycode):
        pass

    def on_touch_down(self, touch):
        p = touch.pos
        self.update_pitches(p)
        self.update_pulse(p)
        self.lead.start()
        self.lastTouch = p
        

    def on_touch_up(self, touch):
        self.lead.stop()

    def on_touch_move(self, touch):
        p = touch.pos
        self.update_pitches(p)
        self.update_pulse(p)
        self.lastTouch = p

    def update_pitches(self, pos=(0,0)):
        mouseX = pos[0]
        w = Window.width

        numBuckets = len(self.curChanges) - self.selectSize + 1
        sizeOfBucket = w / numBuckets

        noteBucket = int(mouseX // sizeOfBucket)


        if noteBucket != self.lastPitchIndex:

            arpegNotes = self.curChanges[noteBucket:noteBucket+self.selectSize]

            self.lead.set_pitches(arpegNotes)
            self.lastPitchIndex = noteBucket

    def update_pulse(self, pos=(0,0)):
        mouseY = pos[1]
        h = Window.height

        numBuckets = len(self.noteLengths)
        sizeOfBucket = h / numBuckets

        pulseBucket = int(mouseY // sizeOfBucket)

        if pulseBucket < len(self.noteLengths) and pulseBucket != self.lastPulseIndex:

            length = self.noteLengths[pulseBucket]
            self.lead.set_rhythm(length, self.articulation)
            self.lastPulseIndex = pulseBucket

    def on_update(self) :
        self.audio.on_update()
        self.objects.on_update()
示例#24
0
    def __init__(self, level, notes, goal_values, gear_values, **kwargs):
        super(LevelEasyMediumScreen, self).__init__(**kwargs)

        # set up notes for the level
        self.notes = notes

        # set up gear values for the levels
        self.goal_values = goal_values

        # set up gear values for the levels
        self.gear_values = gear_values

        self.level = level

        # only turn on tutorial for level 1
        if self.level == 1:
            self.use_tutorial = True
            self.tutorial_screen = 'A'
            self.goal_play_status = None
            self.gear_play_status = None
            self.size_dim = min(Window.width / 6, Window.height / 6)
            self.tutorial_full_overlay = CRectangle(cpos=(Window.width / 2,
                                                          Window.height / 2),
                                                    csize=(Window.width,
                                                           Window.height))
            self.tutorial_options_overlay = Rectangle(
                pos=(0, 0),
                size=(Window.width, self.size_dim + Window.height / 25))
            self.tutorial_musicbox_overlay = Rectangle(
                pos=(Window.width // 2, self.size_dim + Window.height / 25),
                size=(Window.width / 2,
                      Window.height - (self.size_dim + Window.height / 25)))
            self.tutorial_gearbox_overlay = Rectangle(
                pos=(0, self.size_dim + Window.height / 25),
                size=(Window.width / 2,
                      Window.height - (self.size_dim + Window.height / 25)))
            self.skip_image = CoreImage('images/skip_tutorial.png')
            self.tutorial_skip_button = Rectangle(
                pos=(0.98 * Window.width -
                     (self.skip_image.width * self.size_dim / 300),
                     0.98 * Window.height -
                     self.skip_image.height * self.size_dim / 300),
                size=(self.skip_image.width * self.size_dim / 300,
                      self.skip_image.height * self.size_dim / 300),
                texture=self.skip_image.texture)
        else:
            self.use_tutorial = False

        ############################################
        ###              GOAL MUSIC              ###
        ############################################
        self.goal_audio = Audio(2)
        self.goal_synth = Synth('./data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.goal_tempo_map = SimpleTempoMap(120)
        self.goal_sched = AudioScheduler(self.goal_tempo_map)

        # connect scheduler into audio system
        self.goal_audio.set_generator(self.goal_sched)
        self.goal_sched.set_generator(self.goal_synth)

        # generate goal music
        self.goal_music = MusicPlayer(notes=self.notes,
                                      sched=self.goal_sched,
                                      synth=self.goal_synth,
                                      channel=1,
                                      tempo_map=self.goal_tempo_map)
        self.goal_music.update_tempo(self.goal_values[0])
        self.goal_music.update_instrument(self.goal_values[1])
        self.goal_music.update_pitch(self.goal_values[2])
        self.goal_music.update_volume(self.goal_values[3])

        self.goal_music_seq = self.goal_music.generate()

        ############################################
        ###              GEAR MUSIC              ###
        ############################################
        self.gear_audio = Audio(2)
        self.gear_synth = Synth('./data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.gear_tempo_map = SimpleTempoMap(120)
        self.gear_sched = AudioScheduler(self.gear_tempo_map)

        # connect scheduler into audio system
        self.gear_audio.set_generator(self.gear_sched)
        self.gear_sched.set_generator(self.gear_synth)

        # generate gear music
        self.gear_music = MusicPlayer(notes=self.notes,
                                      sched=self.gear_sched,
                                      synth=self.gear_synth,
                                      channel=1,
                                      tempo_map=self.gear_tempo_map)
        self.gear_music_seq = None

        ############################################
        ###       BACKGROUND UI COMPONENTS       ###
        ############################################
        self.gear_area = GearArea()
        self.canvas.add(self.gear_area)

        self.music_box_area = MusicBoxArea()
        self.canvas.add(self.music_box_area)

        self.options = LevelOptions(
            level=level,
            goal_music_seq=self.goal_music_seq,
            duration=self.goal_music.duration,
            edit_goal_play_status=self.edit_goal_play_status)
        self.canvas.add(self.options)

        self.label = Label(text=kwargs['name'],
                           font_name='./fonts/PassionOne-Regular',
                           color=(.165, .718, .792, 1))
        self.add_widget(self.label)

        ###########################################
        ###             GEAR LABELS             ###
        ###########################################
        self.tempo_label = Label(text='Tempo (bpm)',
                                 font_name='./fonts/PassionOne-Regular',
                                 color=(0.7254901960784313, 0.5529411764705883,
                                        0.8196078431372549, 1),
                                 center_x=(Window.width / 4),
                                 center_y=(Window.height / 5.25 * (0.5 + 0.5) +
                                           self.gear_area.position[1]),
                                 font_size=str(Window.width // 50) + 'sp')
        self.instrument_label = Label(
            text='Instrument',
            font_name='./fonts/PassionOne-Regular',
            color=(0.996078431372549, 0.8431372549019608, 0.4, 1),
            center_x=(Window.width / 4),
            center_y=(Window.height / 5.25 * (1.5 + 0.5) +
                      self.gear_area.position[1]),
            font_size=str(Window.width // 50) + 'sp')
        self.pitch_label = Label(text='Pitch (semitones)',
                                 font_name='./fonts/PassionOne-Regular',
                                 color=(1.0, 0.6509803921568628,
                                        0.09019607843137255, 1),
                                 center_x=(Window.width / 4),
                                 center_y=(Window.height / 5.25 * (2.5 + 0.5) +
                                           self.gear_area.position[1]),
                                 font_size=str(Window.width // 50) + 'sp')
        self.volume_label = Label(
            text='Volume',
            font_name='./fonts/PassionOne-Regular',
            color=(0.9254901960784314, 0.32941176470588235, 0.3176470588235294,
                   1),
            center_x=(Window.width / 4),
            center_y=(Window.height / 5.25 * (3.5 + 0.5) +
                      self.gear_area.position[1]),
            font_size=str(Window.width // 50) + 'sp')
        self.add_widget(self.volume_label)
        self.add_widget(self.pitch_label)
        self.add_widget(self.instrument_label)
        self.add_widget(self.tempo_label)

        ###########################################
        ###          GEAR CONSTRUCTION          ###
        ###########################################

        self.gears = []
        self.gear_centers = []
        self.gears_group = AnimGroup()
        self.canvas.add(self.gears_group)

        ###########################################
        ###                GEARS                ###
        ###########################################
        self.gear_storage_locations = []
        self.gear_music_locations = []
        self.gear_labels = []
        self.set_up_gears()

        ###########################################
        ###           PARTICLE EFFECT           ###
        ###########################################
        self.win_ps = ParticleSystem('particles/star_particle.pex')
        self.win_ps.emitter_x = Window.width / 2
        self.win_ps.emitter_y = Window.height / 2
        self.add_widget(self.win_ps)
        self.you_win_label = Label(text=' ',
                                   font_name='./fonts/PassionOne-Regular',
                                   color=(0.5843137254901961,
                                          0.796078431372549,
                                          0.37254901960784315, 1),
                                   center_x=Window.width / 2,
                                   center_y=Window.height / 2,
                                   font_size=str(Window.width // 10) + 'sp')
        self.add_widget(self.you_win_label)

        self.lose_ps = ParticleSystem('particles/lose_particle.pex')
        self.lose_ps.emitter_x = Window.width / 2
        self.lose_ps.emitter_y = Window.height / 2
        self.add_widget(self.lose_ps)
        self.you_lose_label = Label(text=' ',
                                    font_name='./fonts/PassionOne-Regular',
                                    color=(0.9254901960784314,
                                           0.32941176470588235,
                                           0.3176470588235294, 1),
                                    center_x=Window.width / 2,
                                    center_y=Window.height / 2,
                                    font_size=str(Window.width // 10) + 'sp')
        self.add_widget(self.you_lose_label)

        ###########################################
        ###            ERROR MESSAGE            ###
        ###########################################
        self.error_msg = Label(text=' ',
                               font_name='./fonts/PassionOne-Regular',
                               color=(0.9254901960784314, 0.32941176470588235,
                                      0.3176470588235294, 1),
                               center_x=Window.width / 2,
                               center_y=Window.height / 2,
                               font_size=str(Window.width // 20) + 'sp')
        self.add_widget(self.error_msg)

        # ###########################################
        # ###        ADD TUTORIAL OVERLAYS        ###
        # ###########################################
        if self.use_tutorial:
            self.canvas.add(Color(rgba=(0, 0, 0, 0.85)))
            self.canvas.add(self.tutorial_full_overlay)
            self.tutorial_label = Label(
                markup=True,
                text=
                "[font=./fonts/lato-bold]Welcome to the\n[/font] [font=./fonts/options-icons]|[/font] [font=./fonts/PassionOne-Regular]Play It By Gear Tutorial[/font] [font=./fonts/options-icons]|[/font] [font=./fonts/lato-bold]\n\nThe goal of this game is to make the \n goal song match the song you create by \nplacing the correct gears in a music box \n\n[/font] [font=./fonts/lato-light] (click to see the next \nstep of the tutorial)[/font]",
                color=(86 / 255, 189 / 255, 205 / 255, 1),
                center_x=Window.width / 2,
                center_y=Window.height / 2,
                font_size=str(Window.width // 40) + 'sp',
                halign='center')
            self.add_widget(self.tutorial_label)
            self.canvas.add(self.tutorial_skip_button)

        self.on_layout((Window.width, Window.height))
示例#25
0
class MainWidget(BaseWidget):
    def __init__(self):
        super(MainWidget, self).__init__()

        self.audio = Audio(2,
                           input_func=self.receive_audio,
                           num_input_channels=1)
        self.mixer = Mixer()
        self.audio.set_generator(self.mixer)
        self.pitch = PitchDetector()
        self.recorder = VoiceAudioWriter('data')

        self.info = topleft_label()
        self.add_widget(self.info)

        self.anim_group = AnimGroup()

        self.mic_meter = MeterDisplay((50, 25), 150, (-96, 0), (.1, .9, .3))
        self.mic_graph = GraphDisplay((110, 25), 150, 300, (-96, 0),
                                      (.1, .9, .3))

        self.pitch_meter = MeterDisplay((50, 200), 150, (30, 90), (.9, .1, .3))
        self.pitch_graph = GraphDisplay((110, 200), 150, 300, (30, 90),
                                        (.9, .1, .3))

        self.canvas.add(self.mic_meter)
        self.canvas.add(self.mic_graph)
        self.canvas.add(self.pitch_meter)
        self.canvas.add(self.pitch_graph)

        # Record button
        self.record_button = InteractiveImage()
        self.record_button.source = "../data/mic.png"
        self.record_button.x = 400
        self.record_button.y = 400
        self.record_button.size = (100, 100)
        self.record_button.set_callback(self.init_recording)
        self.add_widget(self.record_button)

        # Play button
        self.play_button = InteractiveImage()
        self.play_button.source = "../data/play.png"
        self.play_button.x = 600
        self.play_button.y = 400
        self.play_button.size = (100, 100)
        self.play_button.set_callback(self.play_recording)
        self.add_widget(self.play_button)

        self.canvas.add(self.anim_group)

        self.onset_disp = None
        self.onset_x = 0
        self.cur_pitch = 0

        # Note Scheduler
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.mixer.add(self.sched)
        self.sched.set_generator(self.synth)

        # Note Sequencers
        self.seq = []

        # live Generator
        self.live_wave = None

    def on_update(self):
        self.audio.on_update()
        self.anim_group.on_update()

        self.info.text = 'fps:%d\n' % kivyClock.get_fps()
        self.info.text += 'load:%.2f\n' % self.audio.get_cpu_load()
        self.info.text += "pitch: %.1f\n" % self.cur_pitch
        self.info.text += 'max delta: %.3f\n' % self.onset_detector.get_max_delta(
        )
        self.info.text += 'onset delta thresh (up/down): %.3f\n' % self.onset_detector.onset_thresh

        if self.recorder.active:
            self.info.text += 'RECORDING'

    def receive_audio(self, frames, num_channels):
        assert (num_channels == 1)

        # Microphone volume level, take RMS, convert to dB.
        # display on meter and graph
        rms = np.sqrt(np.mean(frames**2))
        rms = np.clip(rms, 1e-10, 1)  # don't want log(0)
        db = 20 * np.log10(rms)  # convert from amplitude to decibels
        self.mic_meter.set(db)
        self.mic_graph.add_point(db)

        # pitch detection: get pitch and display on meter and graph
        self.cur_pitch = self.pitch.write(frames)
        self.pitch_meter.set(self.cur_pitch)
        self.pitch_graph.add_point(self.cur_pitch)

        # record audio
        self.recorder.add_audio(frames, num_channels)

        # onset detection and classification
        self.onset_detector.write(frames)

    def init_recording(self):
        data = self.recorder.toggle()
        if data:
            print(data)
            wave_gen, filename, duration_midi = data
            for i in range(len(duration_midi)):
                if duration_midi[i][0] < 0.12:
                    duration_midi[i] = (duration_midi[i][0], 0)
            duration_midi = harmony.harmonize(duration_midi)
            self.live_wave = wave_gen
            print([[i[1] for i in j] for j in duration_midi])

            tempo = 120
            multiplier = 1 / 60 * tempo * 480
            converted_midi_duration = [[(i * multiplier, j) for i, j in k]
                                       for k in duration_midi]

            for i in converted_midi_duration:
                self.seq.append(
                    NoteSequencer(self.sched, self.synth, 1, (0, 0), i, True))

    def play_recording(self):
        print("hello")
        for i in self.seq:
            i.start()
        if self.live_wave:
            self.mixer.add(self.live_wave)

    def on_key_down(self, keycode, modifiers):
        t = lookup(keycode[1], ['up', 'down'], [.001, -.001])
        if t is not None:
            self.onset_detector.onset_thresh += t

        if keycode[1] == "w":
            self.init_recording()

        if keycode[1] == "s" and self.seq:
            self.play_recording()
示例#26
0
class LevelSelectScreen(Screen):
    def __init__(self, **kwargs):
        super(LevelSelectScreen, self).__init__(**kwargs)

        Window.clearcolor = colors['grey'].rgba

        self.anim_group = AnimGroup()
        self.canvas.add(self.anim_group)

        self.label = Label(text='Play it by Gear',
                           font_name='./fonts/PassionOne-Regular',
                           color=(.165, .718, .792, 1))
        self.add_widget(self.label)

        self.buttons = []
        self.id_counter = 0

        self.audio = Audio(2)
        self.mixer = Mixer()
        self.audio.set_generator(self.mixer)
        self.start_time = None
        self.switch_level = None

        self.border_color = colors['dark_grey']
        self.border = Line(rectangle=(0, 0, Window.width, Window.height),
                           width=Window.width * 0.03)
        self.anim_group.add(self.border_color)
        self.anim_group.add(self.border)

        self.on_layout((Window.width, Window.height))

    def generate_buttons(self, row_pos, num_buttons, max_num_buttons, num_rows,
                         margin):
        for i in range(num_buttons):
            self.id_counter += 1
            square_dim = min(Window.width / (max_num_buttons + 2),
                             Window.height / (num_rows + 1))
            button = LevelButton(pos=(i / 6 * (Window.width) + margin,
                                      row_pos),
                                 size=(square_dim, square_dim),
                                 id=self.id_counter)
            self.buttons.append(button)
            self.anim_group.add(button)

    def on_touch_up(self, touch):
        for b in self.buttons:
            if b.is_clicked(touch):
                self.mixer.add(
                    WaveGenerator(WaveFile("./data/button_press.wav")))
                self.start_time = time.time()
                edit_progress_file(b.id, 'y')
                self.switch_level = 'Level ' + str(b.id)

    def on_enter(self):
        # update button colors by regenerating buttons
        self.on_layout((Window.width, Window.height))

    def on_layout(self, winsize):
        # update level buttons
        self.anim_group.remove_all()
        self.id_counter = 0
        self.buttons = []
        self.generate_buttons(row_pos=(3 * Window.height / 5 -
                                       Window.height / 10),
                              num_buttons=4,
                              max_num_buttons=5,
                              num_rows=3,
                              margin=Window.width / 6)
        self.generate_buttons(row_pos=(2 * Window.height / 5 -
                                       Window.height / 10),
                              num_buttons=5,
                              max_num_buttons=5,
                              num_rows=3,
                              margin=Window.width / 12)
        self.generate_buttons(row_pos=(1 * Window.height / 5 -
                                       Window.height / 10),
                              num_buttons=4,
                              max_num_buttons=5,
                              num_rows=3,
                              margin=Window.width / 6)

        # update title label
        self.label.center_x = Window.width / 2
        self.label.center_y = 5 * Window.height / 6
        self.label.font_size = str(Window.width // 15) + 'sp'

        # update border
        self.border_color = colors['dark_grey']
        self.border = Line(rectangle=(0, 0, Window.width, Window.height),
                           width=Window.width * 0.03)
        self.anim_group.add(self.border_color)
        self.anim_group.add(self.border)

    def on_update(self):
        self.audio.on_update()
        if self.start_time and time.time() - self.start_time > 0.13:
            self.start_time = None
            self.switch_to(self.switch_level)
示例#27
0
class MainScreen(Screen):
    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)

        mode = 'mac' if (len(sys.argv) == 2) and (sys.argv[1]
                                                  == 'mac') else 'pc'
        self.norm = Normalizer(mode)

        self.info = topleft_label()
        self.add_widget(self.info)

        self.writer = AudioWriter('recordings/song')
        self.audio = Audio(2, self.writer.add_audio)
        self.mixer = Mixer()
        self.mixer.set_gain(1.0)
        self.audio.set_generator(self.mixer)

        self.sandbox = Sandbox(canvas=self.canvas,
                               pos=self.norm.nt((580, 50)),
                               size=self.norm.nt((1000, 1000)))

        # since putting all our sound module code in MainScreen would be a nightmare, we've
        # modularized our modules into separate files. each module has two classes, the sound
        # module itself and its handler class. the handler class is essentially a wrapper of
        # many of MainScreen's important event functions (e.g. on_touch_down) that keeps track
        # of all variables related to that sound module for every connected client.
        self.module_dict = {
            'PhysicsBubble': PhysicsBubble,
            'SoundBlock': SoundBlock,
            'TempoCursor': TempoCursor
        }
        block = SoundBlockHandler(self.norm, self.sandbox, self.mixer, client,
                                  client_id)
        self.module_handlers = {
            'SoundBlock':
            block,
            'PhysicsBubble':
            PhysicsBubbleHandler(self.norm, self.sandbox, self.mixer, client,
                                 client_id, block),
            'TempoCursor':
            TempoCursorHandler(self.norm, self.sandbox, self.mixer, client,
                               client_id, block)
        }

        # name a default starting module and handler
        self.module = PhysicsBubble
        self.module_handler = self.module_handlers[self.module.name]
        self.sandbox.add(self.module_handler.gui)

        # sync with existing server state
        client.emit('sync_module_state', {'module': 'PhysicsBubble'})
        client.emit('sync_module_state', {'module': 'SoundBlock'})
        client.emit('sync_module_state', {'module': 'TempoCursor'})
        client.emit('update_norm', {'norm': {client_id: self.norm.mode}})

    def on_touch_down(self, touch):
        if touch.button != 'left':
            return

        global client, client_id
        data = {'cid': client_id, 'module': self.module.name, 'pos': touch.pos}
        client.emit('touch_down', data)

    def on_touch_move(self, touch):
        if touch.button != 'left':
            return

        global client, client_id
        data = {'cid': client_id, 'module': self.module.name, 'pos': touch.pos}
        client.emit('touch_move', data)

    def on_touch_up(self, touch):
        if touch.button != 'left':
            return

        global client, client_id
        data = {'cid': client_id, 'module': self.module.name, 'pos': touch.pos}
        client.emit('touch_up', data)

    def on_key_down(self, keycode, modifiers):
        global client, client_id
        key = keycode[1]

        # switch module using keys (for now)
        module_name = lookup(key, 'zxc',
                             ['PhysicsBubble', 'SoundBlock', 'TempoCursor'])
        if module_name is not None:
            old_handler = self.module_handler
            new_handler = self.module_handlers[module_name]
            if old_handler.module_name != new_handler.module_name:
                self.sandbox.remove(old_handler.gui)
                self.sandbox.add(new_handler.gui)
                self.module = self.module_dict[module_name]
                self.module_handler = new_handler
        elif key == 'spacebar':
            print('boop')
            self.writer.toggle()
        else:
            data = {'cid': client_id, 'module': self.module.name, 'key': key}
            client.emit('key_down', data)

    def on_update(self):
        self.audio.on_update()
        for _, handler in self.module_handlers.items():
            handler.on_update()

        self.info.text = 'module: {}\n\n'.format(self.module.name)
        self.info.text += self.module_handler.display_controls()

    def on_layout(self, win_size):
        resize_topleft_label(self.info)

    def update_count(self, count):
        self.count = count
示例#28
0
    def __init__(self):
        super(MainWidget, self).__init__()

        self.audio = Audio(2,
                           input_func=self.receive_audio,
                           num_input_channels=1)
        self.mixer = Mixer()
        self.audio.set_generator(self.mixer)
        self.pitch = PitchDetector()
        self.recorder = VoiceAudioWriter('data')

        self.info = topleft_label()
        self.add_widget(self.info)

        self.anim_group = AnimGroup()

        self.mic_meter = MeterDisplay((50, 25), 150, (-96, 0), (.1, .9, .3))
        self.mic_graph = GraphDisplay((110, 25), 150, 300, (-96, 0),
                                      (.1, .9, .3))

        self.pitch_meter = MeterDisplay((50, 200), 150, (30, 90), (.9, .1, .3))
        self.pitch_graph = GraphDisplay((110, 200), 150, 300, (30, 90),
                                        (.9, .1, .3))

        self.canvas.add(self.mic_meter)
        self.canvas.add(self.mic_graph)
        self.canvas.add(self.pitch_meter)
        self.canvas.add(self.pitch_graph)

        # Record button
        self.record_button = InteractiveImage()
        self.record_button.source = "../data/mic.png"
        self.record_button.x = 400
        self.record_button.y = 400
        self.record_button.size = (100, 100)
        self.record_button.set_callback(self.init_recording)
        self.add_widget(self.record_button)

        # Play button
        self.play_button = InteractiveImage()
        self.play_button.source = "../data/play.png"
        self.play_button.x = 600
        self.play_button.y = 400
        self.play_button.size = (100, 100)
        self.play_button.set_callback(self.play_recording)
        self.add_widget(self.play_button)

        self.canvas.add(self.anim_group)

        self.onset_disp = None
        self.onset_x = 0
        self.cur_pitch = 0

        # Note Scheduler
        self.synth = Synth('../data/FluidR3_GM.sf2')

        # create TempoMap, AudioScheduler
        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)

        # connect scheduler into audio system
        self.mixer.add(self.sched)
        self.sched.set_generator(self.synth)

        # Note Sequencers
        self.seq = []

        # live Generator
        self.live_wave = None
示例#29
0
class PuzzleSound(object):
    def __init__(self,
                 notes,
                 bank=0,
                 preset=0,
                 loop=False,
                 simon_says=False,
                 bass_puzzle=False):
        super().__init__()
        self.audio = Audio(2)
        self.synth = Synth("./data/FluidR3_GM.sf2")

        self.tempo_map = SimpleTempoMap(120)
        self.sched = AudioScheduler(self.tempo_map)
        self.sched.set_generator(self.synth)
        self.audio.set_generator(self.sched)

        self.notes = notes
        self.bank = bank
        self.preset = preset
        self.loop = loop
        self.simon_says = simon_says
        self.bass_puzzle = bass_puzzle

        self.note_seq = NoteSequencer(
            sched=self.sched,
            synth=self.synth,
            channel=1,
            program=(self.bank, self.preset),
            notes=self.notes,
            loop=self.loop,
        )

    def set_notes(self, notes):
        self.notes = notes
        if self.simon_says or self.bass_puzzle:
            self.note_seq = NoteSequencer(
                sched=self.sched,
                synth=self.synth,
                channel=1,
                program=(self.bank, self.preset),
                notes=self.notes,
                loop=self.loop,
            )

        self.note_seq.stop()
        self.note_seq.set_notes(self.notes)

        if self.bank == 0:
            self.letters = [n.get_letter() for n in self.notes]

    def set_cb_ons(self, cb_ons):
        self.note_seq.set_cb_ons(cb_ons)

    def set_cb_offs(self, cb_offs):
        self.note_seq.set_cb_offs(cb_offs)

    def set_on_finished(self, on_finished):
        self.note_seq.set_on_finished(on_finished)

    def toggle(self):
        self.note_seq.toggle()

    def on_update(self):
        self.audio.on_update()