Ejemplo n.º 1
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.º 2
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.º 3
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