Ejemplo n.º 1
0
    def __init__(self,
                 norm,
                 sandbox,
                 pos,
                 vel,
                 pitch,
                 timbre,
                 color,
                 bounces,
                 handler,
                 gravity=False,
                 callback=None):
        """
        :param norm: normalizer
        :param sandbox: client's sandbox
        :param pos: initial position
        :param vel: initial velocity
        :param pitch: MIDI pitch value, where 60 is middle C
        :param timbre: type of waveform, e.g. 'sine' or 'sawtooth'
        :param color: 3-tuple of RGB color
        :param bounces: number of times the bubble bounces before fading away
        :param gravity: whether or not the bubble is subjected to downwards gravity
        :param callback: the sound function that is called when the bubble bounces
        """
        super(PhysicsBubble, self).__init__()

        self.norm = norm
        self.sandbox = sandbox

        self.r = self.norm.nv(40)
        self.pos = np.array(pos, dtype=np.float)
        self.vel = 2 * np.array(vel, dtype=np.float)

        self.pitch = pitch
        self.timbre = timbre
        self.color = Color(*color)
        self.text_color = Color(0, 0, 0)
        self.bounces = bounces
        self.gravity = gravity
        self.callback = callback
        self.handler = handler

        self.text = CLabelRect(cpos=pos, text=str(self.bounces))
        self.bubble = self.timbre_to_shape(self.timbre, pos)

        self.add(self.color)
        self.add(self.bubble)
        self.add(self.text_color)
        self.add(self.text)

        # have the bubble fade away when self.bounces = 0
        self.fade_anim = KFAnim((0, 1), (0.25, 0))
        self.time = 0

        self.on_update(0)
Ejemplo n.º 2
0
 def create_instructions(self, win_size):
     self.instructions_text_color = Color(rgba=(1, 1, 1, 1))
     self.instructions_text = CLabelRect(
         (win_size[0] // 8, win_size[1] * 4 / 7),
         "Press + to hear your note sequence.\nPress - to hear the sequence\nyou are trying to match.",
         20,
     )
Ejemplo n.º 3
0
    def create_instructions(self):
        margin = self.grid.tile_side_len // 2
        self.instructions_window_color = Color(rgba=(1, 1, 1, 1))
        self.instructions_window = Rectangle(
            pos=(margin, margin),
            size=(
                self.grid.grid_side_len - 2 * margin -
                2 * self.grid.tile_side_len,
                3 * self.grid.tile_side_len - 2 * margin,
            ),
        )
        self.instructions_text_color = Color(rgba=(0, 0, 0, 1))
        self.instructions_text = CLabelRect(
            (self.win_size[0] // 2, self.win_size[1] // 4.3),
            "Move around the room with the arrow keys\n" +
            "Press 'a' to interact with objects",
            34,
        )

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

        self.add(self.instructions_window_color)
        self.add(self.instructions_window)

        self.add(PopMatrix())

        self.add(self.instructions_text_color)
        self.add(self.instructions_text)
Ejemplo n.º 4
0
    def __init__(self, norm, pos, beat_callback):
        super(CursorGUI, self).__init__()

        self.norm = norm
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.size = self.norm.nt((300, 350))
        self.white = (239 / 255, 226 / 255, 222 / 255)
        self.title_height = self.norm.nv(50)  # height of the word 'instrument'
        self.title = 'beat select'
        x, y = self.pos

        title_pos = (x + self.size[0] / 2, y + self.size[1] -
                     self.title_height / 2 - self.margin / 2)
        self.title = CLabelRect(cpos=title_pos,
                                text=self.title,
                                font_size='18')
        self.add(Color(*self.white))
        self.add(self.title)

        self.add(Color(1, 1, 1))
        self.add(Line(rectangle=(*self.pos, *self.size), width=2))

        bs_pos = (self.pos[0] + self.norm.nv(20),
                  self.pos[1] + self.norm.nv(20))
        self.bs = BeatSelect(self.norm, bs_pos, beat_callback)
        self.add(self.bs)
Ejemplo n.º 5
0
 def create_game_over_text(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 Win!", 70
     )
Ejemplo n.º 6
0
    def __init__(self, prev_room, level=0, on_finished_puzzle=None):
        super().__init__()
        self.door_sources = {
            (4, 9): "./data/Door_up.png",  # UP
            (4, -1): "./data/door_down.png",  # DOWN
            (-1, 4): "./data/door_left.png",  # LEFT
            (9, 4): "./data/Door_right.png",  # RIGHT
        }

        self.prev_room = prev_room
        self.on_finished_puzzle = on_finished_puzzle
        self.animations = AnimGroup()
        self.level = level
        self.notes, self.actual_key = levels[level]
        duration = choice(durations)
        pitch_shift = choice(range(-3, 4))
        self.user_notes = [
            Note(duration,
                 n.get_pitch() + pitch_shift) for n in self.notes
        ]
        render_user_notes = self.level < 2

        self.actual_sound = PuzzleSound(self.notes)
        self.user_sound = PuzzleSound(self.user_notes)
        self.music_bar = MusicBar(self.notes, self.user_notes,
                                  render_user_notes, self.actual_sound)
        self.animations.add(self.music_bar)
        self.add(self.animations)

        self.user_key = "C"

        self.place_objects()

        self.key_label = CLabelRect(
            (Window.width // 30, 23 * Window.height // 32),
            f"Key: {self.user_key}", 34)
        self.add(Color(rgba=(1, 1, 1, 1)))
        self.add(self.key_label)
        self.create_instructions((Window.width, Window.height))
        self.add(self.instructions_text_color)
        self.add(self.instructions_text)
        self.objects = {}
Ejemplo n.º 7
0
    def __init__(self, mode):
        super(HelpDisplay, self).__init__()
        self.mode = mode

        # Start levels
        self.start_box_color = Color(0, 1, 0, 0.2)
        self.start_box = Rectangle(pos=(0.1 * w, 0.7 * h),
                                   size=(0.8 * w, 0.2 * h))
        self.start_text_color = Color(0, 1, 0, 0.8)
        if mode == 'lmode':
            start_text = "Start off with these levels"
            cpos = (0.75 * w, 0.88 * h)
        elif mode == 'gmode':
            start_text = "Complete the learning mode to unlock the first level"
            cpos = (0.6 * w, 0.88 * h)
        self.start_text = CLabelRect(text=start_text,
                                     font_size=font_sz / 4,
                                     font_name=font_name,
                                     cpos=cpos)
        self.add(self.start_box_color)
        self.add(self.start_box)
        self.add(self.start_text_color)
        self.add(self.start_text)

        # Locked levels
        self.locked_box_color = Color(1, 1, 0, 0.2)
        self.locked_box = Rectangle(pos=(0.1 * w, 0.2 * h),
                                    size=(0.8 * w, 0.5 * h))
        self.locked_text_color = Color(1, 1, 0, 0.8)
        if mode == 'lmode':
            locked_text = "Complete the easier levels to unlock new ones"
        elif mode == 'gmode':
            locked_text = "Pass the easier level to unlock the next one"
        self.locked_text = CLabelRect(text=locked_text,
                                      font_size=font_sz / 4,
                                      font_name=font_name,
                                      cpos=(0.65 * w, 0.25 * h))
        self.add(self.locked_box_color)
        self.add(self.locked_box)
        self.add(self.locked_text_color)
        self.add(self.locked_text)
Ejemplo n.º 8
0
 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')
Ejemplo n.º 9
0
    def __init__(self):
        super(TimerDisplay, self).__init__()
        self.duration = 30.
        self.start_x = Window.width * 0.2
        self.end_x = Window.width * .85
        self.start_y = Window.height * .2
        self.end_y = Window.height * .25

        # Initialize moving timer
        self.color = Color(0, 1, 0)  # start off green
        self.bar = Rectangle(pos=(self.start_x, self.start_y),
                             size=(self.end_x - self.start_x,
                                   self.end_y - self.start_y))
        self.add(self.color)
        self.add(self.bar)

        self.remaining_time = CLabelRect(
            cpos=(self.end_x + 50, self.start_y),
            text=str(int(self.duration)),
            font_size=(self.end_y - self.start_y) / 2,
            font_name="assets/AtlantisInternational")
        self.add(self.remaining_time)

        # Vertical borders
        self.border_left = Line(width=2)
        self.border_mid = Line(width=2)
        self.border_right = Line(width=2)
        self.add(self.border_left)
        self.add(self.border_right)
        self.add(self.border_mid)

        # Horizontal borders
        self.border_bot = Line(width=2)
        self.border_top = Line(width=2)
        self.add(self.border_bot)
        self.add(self.border_top)

        self.on_layout(Window.size)
Ejemplo n.º 10
0
    def on_layout(self, win_size):
        self.remove(self.character)
        self.remove(self.grid)
        self.remove(self.instructions_text_color)
        self.remove(self.instructions_text)
        self.grid.on_layout((win_size[0], 0.75 * win_size[1]))
        for pos, obj in self.objects.items():
            self.remove(obj)

        self.add(self.grid)
        if not self.objects:
            self.create_objects()
        self.place_objects()
        self.character.on_layout(win_size)
        self.add(self.character)

        self.music_bar.on_layout(win_size)
        self.remove(self.key_label)
        self.key_label = CLabelRect(
            (win_size[0] // 30, 23 * win_size[1] // 32),
            f"Key: {self.user_key}", 34)
        self.add(Color(rgba=(1, 1, 1, 1)))
        self.add(self.key_label)

        self.create_instructions(win_size)
        self.add(self.instructions_text_color)
        self.add(self.instructions_text)

        self.create_game_over_text(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.on_game_over()
Ejemplo n.º 11
0
    def on_touch_down(self, cid, pos):
        if cid == self.cid:
            self.gui.on_touch_down(pos)

        if not self.sandbox.in_bounds(pos):
            return

        # start drawing drag line and preview of the PhysicsBubble
        self.hold_point[cid] = pos
        self.hold_shape[cid] = self.timbre_to_shape(self.timbre[cid], pos)
        self.hold_line[cid] = Line(points=(*pos, *pos), width=3)
        self.text[cid] = CLabelRect(cpos=pos, text=str(self.bounces[cid]))

        # if self.skip.get(cid) == True:
        #     self.skip[cid] = False
        #     return

        self.sandbox.add(Color(*self.color[cid]))
        self.sandbox.add(self.hold_shape[cid])
        self.sandbox.add(self.hold_line[cid])
        self.sandbox.add(self.text_color)
        self.sandbox.add(self.text[cid])
Ejemplo n.º 12
0
    def __init__(self, norm, pos, callback):
        super(GravitySelect, self).__init__()
        self.norm = norm

        self.callback = callback
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.check_size = self.norm.nt((50, 50))
        self.size = (
            self.norm.nv(210),
            2*self.margin + self.check_size[1]
        )

        self.border_color = Color(50/255, 147/255, 140/255) # bluegreen
        self.border = Line(rectangle=(*self.pos, *self.size), width=2)
        self.add(self.border_color)
        self.add(self.border)

        self.check_color = Color(1, 1, 1)
        self.off = Rectangle(
            pos=(self.pos[0] + self.margin, self.pos[1] + self.margin),
            size=self.check_size,
            texture=Image('ui/buttons/unchecked.png').texture
        )
        self.on = Rectangle(
            pos=(self.pos[0] + self.margin, self.pos[1] + self.margin),
            size=self.check_size,
            texture=Image('ui/buttons/checked.png').texture
        )
        self.add(self.check_color)
        self.add(self.off)

        title_pos = (
            self.pos[0] + self.norm.nv(140),
            self.pos[1] + self.check_size[1]/2 + self.margin
        )
        self.title = CLabelRect(cpos=title_pos, text='gravity', font_size='18')
        self.add(Color(1, 1, 1))
        self.add(self.title)
Ejemplo n.º 13
0
    def __init__(self, norm, pos, callback):
        super(TimbreSelect, self).__init__()
        self.norm = norm

        self.selected = 'sine' # the actual important variable: which timbre is selected!

        self.callback = callback
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.button_length = self.norm.nv(64)
        self.title_height = self.norm.nv(50) # height of the word 'timbre'
        self.size = (
            (4 * self.button_length) + (5 * self.margin),
            self.button_length + (2 * self.margin) + self.title_height
        )

        self.white = (239/255, 226/255, 222/255)
        self.red = (201/255, 108/255, 130/255)

        self.border_color = Color(147/255, 127/255, 159/255) # purple
        self.border = Line(rectangle=(*self.pos, *self.size), width=2)
        self.add(self.border_color)
        self.add(self.border)

        button_size = (self.button_length, self.button_length)
        self.timbres = {
            'sine': Rectangle(size=button_size, texture=Image('images/sine.png').texture),
            'square': Rectangle(size=button_size, texture=Image('images/square.png').texture),
            'triangle': Rectangle(size=button_size, texture=Image('images/triangle.png').texture),
            'sawtooth': Rectangle(size=button_size, texture=Image('images/sawtooth.png').texture)
        }
        self.timbre_bgs = {
            'sine': Rectangle(size=button_size),
            'square': Rectangle(size=button_size),
            'triangle': Rectangle(size=button_size),
            'sawtooth': Rectangle(size=button_size)
        }
        self.timbre_colors = {
            'sine': Color(*self.red), # default selected timbre
            'square': Color(*self.white),
            'triangle': Color(*self.white),
            'sawtooth': Color(*self.white)
        }

        x, y = self.pos

        sine_pos = (x + self.margin, y + self.margin)
        square_pos = (x + 2*self.margin + self.button_length, y + self.margin)
        triangle_pos = (x + 3*self.margin + 2*self.button_length, y + self.margin)
        sawtooth_pos = (x + 4*self.margin + 3*self.button_length, y + self.margin)

        for timbre, timbre_pos in zip(
            ('sine', 'square', 'triangle', 'sawtooth'),
            (sine_pos, square_pos, triangle_pos, sawtooth_pos)
        ):
            self.timbres[timbre].pos = self.timbre_bgs[timbre].pos = timbre_pos
            self.add(self.timbre_colors[timbre])
            self.add(self.timbre_bgs[timbre])
            self.add(self.timbres[timbre])

        title_pos = (x + self.size[0]/2, y + self.size[1] - self.title_height/2 - self.margin/2)
        self.title = CLabelRect(cpos=title_pos, text='timbre', font_size='18')
        self.add(Color(*self.white))
        self.add(self.title)
Ejemplo n.º 14
0
class TimerDisplay(InstructionGroup):
    def __init__(self):
        super(TimerDisplay, self).__init__()
        self.duration = 30.
        self.start_x = Window.width * 0.2
        self.end_x = Window.width * .85
        self.start_y = Window.height * .2
        self.end_y = Window.height * .25

        # Initialize moving timer
        self.color = Color(0, 1, 0)  # start off green
        self.bar = Rectangle(pos=(self.start_x, self.start_y),
                             size=(self.end_x - self.start_x,
                                   self.end_y - self.start_y))
        self.add(self.color)
        self.add(self.bar)

        self.remaining_time = CLabelRect(
            cpos=(self.end_x + 50, self.start_y),
            text=str(int(self.duration)),
            font_size=(self.end_y - self.start_y) / 2,
            font_name="assets/AtlantisInternational")
        self.add(self.remaining_time)

        # Vertical borders
        self.border_left = Line(width=2)
        self.border_mid = Line(width=2)
        self.border_right = Line(width=2)
        self.add(self.border_left)
        self.add(self.border_right)
        self.add(self.border_mid)

        # Horizontal borders
        self.border_bot = Line(width=2)
        self.border_top = Line(width=2)
        self.add(self.border_bot)
        self.add(self.border_top)

        self.on_layout(Window.size)

    def reset(self, duration=30.):
        self.duration = duration
        self.color.rgb = (0, 1, 0)
        self.bar.size = (self.end_x - self.start_x, self.end_y - self.start_y)
        self.remaining_time.set_text(str(int(self.duration)))

    def get_width(self, time):
        t = (self.end_x - self.start_x) * (1 - time / self.duration)
        return t

    def on_update(self, time_elapsed):
        if time_elapsed > self.duration:
            return 'end of game'

        if time_elapsed >= 0:
            self.bar.size = (self.get_width(time_elapsed),
                             self.end_y - self.start_y)
            # update remaining time
            self.remaining_time.set_text(str(int(self.duration -
                                                 time_elapsed)))
            # update bar timer color
            self.color.rgb = (min(time_elapsed / self.duration * 2, 1),
                              min(1,
                                  (1 - time_elapsed / self.duration) * 2), 0)

    def on_layout(self, win_size):
        self.start_x = win_size[0] * 0.2
        self.end_x = win_size[0] * .85
        self.start_y = win_size[1] * .2
        self.end_y = win_size[1] * .25

        self.bar.pos = (self.start_x, self.start_y)
        self.border_left.points = [(self.start_x, self.start_y),
                                   (self.start_x, self.end_y)]
        self.border_mid.points = [
            ((self.start_x + self.end_x) / 2, self.start_y),
            ((self.start_x + self.end_x) / 2, self.end_y)
        ]
        self.border_right.points = [(self.end_x, self.start_y),
                                    (self.end_x, self.end_y)]
        self.border_bot.points = [(self.start_x, self.start_y),
                                  (self.end_x, self.start_y)]
        self.border_top.points = [(
            self.start_x,
            self.end_y,
        ), (self.end_x, self.end_y)]
        self.remaining_time.set_cpos((self.end_x + 50, self.start_y))
Ejemplo n.º 15
0
class HelpDisplay(InstructionGroup):
    '''
    Help Overlay.
    |---------------------|
    |mode                 |
    |   (O   O   O   O)   |
    |    O   O   O   O    |
    |    O   O   O   O    |
    |return           help|
    |---------------------|
    '''
    def __init__(self, mode):
        super(HelpDisplay, self).__init__()
        self.mode = mode

        # Start levels
        self.start_box_color = Color(0, 1, 0, 0.2)
        self.start_box = Rectangle(pos=(0.1 * w, 0.7 * h),
                                   size=(0.8 * w, 0.2 * h))
        self.start_text_color = Color(0, 1, 0, 0.8)
        if mode == 'lmode':
            start_text = "Start off with these levels"
            cpos = (0.75 * w, 0.88 * h)
        elif mode == 'gmode':
            start_text = "Complete the learning mode to unlock the first level"
            cpos = (0.6 * w, 0.88 * h)
        self.start_text = CLabelRect(text=start_text,
                                     font_size=font_sz / 4,
                                     font_name=font_name,
                                     cpos=cpos)
        self.add(self.start_box_color)
        self.add(self.start_box)
        self.add(self.start_text_color)
        self.add(self.start_text)

        # Locked levels
        self.locked_box_color = Color(1, 1, 0, 0.2)
        self.locked_box = Rectangle(pos=(0.1 * w, 0.2 * h),
                                    size=(0.8 * w, 0.5 * h))
        self.locked_text_color = Color(1, 1, 0, 0.8)
        if mode == 'lmode':
            locked_text = "Complete the easier levels to unlock new ones"
        elif mode == 'gmode':
            locked_text = "Pass the easier level to unlock the next one"
        self.locked_text = CLabelRect(text=locked_text,
                                      font_size=font_sz / 4,
                                      font_name=font_name,
                                      cpos=(0.65 * w, 0.25 * h))
        self.add(self.locked_box_color)
        self.add(self.locked_box)
        self.add(self.locked_text_color)
        self.add(self.locked_text)

    def on_layout(self, win_size):
        w, h = win_size
        self.start_box.pos = (0.1 * w, 0.7 * h)
        self.start_box.size = (0.8 * w, 0.2 * h)
        if self.mode == 'lmode':
            self.start_text.set_cpos((0.75 * w, 0.88 * h))
        elif self.mode == 'gmode':
            self.start_text.set_cpos((0.6 * w, 0.88 * h))
        self.locked_box.pos = (0.1 * w, 0.2 * h)
        self.locked_box.size = (0.8 * w, 0.5 * h)
        self.locked_text.set_cpos((0.65 * w, 0.25 * h))
Ejemplo n.º 16
0
class PianoPuzzle(Puzzle):
    def __init__(self, prev_room, level=0, on_finished_puzzle=None):
        super().__init__()
        self.door_sources = {
            (4, 9): "./data/Door_up.png",  # UP
            (4, -1): "./data/door_down.png",  # DOWN
            (-1, 4): "./data/door_left.png",  # LEFT
            (9, 4): "./data/Door_right.png",  # RIGHT
        }

        self.prev_room = prev_room
        self.on_finished_puzzle = on_finished_puzzle
        self.animations = AnimGroup()
        self.level = level
        self.notes, self.actual_key = levels[level]
        duration = choice(durations)
        pitch_shift = choice(range(-3, 4))
        self.user_notes = [
            Note(duration,
                 n.get_pitch() + pitch_shift) for n in self.notes
        ]
        render_user_notes = self.level < 2

        self.actual_sound = PuzzleSound(self.notes)
        self.user_sound = PuzzleSound(self.user_notes)
        self.music_bar = MusicBar(self.notes, self.user_notes,
                                  render_user_notes, self.actual_sound)
        self.animations.add(self.music_bar)
        self.add(self.animations)

        self.user_key = "C"

        self.place_objects()

        self.key_label = CLabelRect(
            (Window.width // 30, 23 * Window.height // 32),
            f"Key: {self.user_key}", 34)
        self.add(Color(rgba=(1, 1, 1, 1)))
        self.add(self.key_label)
        self.create_instructions((Window.width, Window.height))
        self.add(self.instructions_text_color)
        self.add(self.instructions_text)
        self.objects = {}

    def play(self, actual=False):
        if actual:
            print("Should be setting the cb_ons")
            self.actual_sound.set_cb_ons([self.music_bar.play])
            self.actual_sound.toggle()
        else:
            self.user_sound.set_cb_ons([self.music_bar.play])
            self.user_sound.toggle()

    def create_instructions(self, win_size):
        self.instructions_text_color = Color(rgba=(1, 1, 1, 1))
        self.instructions_text = CLabelRect(
            (win_size[0] // 8, win_size[1] * 4 / 7),
            "Press + to hear your note sequence.\nPress - to hear the sequence\nyou are trying to match.",
            20,
        )

    def on_pitch_change(self, pitch_index):
        offset = 1 if self.character.direction == Button.RIGHT.value else -1
        for note in self.user_notes:
            pitch = note.get_pitch()
            note.set_note(pitch + offset)
        self.user_sound.set_notes(self.user_notes)

    def on_duration_change(self, dur_index):
        for note in self.user_notes:
            note.set_dur(durations[dur_index])
        self.user_sound.set_notes(self.user_notes)

    def on_key_change(self, key_index):
        self.user_key = key_names[key_index]
        self.update_key()
        self.user_sound.set_notes(self.user_notes)

    def update_key(self):
        key_sig = keys[self.user_key]
        for note in self.user_notes:
            base_letter = note.get_letter()[0]
            letter_before = names[names.index(base_letter) - 1]
            if base_letter not in key_sig["#"]:
                note.remove_sharp()
            if base_letter not in key_sig["b"]:
                note.remove_flat()

            if base_letter in key_sig["#"] and not (note.get_letter()[:-1]
                                                    == base_letter + "#"):
                note.add_sharp()
            if base_letter in key_sig["b"] and not (note.get_letter()[:-1]
                                                    == letter_before + "#"):
                note.add_flat()

    """ Mandatory Puzzle methods """

    def is_game_over(self):
        same_key = self.user_key == self.actual_key
        same_dur = (self.music_bar.user_notes[0].get_dur() ==
                    self.music_bar.actual_notes[0].get_dur())
        same_pitch = (self.music_bar.user_notes[0].get_pitch() ==
                      self.music_bar.actual_notes[0].get_pitch())

        return same_key and same_dur and same_pitch

    def create_objects(self):
        size = (self.grid.tile_side_len, self.grid.tile_side_len)

        # PITCH
        self.objects[(4, 7)] = MovingBlock(
            size,
            self.grid.grid_to_pixel((4, 7)),
            ((1, 7), (8, 7)),
            "./data/pitch_slider.png",
            self.on_pitch_change,
        )

        # RHYTHM
        duration = self.user_notes[0].get_dur()
        self.objects[(durations.index(duration) + 3, 2)] = MovingBlock(
            size,
            self.grid.grid_to_pixel((durations.index(duration) + 3, 2)),
            ((3, 2), (7, 2)),
            "./data/rhythm_slider.png",
            self.on_duration_change,
        )

        # KEY
        self.objects[(key_names.index(self.user_key) + 1, 5)] = MovingBlock(
            size,
            self.grid.grid_to_pixel((key_names.index(self.user_key) + 1, 5)),
            ((1, 5), (7, 5)),
            "./data/key_slider.png",
            self.on_key_change,
        )
        self.objects[(9, 4)] = DoorTile(
            size,
            self.grid.grid_to_pixel((9, 4)),
            self.prev_room,
            source=self.door_sources[(9, 4)],
        )

    def place_objects(self):
        # rhythm_color = Color(rgba=(0, 0.5, 0.5, 1))
        for i in range(len(durations)):  # rhythm
            self.grid.get_tile(
                (i + 3, 2)).set_color(color=Tile.base_color,
                                      source="./data/trackv2.png")

        # pitch_color = Color(rgba=(0.2, 0.5, 1, 1))
        for i in range(7):  # rhythm
            self.grid.get_tile(
                (i + 1, 7)).set_color(color=Tile.base_color,
                                      source="./data/trackv2.png")

        # key_color = Color(rgba=(0.2, 0.5, 0, 1))
        for i in range(len(key_names)):
            self.grid.get_tile(
                (i + 1, 5)).set_color(color=Tile.base_color,
                                      source="./data/trackv2.png")

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

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

        self.add(PopMatrix())

    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].icon_source,
                self.objects[new_location].callback,
            )
            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.objects[obj_loc].on_block_placement(obj_loc)
            return True
        else:
            return False

    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 on_player_input(self, button):
        player_pos = self.character.grid_pos
        if button in [Button.UP, Button.DOWN, Button.LEFT, Button.RIGHT]:
            move_possible = True
            x, y = button.value
            new_pos = (player_pos[0] + x, player_pos[1] + y)
            if new_pos in self.objects:
                if isinstance(self.objects[new_pos], DoorTile):
                    if not isinstance(self.objects[new_pos].other_room,
                                      Puzzle):
                        # instantiate class when we enter the door
                        self.objects[new_pos].other_room = self.objects[
                            new_pos].other_room(self, self.level + 1,
                                                self.on_finished_puzzle)
                    next_room_pos = (8 - new_pos[0] + x, 8 - new_pos[1] + y)
                    self.objects[
                        new_pos].other_room.character.change_direction(
                            button.value)
                    self.objects[new_pos].other_room.character.move_player(
                        next_room_pos)
                    return self.objects[new_pos].other_room

            self.character.change_direction(button.value)

            if new_pos in self.objects:
                if self.objects[new_pos].moveable:
                    move_possible = self.move_block(new_pos, x, y)
            if move_possible:
                self.character.move_player(new_pos)
                player_pos = self.character.grid_pos

        if button == Button.MINUS:
            self.play(actual=True)
        elif button == Button.PLUS:
            self.play(actual=False)

    def on_update(self):
        self.animations.on_update()
        self.actual_sound.on_update()
        self.user_sound.on_update()
        self.key_label.set_text(f"Key: {self.user_key}")
        if not self.game_over and self.is_game_over():
            for pos, obj in self.objects.items():
                if isinstance(obj, MovingBlock):
                    obj.moveable = False
            if self.level == max(levels.keys()):
                self.on_finished_puzzle()
                self.on_game_over()
            else:
                if (-1, 4) not in self.objects:
                    size = (self.grid.tile_side_len, self.grid.tile_side_len)
                    self.objects[(-1, 4)] = DoorTile(
                        size,
                        self.grid.grid_to_pixel((-1, 4)),
                        PianoPuzzle,
                        source=self.door_sources[(-1, 4)],
                    )
                self.add(PushMatrix())
                self.add(Translate(*self.grid.pos))
                self.add(self.objects[(-1, 4)])
                self.add(PopMatrix())

    def on_layout(self, win_size):
        self.remove(self.character)
        self.remove(self.grid)
        self.remove(self.instructions_text_color)
        self.remove(self.instructions_text)
        self.grid.on_layout((win_size[0], 0.75 * win_size[1]))
        for pos, obj in self.objects.items():
            self.remove(obj)

        self.add(self.grid)
        if not self.objects:
            self.create_objects()
        self.place_objects()
        self.character.on_layout(win_size)
        self.add(self.character)

        self.music_bar.on_layout(win_size)
        self.remove(self.key_label)
        self.key_label = CLabelRect(
            (win_size[0] // 30, 23 * win_size[1] // 32),
            f"Key: {self.user_key}", 34)
        self.add(Color(rgba=(1, 1, 1, 1)))
        self.add(self.key_label)

        self.create_instructions(win_size)
        self.add(self.instructions_text_color)
        self.add(self.instructions_text)

        self.create_game_over_text(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.on_game_over()
Ejemplo n.º 17
0
    def __init__(self, norm, pos, callback):
        super(PitchSelect, self).__init__()
        self.norm = norm

        self.selected_key = 0
        self.root_pitch = 60
        self.pitch = 60  # default pitch

        self.green = (144 / 255, 238 / 255, 144 / 255)
        self.white = (239 / 255, 226 / 255, 222 / 255)
        self.black = (.2, .2, .2)
        self.color_names = [
            'red', 'orange', 'yellow', 'green', 'teal', 'blue', 'indigo',
            'violet', 'turquoise', 'pink', 'peach', 'magenta', 'grey'
        ]
        self.callback = callback
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.white_key_size = self.norm.nt((50, 150))
        self.black_key_size = self.norm.nt((40, 100))
        self.key_margin = self.norm.nv(2)  # pixels of space between keys
        self.size = (8 * self.white_key_size[0] + 7 * self.key_margin +
                     2 * self.margin, self.white_key_size[1] +
                     2 * self.margin + self.norm.nv(60))
        self.border_color = Color(238 / 255, 234 / 255, 202 / 255)  # yellow
        self.border = Line(rectangle=(*self.pos, *self.size), width=2)
        self.add(self.border_color)
        self.add(self.border)

        self.keys = [None] * 13
        self.white_keys = [0, 2, 4, 5, 7, 9, 11, 12]
        self.black_keys = [1, 3, 6, 8, 10]
        key_start = (self.pos[0] + self.margin, self.pos[1] + self.margin)
        unit = self.white_key_size[0] + self.key_margin
        black_key_units = [1, 2, 4, 5, 6]
        for i, m in zip(self.white_keys, range(8)):
            self.keys[i] = Rectangle(size=self.white_key_size,
                                     pos=(key_start[0] + m * unit,
                                          key_start[1]))
        for i, m in zip(self.black_keys, black_key_units):
            self.keys[i] = CRectangle(csize=self.black_key_size,
                                      cpos=(key_start[0] + m * unit,
                                            key_start[1] + self.norm.nv(100)))

        self.key_colors = [None] * 13
        for i in self.white_keys:
            self.key_colors[i] = Color(*self.white)
            self.add(self.key_colors[i])
            self.add(self.keys[i])
        for i in self.black_keys:
            self.key_colors[i] = Color(*self.black)
            self.add(self.key_colors[i])
            self.add(self.keys[i])
        self.key_colors[0].rgb = self.green

        self.arrow_size = self.norm.nt((50, 50))
        self.left_pos = (self.pos[0] + self.margin, self.pos[1] +
                         self.size[1] - self.arrow_size[1] - self.norm.nv(10))
        self.left_off = Rectangle(
            pos=self.left_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/left_arrow.png').texture)
        self.left_on = Rectangle(
            pos=self.left_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/left_arrow_clicked.png').texture)
        self.right_pos = (self.pos[0] + self.size[0] - self.margin -
                          self.arrow_size[0], self.pos[1] + self.size[1] -
                          self.arrow_size[1] - self.norm.nv(10))
        self.right_off = Rectangle(
            pos=self.right_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/right_arrow.png').texture)
        self.right_on = Rectangle(
            pos=self.right_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/right_arrow_clicked.png').texture)
        # left_off and right_off are always drawn, but when user mouses over an arrow,
        # left_on and right_on are drawn over left_off and right_off
        self.add(Color(1, 1, 1))
        self.add(self.left_off)
        self.add(self.right_off)

        title_pos = (self.pos[0] + self.size[0] / 2, self.pos[1] +
                     self.size[1] - self.margin - self.norm.nv(20))
        self.title = CLabelRect(cpos=title_pos,
                                text='pitch: {}'.format(
                                    midi_pitch_to_note_name(self.pitch)),
                                font_size='18')
        self.add(Color(1, 1, 1))
        self.add(self.title)
Ejemplo n.º 18
0
class PitchSelect(InstructionGroup):
    """
    Submodule to select the instrument pitch of SoundBlock in the form of a graphical piano.
    """
    def __init__(self, norm, pos, callback):
        super(PitchSelect, self).__init__()
        self.norm = norm

        self.selected_key = 0
        self.root_pitch = 60
        self.pitch = 60  # default pitch

        self.green = (144 / 255, 238 / 255, 144 / 255)
        self.white = (239 / 255, 226 / 255, 222 / 255)
        self.black = (.2, .2, .2)
        self.color_names = [
            'red', 'orange', 'yellow', 'green', 'teal', 'blue', 'indigo',
            'violet', 'turquoise', 'pink', 'peach', 'magenta', 'grey'
        ]
        self.callback = callback
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.white_key_size = self.norm.nt((50, 150))
        self.black_key_size = self.norm.nt((40, 100))
        self.key_margin = self.norm.nv(2)  # pixels of space between keys
        self.size = (8 * self.white_key_size[0] + 7 * self.key_margin +
                     2 * self.margin, self.white_key_size[1] +
                     2 * self.margin + self.norm.nv(60))
        self.border_color = Color(238 / 255, 234 / 255, 202 / 255)  # yellow
        self.border = Line(rectangle=(*self.pos, *self.size), width=2)
        self.add(self.border_color)
        self.add(self.border)

        self.keys = [None] * 13
        self.white_keys = [0, 2, 4, 5, 7, 9, 11, 12]
        self.black_keys = [1, 3, 6, 8, 10]
        key_start = (self.pos[0] + self.margin, self.pos[1] + self.margin)
        unit = self.white_key_size[0] + self.key_margin
        black_key_units = [1, 2, 4, 5, 6]
        for i, m in zip(self.white_keys, range(8)):
            self.keys[i] = Rectangle(size=self.white_key_size,
                                     pos=(key_start[0] + m * unit,
                                          key_start[1]))
        for i, m in zip(self.black_keys, black_key_units):
            self.keys[i] = CRectangle(csize=self.black_key_size,
                                      cpos=(key_start[0] + m * unit,
                                            key_start[1] + self.norm.nv(100)))

        self.key_colors = [None] * 13
        for i in self.white_keys:
            self.key_colors[i] = Color(*self.white)
            self.add(self.key_colors[i])
            self.add(self.keys[i])
        for i in self.black_keys:
            self.key_colors[i] = Color(*self.black)
            self.add(self.key_colors[i])
            self.add(self.keys[i])
        self.key_colors[0].rgb = self.green

        self.arrow_size = self.norm.nt((50, 50))
        self.left_pos = (self.pos[0] + self.margin, self.pos[1] +
                         self.size[1] - self.arrow_size[1] - self.norm.nv(10))
        self.left_off = Rectangle(
            pos=self.left_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/left_arrow.png').texture)
        self.left_on = Rectangle(
            pos=self.left_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/left_arrow_clicked.png').texture)
        self.right_pos = (self.pos[0] + self.size[0] - self.margin -
                          self.arrow_size[0], self.pos[1] + self.size[1] -
                          self.arrow_size[1] - self.norm.nv(10))
        self.right_off = Rectangle(
            pos=self.right_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/right_arrow.png').texture)
        self.right_on = Rectangle(
            pos=self.right_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/right_arrow_clicked.png').texture)
        # left_off and right_off are always drawn, but when user mouses over an arrow,
        # left_on and right_on are drawn over left_off and right_off
        self.add(Color(1, 1, 1))
        self.add(self.left_off)
        self.add(self.right_off)

        title_pos = (self.pos[0] + self.size[0] / 2, self.pos[1] +
                     self.size[1] - self.margin - self.norm.nv(20))
        self.title = CLabelRect(cpos=title_pos,
                                text='pitch: {}'.format(
                                    midi_pitch_to_note_name(self.pitch)),
                                font_size='18')
        self.add(Color(1, 1, 1))
        self.add(self.title)

    def on_touch_down(self, pos):
        for i in self.black_keys:
            if in_bounds(pos, self.keys[i].pos, self.black_key_size):
                self.select(i)
                return  # don't also check for white keys
        for i in self.white_keys:
            if in_bounds(pos, self.keys[i].pos, self.white_key_size):
                self.select(i)

        if in_bounds(pos, self.left_off.pos, self.arrow_size):
            self.left_press()
        if in_bounds(pos, self.right_off.pos, self.arrow_size):
            self.right_press()

    def left_press(self):
        if self.root_pitch - 12 < 24:  # don't go below C1 in pitch
            return

        index = self.pitch - self.root_pitch
        self.root_pitch -= 12
        self.pitch -= 12
        self.title.set_text('pitch: {}'.format(
            midi_pitch_to_note_name(self.pitch)))
        self.callback(self.color_names[index], self.pitch)

    def right_press(self):
        if self.root_pitch + 12 >= 96:  # don't go above C7 in pitch
            return

        index = self.pitch - self.root_pitch
        self.root_pitch += 12
        self.pitch += 12
        self.title.set_text('pitch: {}'.format(
            midi_pitch_to_note_name(self.pitch)))
        self.callback(self.color_names[index], self.pitch)

    def left_anim(self, pos):
        if in_bounds(pos, self.left_off.pos, self.arrow_size):
            if self.left_on not in self.children:
                self.add(self.left_on)
        else:
            if self.left_on in self.children:
                self.remove(self.left_on)

    def right_anim(self, pos):
        if in_bounds(pos, self.right_off.pos, self.arrow_size):
            if self.right_on not in self.children:
                self.add(self.right_on)
        else:
            if self.right_on in self.children:
                self.remove(self.right_on)

    def select(self, key):
        if key == self.selected_key:
            return
        previous_select = self.selected_key
        self.key_colors[key].rgb = self.green
        color = self.white if previous_select in self.white_keys else self.black
        self.key_colors[previous_select].rgb = color
        pitch = self.root_pitch + key
        self.title.set_text('pitch: {}'.format(midi_pitch_to_note_name(pitch)))
        self.pitch = pitch
        self.selected_key = key
        self.callback(self.color_names[key], self.pitch)

    def on_update(self, pos):
        self.left_anim(pos)
        self.right_anim(pos)
Ejemplo n.º 19
0
    def __init__(self, norm, pos, callback):
        super(InstrumentSelect, self).__init__()
        self.norm = norm
        self.selected = 'piano'

        self.callback = callback
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.button_length = self.norm.nv(64)
        self.title_height = self.norm.nv(50)  # height of the word 'instrument'

        self.size = ((5 * self.button_length) + (6 * self.margin),
                     self.button_length + (2 * self.margin) +
                     self.title_height)

        self.white = (239 / 255, 226 / 255, 222 / 255)
        self.red = (201 / 255, 108 / 255, 130 / 255)

        self.border_color = Color(147 / 255, 127 / 255, 159 / 255)  # purple
        self.border = Line(rectangle=(*self.pos, *self.size), width=2)
        self.add(self.border_color)
        self.add(self.border)

        button_size = (self.button_length, self.button_length)
        self.instruments = {
            'piano':
            Rectangle(size=button_size,
                      texture=Image('images/piano.png').texture),
            'violin':
            Rectangle(size=button_size,
                      texture=Image('images/violin.png').texture),
            'trumpet':
            Rectangle(size=button_size,
                      texture=Image('images/trumpet.png').texture),
            'ocarina':
            Rectangle(size=button_size,
                      texture=Image('images/ocarina.png').texture),
            'choir':
            Rectangle(size=button_size,
                      texture=Image('images/choir.png').texture)
        }
        self.instrument_bgs = {
            'piano': Rectangle(size=button_size),
            'violin': Rectangle(size=button_size),
            'trumpet': Rectangle(size=button_size),
            'ocarina': Rectangle(size=button_size),
            'choir': Rectangle(size=button_size)
        }
        self.instrument_colors = {
            'piano': Color(*self.red),  # default selected timbre
            'violin': Color(*self.white),
            'trumpet': Color(*self.white),
            'ocarina': Color(*self.white),
            'choir': Color(*self.white)
        }

        x, y = self.pos

        piano_pos = (x + self.margin, y + self.margin)
        violin_pos = (x + 2 * self.margin + self.button_length,
                      y + self.margin)
        trumpet_pos = (x + 3 * self.margin + 2 * self.button_length,
                       y + self.margin)
        ocarina_pos = (x + 4 * self.margin + 3 * self.button_length,
                       y + self.margin)
        choir_pos = (x + 5 * self.margin + 4 * self.button_length,
                     y + self.margin)

        for instrument, instrument_pos in zip(
            ('piano', 'violin', 'trumpet', 'ocarina', 'choir'),
            (piano_pos, violin_pos, trumpet_pos, ocarina_pos, choir_pos)):
            self.instruments[instrument].pos = self.instrument_bgs[
                instrument].pos = instrument_pos
            self.add(self.instrument_colors[instrument])
            self.add(self.instrument_bgs[instrument])
            self.add(self.instruments[instrument])

        title_pos = (x + self.size[0] / 2, y + self.size[1] -
                     self.title_height / 2 - self.margin / 2)
        self.title = CLabelRect(cpos=title_pos,
                                text='instrument',
                                font_size='18')
        self.add(Color(*self.white))
        self.add(self.title)
Ejemplo n.º 20
0
class BounceSelect(InstructionGroup):
    """
    Submodule to toggle bounces of PhysicsBubble.
    """
    def __init__(self, norm, pos, callback):
        super(BounceSelect, self).__init__()
        self.norm = norm

        self.bounces = 5

        self.callback = callback
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.size = self.norm.nt((210, 130))

        self.border_color = Color(170/255, 220/255, 206/255) # green
        self.border = Line(rectangle=(*self.pos, *self.size), width=2)
        self.add(self.border_color)
        self.add(self.border)

        self.arrow_size = self.norm.nt((50, 50))
        self.left_pos = (
            self.pos[0] + self.margin,
            self.pos[1] + self.margin
        )
        self.left_off = Rectangle(
            pos=self.left_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/left_arrow.png').texture
        )
        self.left_on = Rectangle(
            pos=self.left_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/left_arrow_clicked.png').texture
        )
        self.right_pos = (
            self.pos[0] + self.size[0] - self.margin - self.arrow_size[0],
            self.pos[1] + self.margin
        )
        self.right_off = Rectangle(
            pos=self.right_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/right_arrow.png').texture
        )
        self.right_on = Rectangle(
            pos=self.right_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/right_arrow_clicked.png').texture
        )
        # left_off and right_off are always drawn, but when user mouses over an arrow,
        # left_on and right_on are drawn over left_off and right_off
        self.add(Color(1, 1, 1))
        self.add(self.left_off)
        self.add(self.right_off)

        title_pos = (self.pos[0] + self.size[0]/2, self.pos[1] + self.size[1] - self.norm.nv(30))
        self.title = CLabelRect(cpos=title_pos, text='bounces', font_size='18')
        self.add(self.title)

        bounce_text_pos = (
            self.pos[0] + self.size[0]/2,
            self.pos[1] + self.margin + self.arrow_size[1]/2
        )
        self.bounce_text = CLabelRect(cpos=bounce_text_pos, text=str(self.bounces), font_size='18')
        self.add(self.bounce_text)

    def on_touch_down(self, pos):
        if in_bounds(pos, self.left_off.pos, self.arrow_size):
            self.left_press()
        elif in_bounds(pos, self.right_off.pos, self.arrow_size):
            self.right_press()

    def left_press(self):
        self.bounces -= 1
        self.bounce_text.set_text(str(self.bounces))
        self.callback(self.bounces)

    def right_press(self):
        self.bounces += 1
        self.bounce_text.set_text(str(self.bounces))
        self.callback(self.bounces)

    def left_anim(self, pos):
        if in_bounds(pos, self.left_off.pos, self.arrow_size):
            if self.left_on not in self.children:
                self.add(self.left_on)
        else:
            if self.left_on in self.children:
                self.remove(self.left_on)

    def right_anim(self, pos):
        if in_bounds(pos, self.right_off.pos, self.arrow_size):
            if self.right_on not in self.children:
                self.add(self.right_on)
        else:
            if self.right_on in self.children:
                self.remove(self.right_on)

    def update_bounces(self, bounces):
        self.bounces = bounces
        self.bounce_text.set_text(str(bounces))

    def on_update(self, pos):
        self.left_anim(pos)
        self.right_anim(pos)
Ejemplo n.º 21
0
    def __init__(self, norm, pos, callback):
        super(BounceSelect, self).__init__()
        self.norm = norm

        self.bounces = 5

        self.callback = callback
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.size = self.norm.nt((210, 130))

        self.border_color = Color(170/255, 220/255, 206/255) # green
        self.border = Line(rectangle=(*self.pos, *self.size), width=2)
        self.add(self.border_color)
        self.add(self.border)

        self.arrow_size = self.norm.nt((50, 50))
        self.left_pos = (
            self.pos[0] + self.margin,
            self.pos[1] + self.margin
        )
        self.left_off = Rectangle(
            pos=self.left_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/left_arrow.png').texture
        )
        self.left_on = Rectangle(
            pos=self.left_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/left_arrow_clicked.png').texture
        )
        self.right_pos = (
            self.pos[0] + self.size[0] - self.margin - self.arrow_size[0],
            self.pos[1] + self.margin
        )
        self.right_off = Rectangle(
            pos=self.right_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/right_arrow.png').texture
        )
        self.right_on = Rectangle(
            pos=self.right_pos,
            size=self.arrow_size,
            texture=Image('ui/buttons/right_arrow_clicked.png').texture
        )
        # left_off and right_off are always drawn, but when user mouses over an arrow,
        # left_on and right_on are drawn over left_off and right_off
        self.add(Color(1, 1, 1))
        self.add(self.left_off)
        self.add(self.right_off)

        title_pos = (self.pos[0] + self.size[0]/2, self.pos[1] + self.size[1] - self.norm.nv(30))
        self.title = CLabelRect(cpos=title_pos, text='bounces', font_size='18')
        self.add(self.title)

        bounce_text_pos = (
            self.pos[0] + self.size[0]/2,
            self.pos[1] + self.margin + self.arrow_size[1]/2
        )
        self.bounce_text = CLabelRect(cpos=bounce_text_pos, text=str(self.bounces), font_size='18')
        self.add(self.bounce_text)
Ejemplo n.º 22
0
    def __init__(self, norm, pos, callback):
        super(DrumSelect, self).__init__()
        self.norm = norm
        self.selected = 'snare'

        self.callback = callback
        self.pos = pos
        self.margin = self.norm.nv(20)
        self.button_length = self.norm.nv(64)
        self.title_height = self.norm.nv(50)  # height of the word 'drumset'

        self.size = ((5 * self.button_length) + (6 * self.margin),
                     self.button_length + (2 * self.margin) +
                     self.title_height)

        self.white = (239 / 255, 226 / 255, 222 / 255)
        self.red = (201 / 255, 108 / 255, 130 / 255)

        self.border_color = Color(214 / 255, 152 / 255, 142 / 255)  #orange
        self.border = Line(rectangle=(*self.pos, *self.size), width=2)
        self.add(self.border_color)
        self.add(self.border)

        button_size = (self.button_length, self.button_length)
        self.instruments = {
            'snare':
            Rectangle(size=button_size,
                      texture=Image('images/snare.png').texture),
            'crash':
            Rectangle(size=button_size,
                      texture=Image('images/crash.png').texture),
            'bass':
            Rectangle(size=button_size,
                      texture=Image('images/bass.png').texture),
            'hihat':
            Rectangle(size=button_size,
                      texture=Image('images/hihat.png').texture),
            'triangle':
            Rectangle(size=button_size,
                      texture=Image('images/triangle_instr.png').texture)
        }
        self.instrument_bgs = {
            'snare': Rectangle(size=button_size),
            'crash': Rectangle(size=button_size),
            'bass': Rectangle(size=button_size),
            'hihat': Rectangle(size=button_size),
            'triangle': Rectangle(size=button_size)
        }
        self.instrument_colors = {
            'snare': Color(*self.red),  # default selected timbre
            'crash': Color(*self.white),
            'bass': Color(*self.white),
            'hihat': Color(*self.white),
            'triangle': Color(*self.white)
        }

        x, y = self.pos

        snare_pos = (x + self.margin, y + self.margin)
        crash_pos = (x + 2 * self.margin + self.button_length, y + self.margin)
        bass_pos = (x + 3 * self.margin + 2 * self.button_length,
                    y + self.margin)
        hihat_pos = (x + 4 * self.margin + 3 * self.button_length,
                     y + self.margin)
        triangle_pos = (x + 5 * self.margin + 4 * self.button_length,
                        y + self.margin)

        for instrument, instrument_pos in zip(
            ('snare', 'crash', 'bass', 'hihat', 'triangle'),
            (snare_pos, crash_pos, bass_pos, hihat_pos, triangle_pos)):
            self.instruments[instrument].pos = self.instrument_bgs[
                instrument].pos = instrument_pos
            self.add(self.instrument_colors[instrument])
            self.add(self.instrument_bgs[instrument])
            self.add(self.instruments[instrument])

        title_pos = (x + self.size[0] / 2, y + self.size[1] -
                     self.title_height / 2 - self.margin / 2)
        self.title = CLabelRect(cpos=title_pos, text='drumkit', font_size='18')
        self.add(Color(*self.white))
        self.add(self.title)
Ejemplo n.º 23
0
class PhysicsBubble(InstructionGroup):
    """
    This module is a drag-and-release physics-based bubble that plays a sound upon colliding with
    another collidable object, including the sandbox edges.
    """
    name = 'PhysicsBubble'

    def __init__(self,
                 norm,
                 sandbox,
                 pos,
                 vel,
                 pitch,
                 timbre,
                 color,
                 bounces,
                 handler,
                 gravity=False,
                 callback=None):
        """
        :param norm: normalizer
        :param sandbox: client's sandbox
        :param pos: initial position
        :param vel: initial velocity
        :param pitch: MIDI pitch value, where 60 is middle C
        :param timbre: type of waveform, e.g. 'sine' or 'sawtooth'
        :param color: 3-tuple of RGB color
        :param bounces: number of times the bubble bounces before fading away
        :param gravity: whether or not the bubble is subjected to downwards gravity
        :param callback: the sound function that is called when the bubble bounces
        """
        super(PhysicsBubble, self).__init__()

        self.norm = norm
        self.sandbox = sandbox

        self.r = self.norm.nv(40)
        self.pos = np.array(pos, dtype=np.float)
        self.vel = 2 * np.array(vel, dtype=np.float)

        self.pitch = pitch
        self.timbre = timbre
        self.color = Color(*color)
        self.text_color = Color(0, 0, 0)
        self.bounces = bounces
        self.gravity = gravity
        self.callback = callback
        self.handler = handler

        self.text = CLabelRect(cpos=pos, text=str(self.bounces))
        self.bubble = self.timbre_to_shape(self.timbre, pos)

        self.add(self.color)
        self.add(self.bubble)
        self.add(self.text_color)
        self.add(self.text)

        # have the bubble fade away when self.bounces = 0
        self.fade_anim = KFAnim((0, 1), (0.25, 0))
        self.time = 0

        self.on_update(0)

    def timbre_to_shape(self, timbre, pos):
        if timbre == 'sine':
            return CEllipse(cpos=pos, size=self.norm.nt((80, 80)), segments=20)
        elif timbre == 'triangle':
            return CEllipse(cpos=pos, size=self.norm.nt((90, 90)), segments=3)
        elif timbre == 'square':
            return CRectangle(cpos=pos, size=self.norm.nt((80, 80)))
        elif timbre == 'sawtooth':
            # square rotated 45 degrees
            return CEllipse(cpos=pos, size=self.norm.nt((90, 90)), segments=4)

    def on_update(self, dt):
        if self.gravity:
            self.vel += downwards_gravity * dt
            self.pos += self.vel * dt
        else:
            self.pos += self.vel * dt

        if self.bounces > 0:
            if self.check_for_block_collisions() and self.callback is not None:
                self.callback(self.pitch, self.timbre)
            if self.check_for_collisions() and self.callback is not None:
                self.callback(self.pitch, self.timbre)
        # second condition checks if bubble hasn't been moving but there's no gravity --
        # since bubble would be on the screen forever without making sound, fade it away
        if self.bounces <= 0 or (not self.gravity
                                 and np.linalg.norm(self.vel) == 0):
            self.color.a = self.fade_anim.eval(self.time)
            self.time += dt

        self.bubble.set_cpos(self.pos)
        self.text.set_cpos(self.pos)

        return self.fade_anim.is_active(self.time)

    def check_for_collisions(self):
        bottom = self.sandbox.pos[1]
        top = self.sandbox.pos[1] + self.sandbox.height
        left = self.sandbox.pos[0]
        right = self.sandbox.pos[0] + self.sandbox.width

        # collision with bottom
        if self.pos[1] - self.r < bottom:
            self.vel[1] = -self.vel[
                1] * damping_factor if self.gravity else -self.vel[1]
            self.pos[1] = bottom + self.r
            self.bounces -= 1
            self.text.set_text(str(self.bounces))
            return True

        # collision with top
        if self.pos[1] + self.r > top:
            self.vel[1] = -self.vel[1]
            self.pos[1] = top - self.r
            self.bounces -= 1
            self.text.set_text(str(self.bounces))
            return True

        # collision with left
        if self.pos[0] - self.r < left:
            self.vel[0] = -self.vel[0]
            self.pos[0] = left + self.r
            self.bounces -= 1
            self.text.set_text(str(self.bounces))
            return True

        # collision with right
        if self.pos[0] + self.r > right:
            self.vel[0] = -self.vel[0]
            self.pos[0] = right - self.r
            self.bounces -= 1
            self.text.set_text(str(self.bounces))
            return True

    def check_for_block_collisions(self):
        """Check to see if this bubble collided with any SoundBlocks."""
        collide = False
        blocks = self.handler.block_handler.blocks.objects
        for block in blocks:
            left_x = block.pos[0]
            right_x = block.pos[0] + block.size[0]
            bottom_y = block.pos[1]
            top_y = block.pos[1] + block.size[1]

            # going left
            if self.pos[0] + self.r >= left_x and \
               self.pos[0]+self.r <= right_x and \
               self.pos[1] >= bottom_y and self.pos[1] <= top_y:

                self.vel[0] *= -1
                self.pos[0] = left_x - self.r
                self.bounces -= 1
                self.text.set_text(str(self.bounces))
                block.flash()

                collide = True

            # going right
            if self.pos[0] - self.r <= right_x and \
               self.pos[0]-self.r >= left_x and \
               self.pos[1] >= bottom_y and self.pos[1] <= top_y:

                self.vel[0] *= -1
                self.pos[0] = right_x + self.r
                self.bounces -= 1
                self.text.set_text(str(self.bounces))
                block.flash()

                collide = True

            # going up
            if self.pos[1] + self.r >= bottom_y and \
               self.pos[1] + self.r <= top_y and \
               self.pos[0] >= left_x and self.pos[0] <= right_x:

                self.vel[1] *= -1
                self.pos[1] = bottom_y - self.r
                self.bounces -= 1
                self.text.set_text(str(self.bounces))
                block.flash()

                collide = True

            # going down
            if self.pos[1] - self.r <= top_y and \
               self.pos[1]-self.r >= bottom_y and \
               self.pos[0] >= left_x and self.pos[0] <= right_x:

                self.vel[1] *= -1
                self.pos[1] = top_y + self.r
                self.bounces -= 1
                self.text.set_text(str(self.bounces))
                block.flash()

                collide = True

        return collide