Ejemplo n.º 1
0
    def __init__(self):
        super(CrossBar, self).__init__()

        w = Window.width
        h = Window.height

        leftX = 0
        bottomY = 0

        self.shape = Line(points=[0,0,w,0], width=2)

        self.color = Color((1, 1, 1), a=1)

        #speed of the song is 104/60 = 1.733333 beats per second.
        #lets say that the height of a quarter note (one beat) is 100.
        #Then I would want that square to travel 2*100 =200 units per second.
        beatsInHeight = h/200
        secondsToTravel = beatsInHeight / 1.7333333
        #print("seconds to travel: ",secondsToTravel)

        self.yPos_anim = KFAnim((0, bottomY), (secondsToTravel, h))
        #self.alpha_anim = KFAnim((0, 1), (1+decay, 0))

        self.add(self.color)
        self.add(self.shape)

        self.time = 0
        self.on_update(0)
Ejemplo n.º 2
0
class SoundBlock(InstructionGroup):
    """
    This module is a rectangular, static block that plays a sound when either someone clicks it,
    or another sound module (e.g. PhysicsBubble) collides with it.
    """
    name = 'SoundBlock'

    def __init__(self,
                 norm,
                 sandbox,
                 pos,
                 size,
                 channel,
                 pitch,
                 color,
                 handler,
                 callback=None):
        super(SoundBlock, self).__init__()
        self.norm = norm
        self.sandbox = sandbox
        self.pos = np.array(pos, dtype=np.float)
        self.size = np.array(size, dtype=np.float)
        self.handler = handler
        self.callback = callback

        self.rect = Rectangle(
            pos=self.pos,
            size=self.size,
        )
        self.white = (239 / 255, 226 / 255, 222 / 255)
        self.color = Color(*self.white)
        self.add(self.color)
        self.add(self.rect)

        self.channel = channel
        self.pitch = pitch
        self.hit_color = color

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

        self.hit = False
        self.flash_anim = KFAnim((0, *self.hit_color), (.5, *self.white))

        self.time = 0

    def flash(self):
        self.callback(self.channel, self.pitch)
        self.time = 0
        self.hit = True

    def on_update(self, dt):
        if self.hit:
            rgb = self.flash_anim.eval(self.time)
            self.color.rgb = rgb
            self.time += dt
            if not self.flash_anim.is_active(self.time):
                self.hit = False
                self.time = 0
Ejemplo n.º 3
0
class FadingMusicNote(InstructionGroup):
    def __init__(self, pos=(0, 0)):
        super(FadingMusicNote, self).__init__()
        self.body = Rectangle(
            pos=pos,
            size=(50, 50),
            texture=Img('./data/scene/eightnote.png').texture)
        self.pop_anim = KFAnim((0, self.body.size[0]), (.5, self.body.size[0]),
                               (1.0, 0))
        mag = random.uniform(20, 30)
        theta = random.uniform(0, 2 * np.pi)
        dx, dy = mag * np.cos(theta), mag * np.sin(theta)
        self.pos_anim = KFAnim((0, pos[0], pos[1]),
                               (.5, pos[0] + dx, pos[1] + dy))
        self.add(self.body)
        self.time = 0
        self.active = True
        self.on_update(0)

    def on_update(self, dt):
        # the disappearing animation just reduces the size
        new_size = self.pop_anim.eval(self.time)
        new_pos = self.pos_anim.eval(self.time)
        self.body.size = (new_size, new_size)
        self.body.pos = new_pos
        self.time += dt
        return self.pop_anim.is_active(self.time)

    def start_anim(self):
        self.active = True
Ejemplo n.º 4
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.º 5
0
    def __init__(self, time, time_quant, seconds, lane_ratio):
        super(Gem, self).__init__(time, time_quant, seconds)
        # self.color_stages = ((.8, .3, .4), (.85, .75, .1), (.2, .8, .4))
        self.color = Color(0.3 + 0.7 * lane_ratio, 0.8, 1, mode='hsv').rgb
        self.sprite = GemSprite(self.color)
        self.posistion = (100, 100)
        self.add_graphic(self.sprite)
        self.y = 0

        self.total_height = None

        # For fading
        self.last_time = time
        self.anim = KFAnim((0, 0.8), (seconds, .3))
Ejemplo n.º 6
0
    def render_elements(self):
        self.height = self.win_size[1] * 3 / 4
        self.staff_lines_height = (self.win_size[1] / 4) * (2 / 3) / 5
        self.middle_c_h = (self.win_size[1] / 4) / 6
        self.staff_h = self.middle_c_h + self.staff_lines_height

        self.notes_start = self.win_size[0] / 10
        self.notes_width = self.win_size[0] - self.notes_start

        t = self.tempo_map.tick_to_time(
            sum(note.get_dur() for note in self.actual_notes))
        # t = (sum(note.get_dur() for note in self.actual_notes) + 480) / 960
        self.now_bar = Line(points=(self.notes_start, self.height,
                                    self.notes_start, self.win_size[1]))
        self.now_bar_pos = KFAnim((0, self.notes_start), (t, self.win_size[0]))
        self.border = Line(points=(0, self.height, self.win_size[0],
                                   self.height))

        # loop thru all notes and map positions -only draw lines for certain ones

        self.staff_lines = []
        self.staff_mappings = dict()

        for i in range(len(all_notes)):
            height = self.height + self.middle_c_h + self.staff_lines_height * i / 2.0
            if all_notes[i] in notes_w_staff_lines:

                self.staff_lines.append(
                    Line(points=(0, height, self.win_size[0], height)))
            self.staff_mappings[
                all_notes[i]] = height - self.staff_lines_height / 2.0
        if self.render_user_notes:
            self.place_notes(actual=True)
        self.place_notes(actual=False)
        self.add(Color(a=1))

        self.add(self.now_bar)
        self.add(self.border)
        for line in self.staff_lines:
            self.add(line)
        self.clef = Rectangle(
            source="./data/treble_clef_white.png",
            pos=(self.win_size[0] / 50, self.height + self.middle_c_h),
            size=(self.win_size[0] / 22, self.height / 4.5),
        )
        self.add(self.clef)
Ejemplo n.º 7
0
 def __init__(self, pos=(0, 0)):
     super(FadingMusicNote, self).__init__()
     self.body = Rectangle(
         pos=pos,
         size=(50, 50),
         texture=Img('./data/scene/eightnote.png').texture)
     self.pop_anim = KFAnim((0, self.body.size[0]), (.5, self.body.size[0]),
                            (1.0, 0))
     mag = random.uniform(20, 30)
     theta = random.uniform(0, 2 * np.pi)
     dx, dy = mag * np.cos(theta), mag * np.sin(theta)
     self.pos_anim = KFAnim((0, pos[0], pos[1]),
                            (.5, pos[0] + dx, pos[1] + dy))
     self.add(self.body)
     self.time = 0
     self.active = True
     self.on_update(0)
Ejemplo n.º 8
0
class NoteShape(InstructionGroup):
    def __init__(self, topLeftPos, height, width):
        super(NoteShape, self).__init__()

        w = Window.width
        h = Window.height

        self.height = height
        self.width = width


        leftX = topLeftPos[0]
        topY = topLeftPos[1]
        bottomY = topLeftPos[1] - height

        self.shape = Rectangle(pos = (leftX, bottomY), size=(width, height))

        colorChange = leftX / w
        hue = .6 + .5 * (colorChange) 
        #hue = .76
        self.color = Color(hsv=(hue, 1, 1), a=1)

        #speed of the song is 2 beats per second.
        #lets say that the height of a quarter note (one beat) is 150.
        #Then I would want that square to travel 2*100 =200 units per second.
        beatsInHeight = h/200
        secondsToTravel = beatsInHeight / 1.7333333
        #print("seconds to travel: ",secondsToTravel)

        self.yPos_anim = KFAnim((0, topY), (secondsToTravel, h))
        #self.alpha_anim = KFAnim((0, 1), (1+decay, 0))

        self.add(self.color)
        self.add(self.shape)

        self.time = 0
        self.on_update(0)

    
    def on_update(self, dt):

        w = Window.width
        h = Window.height

        leftPos = self.shape.pos[0]         
        
        yPos = self.yPos_anim.eval(self.time)
        
        self.shape.pos = (leftPos, yPos-self.height)

        #alpha = self.alpha_anim.eval(self.time)
        #self.color.a = alpha

        self.time += dt

        return yPos < h
Ejemplo n.º 9
0
    def __init__(self,
                 norm,
                 sandbox,
                 pos,
                 size,
                 channel,
                 pitch,
                 color,
                 handler,
                 callback=None):
        super(SoundBlock, self).__init__()
        self.norm = norm
        self.sandbox = sandbox
        self.pos = np.array(pos, dtype=np.float)
        self.size = np.array(size, dtype=np.float)
        self.handler = handler
        self.callback = callback

        self.rect = Rectangle(
            pos=self.pos,
            size=self.size,
        )
        self.white = (239 / 255, 226 / 255, 222 / 255)
        self.color = Color(*self.white)
        self.add(self.color)
        self.add(self.rect)

        self.channel = channel
        self.pitch = pitch
        self.hit_color = color

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

        self.hit = False
        self.flash_anim = KFAnim((0, *self.hit_color), (.5, *self.white))

        self.time = 0
Ejemplo n.º 10
0
class Gem(VirtualGem):
    def __init__(self, time, time_quant, seconds, lane_ratio):
        super(Gem, self).__init__(time, time_quant, seconds)
        # self.color_stages = ((.8, .3, .4), (.85, .75, .1), (.2, .8, .4))
        self.color = Color(0.3 + 0.7 * lane_ratio, 0.8, 1, mode='hsv').rgb
        self.sprite = GemSprite(self.color)
        self.posistion = (100, 100)
        self.add_graphic(self.sprite)
        self.y = 0

        self.total_height = None

        # For fading
        self.last_time = time
        self.anim = KFAnim((0, 0.8), (seconds, .3))

    def set_pos(self):
        self.y = self.lane.track.time2y(self.time)
        self.position = (0, self.y - self.sprite.size[1])

    def on_release(self, time):
        super(Gem, self).on_release(time)
        # Draw gradient gem
        self.remove_graphic(self.sprite)
        self.sprite = GradientGemSprite(self.sprite.size, self.color,
                                        self.sprite.color.rgb)
        self.add_graphic(self.sprite)

    # Function called to render gem based on it's
    # self.time and self.length parameters.
    def set_pos_and_size(self):
        top_y = self.lane.track.time2y(self.time)
        bot_y = self.lane.track.time2y(self.time + self.length)
        size_x, size_y = self.sprite.texture.size
        self.sprite.texture.size = (size_x, top_y - bot_y)
        self.position = (0, bot_y)

    def get_height(self):
        return self.sprite.texture.size[1]

    def update_length(self, y):
        size_x, size_y = self.sprite.texture.size
        self.sprite.texture.size = (size_x, self.y - y)
        self.position.y = y

    def update_remove_length(self, y):
        if self.total_height is None:
            # Rememeber height before shrinking
            self.total_height = self.get_height()
        size_x, size_y = self.sprite.texture.size
        self.sprite.texture.size = (size_x, self.total_height - self.y + y)

    def on_update(self):
        # Fade Color
        now = self.lane.now
        dt = now - self.last_time % self.seconds
        if now < self.last_time % self.seconds:
            # New frame
            dt += self.seconds
        s = self.anim.eval(self.last_time - self.time)
        self.sprite.color.v = s
        self.last_time += dt

    def __str__(self):
        return '<GEM %0.2f : %0.2f>' % (self.time, self.length)
Ejemplo n.º 11
0
class MusicBar(InstructionGroup):
    def __init__(self, actual_notes, user_notes, render_user_notes, sound):
        super().__init__()
        self.win_size = (Window.width, Window.height)
        self.actual_notes = actual_notes
        self.user_notes = user_notes
        self.render_user_notes = render_user_notes
        self.tempo_map = sound.tempo_map

        self.render_elements()

        self.time = 0
        self.now_bar_moving = False

    def render_elements(self):
        self.height = self.win_size[1] * 3 / 4
        self.staff_lines_height = (self.win_size[1] / 4) * (2 / 3) / 5
        self.middle_c_h = (self.win_size[1] / 4) / 6
        self.staff_h = self.middle_c_h + self.staff_lines_height

        self.notes_start = self.win_size[0] / 10
        self.notes_width = self.win_size[0] - self.notes_start

        t = self.tempo_map.tick_to_time(
            sum(note.get_dur() for note in self.actual_notes))
        # t = (sum(note.get_dur() for note in self.actual_notes) + 480) / 960
        self.now_bar = Line(points=(self.notes_start, self.height,
                                    self.notes_start, self.win_size[1]))
        self.now_bar_pos = KFAnim((0, self.notes_start), (t, self.win_size[0]))
        self.border = Line(points=(0, self.height, self.win_size[0],
                                   self.height))

        # loop thru all notes and map positions -only draw lines for certain ones

        self.staff_lines = []
        self.staff_mappings = dict()

        for i in range(len(all_notes)):
            height = self.height + self.middle_c_h + self.staff_lines_height * i / 2.0
            if all_notes[i] in notes_w_staff_lines:

                self.staff_lines.append(
                    Line(points=(0, height, self.win_size[0], height)))
            self.staff_mappings[
                all_notes[i]] = height - self.staff_lines_height / 2.0
        if self.render_user_notes:
            self.place_notes(actual=True)
        self.place_notes(actual=False)
        self.add(Color(a=1))

        self.add(self.now_bar)
        self.add(self.border)
        for line in self.staff_lines:
            self.add(line)
        self.clef = Rectangle(
            source="./data/treble_clef_white.png",
            pos=(self.win_size[0] / 50, self.height + self.middle_c_h),
            size=(self.win_size[0] / 22, self.height / 4.5),
        )
        self.add(self.clef)

    def play(self):
        self.now_bar_moving = True

    def place_notes(self, actual=True):
        notes_to_place = self.actual_notes if actual else self.user_notes
        if actual:
            self.add(Color(a=0.5))
        else:
            self.user_note_instructions = set()

        num_measures = int(
            sum(note.get_dur() / 480 / 4 for note in self.actual_notes))
        note_index = 0
        # place all measure lines
        x_start = self.notes_start
        for i in range(num_measures):
            # measure = []
            measure_beats = 0
            x_end = self.notes_start + self.notes_width * (i +
                                                           1) / num_measures
            while measure_beats < 1 and note_index < len(notes_to_place):
                duration = notes_to_place[note_index].get_dur() / 480 / 4
                # pitch = notes_to_place[note_index].get_pitch()
                n_val = notes_to_place[note_index].get_letter()
                if len(n_val) == 3:
                    n_val = n_val[0::2]
                height = (self.staff_mappings[n_val]
                          if n_val in self.staff_mappings else self.height)
                x_pos = x_start + (measure_beats) * (x_end - x_start)
                if n_val == "C4":  # ledger line
                    ledger_width = 15
                    ledger_height = height + self.staff_lines_height / 2.0
                    ledger = Line(points=(
                        x_pos - ledger_width,
                        ledger_height,
                        x_pos + self.staff_lines_height + ledger_width,
                        ledger_height,
                    ))
                    self.add(ledger)
                note_obj = NoteIcon(self.staff_lines_height, x_pos, height)
                self.add(note_obj)
                if not actual:
                    self.user_note_instructions.add(note_obj)
                    if n_val == "C4":
                        self.user_note_instructions.add(ledger)
                measure_beats += duration
                note_index += 1
            self.add(
                Line(points=(
                    x_end,
                    self.height + self.staff_h,
                    x_end,
                    self.win_size[1] - self.middle_c_h,
                )))
            x_start = x_end

    def on_update(self, dt):
        if self.now_bar_moving:
            pos = self.now_bar_pos.eval(self.time)
            self.now_bar.points = (pos, self.height, pos, self.win_size[1])
            self.time += dt
            if pos == self.win_size[0]:
                self.time = 0
                self.now_bar_moving = False
                pos = self.now_bar_pos.eval(self.time)
                self.now_bar.points = (pos, self.height, pos, self.win_size[1])
        for ins in self.user_note_instructions:
            self.remove(ins)
        self.place_notes(actual=False)

        return

    def on_layout(self, win_size):
        self.clear()

        self.win_size = win_size
        self.render_elements()
Ejemplo n.º 12
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