Beispiel #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))
Beispiel #2
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"))
Beispiel #4
0
    def __init__(self):
        super(GameObject, self).__init__()

        self._graphics = Graphics()
        self._transform = Transform(self._graphics)
        self._mixer = Mixer()
        self._parent = None
        self._game_objects = set()
        self._widgets = set()
        self._event_listeners = defaultdict(lambda: [])

        self.updating = False
        self.to_add = []
    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
Beispiel #6
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
Beispiel #7
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()
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()
Beispiel #9
0
class GameObject(object):
    '''
	Game Objects can contain each other 
	(like HTML divs, or something)
	'''
    def __init__(self):
        super(GameObject, self).__init__()

        self._graphics = Graphics()
        self._transform = Transform(self._graphics)
        self._mixer = Mixer()
        self._parent = None
        self._game_objects = set()
        self._widgets = set()
        self._event_listeners = defaultdict(lambda: [])

        self.updating = False
        self.to_add = []

    @property
    def game_objects(self):
        return self._game_objects

    @property
    def client(self):
        return self.base_widget.client_obj if self.base_widget else None

    @property
    def base_widget(self):
        if self._parent:
            return self._parent.base_widget
        return None

    @property
    def widgets(self):
        widgets = self._widgets.copy()
        for go in self._game_objects:
            widgets.update(go.widgets)
        return widgets

    def add_widget(self, widget):
        self._widgets.add(widget)
        # self._add_widget(widget)

    def get_abs_pos(self):
        x = self.position.x
        y = self.position.y
        x *= self.scale.x
        y *= self.scale.y
        parent = self._parent
        while parent is not None:
            xp = parent.position.x
            yp = parent.position.y
            x += xp * parent.scale.x
            y += yp * parent.scale.y
            parent = parent._parent

        return x, y

    def on_add(self):
        pass

    @property
    def position(self):
        return self._transform.position

    @position.setter
    def position(self, new_pos):
        self._transform.position.xy = new_pos
        for widget in self._widgets:
            widget.pos = new_pos

    @property
    def rotation(self):
        return self._transform.rotation

    @rotation.setter
    def rotation(self, new_rotation):
        self._transform.rotation.angle = new_rotation

    @property
    def scale(self):
        return self._transform.scale

    @scale.setter
    def scale(self, new_scale):
        self._transform.scale.x = new_scale
        self._transform.scale.y = new_scale

    def add_graphic(self, graphic):
        self._graphics.add(graphic)

    def remove_graphic(self, graphic):
        self._graphics.remove(graphic)

    def add_generator(self, generator):
        self._mixer.add(generator)

    def remove_generator(self, generator):
        self._mixer.remove(generator)

    def add(self, *game_objects):
        for go in game_objects:
            if self.updating:
                self.to_add.append(go)
            else:
                self.add_game_object(go)
                go.on_add()

    def add_game_object(self, game_object):
        # self.add_widget(game_object)
        # assert game_object._parent == None, 'game object already has parent'
        if game_object._parent:
            game_object._parent.remove(game_object)
        game_object._parent = self
        self._game_objects.add(game_object)
        self._graphics.add(game_object._transform)
        self._mixer.add(game_object._mixer)

    def remove(self, *game_objects):
        for go in game_objects:
            self.remove_game_object(go)

    def remove_game_object(self, game_object):
        # pass
        if game_object._parent != self: return
        game_object._parent = None
        self._game_objects.remove(game_object)
        self._graphics.remove(game_object._transform)
        self._mixer.remove(game_object._mixer)

    def add_event_listener(self, event, callback):
        self._event_listeners[event].append(callback)

    def trigger_event(self, event_type, **kwargs):
        assert self._parent != None, 'Game Object needs to be attached to a scene. Event Lost to the void'
        self._parent.trigger_event(event_type, **kwargs)

    def _handle_event(self, event):
        if hasattr(self, event.type):
            getattr(self, event.type)(event)

        for callback in self._event_listeners[event.type]:
            callback(self, event)

        for go in self._game_objects:
            go._handle_event(event)

    def _on_update(self):
        self.updating = True
        self.on_update()
        dt = kivyClock.frametime
        self._graphics.on_update(dt)
        for go in self._game_objects:
            go._on_update()
        self.updating = False
        for go in self.to_add:
            self.add(go)
        self.to_add = []

    def on_update(self):
        pass

    def on_add(self):
        pass
Beispiel #10
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
Beispiel #11
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)
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]