예제 #1
0
 def draw(self, canvas, time_dict: dict):
     time_dict['bars'] -= self.__metadata['empty_bars']
     if time_dict['bars'] < 0:
         font = pygame.font.Font('Assets/Fonts/Patapon.ttf', 40)
         center = [a / 2 for a in canvas.get_size()]
         ready_text = font.render('Get ready', 1, (255,) * 3)
         ready_sprite = Sprite(ready_text)
         ready_sprite.transform(center=center,
                                opacity=1 - (time_dict['beats'] + time_dict['delta'] + 0.5) / time_dict[
                                    'beat_size'] if time_dict['bars'] == -1 else 1)
         ready_sprite.draw(canvas)
     self.game.draw(time_dict, canvas)
예제 #2
0
class StubMinigame(Engine.MiniGame.AbstractMiniGame):
    def configure(self, config_json):
        if 'sprite' in config_json:
            self.spr = Sprite(config_json['sprite'])
            self.spr.transform(center=(400, 300))

    def reset(self):
        pass

    def __init__(self,
                 life_time,
                 sprite=Sprite('Assets/Artwork/bullet.png'),
                 base_color=(0, 0, 0)):
        super().__init__(life_time)
        self.spr: Sprite = sprite
        sprite.transform(center=(400, 300))
        self.color = None
        self.base_color = base_color
        self.bp = pygame.mixer.Sound('Assets/Sound/wrong.wav')

    def update(self, time: dict):
        self.color = (255 - 2 * abs(time['delta']) *
                      (255 - self.base_color[0]), 255 -
                      2 * abs(time['delta']) * (255 - self.base_color[1]),
                      255 - 2 * abs(time['delta']) *
                      (255 - self.base_color[2]))
        self.spr.transform(opacity=(2 * (0.5 - abs(time['delta'])))**2.1,
                           scale=1 + (0.5 - abs(time['delta']))**2.1 *
                           (0.5 if time['beats'] == 0 else 0.2))
        return {'delta_health': 0, 'delta_score': 0}

    def draw(self, time: dict, canvas):
        self.spr.draw(canvas)

    def handle(self, event):
        return {
            'delta_health': -10,
            'delta_score': (1 - (2 * abs(event['time']['delta']))**0.3) * 30
        }
예제 #3
0
class GameUI(AbstractUI):
    def update(self):
        self.info = self.runtime.update()

    def __init__(self, canvas, runtime: LevelRuntime = None):
        self.views = None
        super().__init__(canvas)
        self.runtime = runtime
        self.control_keys = [pygame.K_p, pygame.K_ESCAPE, pygame.K_k, pygame.K_m]
        self.info = None
        self.settings_popup = None
        self.display_controls = True

        heart_image = pygame.image.load('Assets/Artwork/UI/Game/heart.png')
        heart_image = pygame.transform.scale(heart_image, (int(RADIUS * 2 * 0.8),) * 2)
        self.heart_sprite = Sprite(heart_image)
        self.heart_sprite.transform(center=(canvas.get_size()[0] - MARGIN - RADIUS, MARGIN + RADIUS))

    def key_press(self, event):
        if self.info['over']:
            if event['key'] == pygame.K_ESCAPE:
                self.runtime.pause()
                return self.views['menu']
            else:
                return

        if not (event['key'] in self.control_keys) and (self.runtime is not None) and not self.info['pause']:
            self.runtime.key_pressed(event)
            return

        # Toggle pause
        if event['key'] == pygame.K_p:
            if self.info['pause']:
                if not self.settings_popup:
                    self.runtime.play()
            else:
                self.runtime.pause()

        if event['key'] == pygame.K_ESCAPE:
            self.runtime.pause()
            return self.views['menu']

        if event['key'] == pygame.K_k:
            if self.info['pause']:
                if self.settings_popup:
                    self.settings_popup = None
                    self.runtime.play()
                else:
                    self.settings_popup = SettingsPopup(self.canvas)
            if not self.info['pause']:
                self.runtime.pause()
                self.settings_popup = SettingsPopup(self.canvas)

        if event['key'] == pygame.K_m:
            self.display_controls = not self.display_controls

        if self.settings_popup:
            self.settings_popup.key_press(event)

    def draw_controls(self):
        size = self.canvas.get_size()

        # Количество очков в левом верхнем углу
        font = pygame.font.Font('Assets/Fonts/Patapon.ttf', MARGIN)
        sc_text = font.render('Score: {}'.format(self.info['stats']['global_score']), 1, WHITE)
        l_sc_text = font.render('Current mini-game score: {}'.format(self.info['stats']['current_score']), 1, WHITE)
        self.canvas.blit(sc_text, (0, 0))
        self.canvas.blit(l_sc_text, (0, 40))

        # Индикатор здоровья в правом верхнем углу
        pygame.draw.ellipse(self.canvas, BLACK, [size[0] - MARGIN - RADIUS * 2, MARGIN, RADIUS * 2, RADIUS * 2])

        if self.info['over']:  # Полоса здоровья становится белым кругом в конце игры
            pygame.draw.ellipse(self.canvas, WHITE, [size[0] - MARGIN - RADIUS * 2, MARGIN, RADIUS * 2, RADIUS * 2], 5)
        else:  # А пока она красная
            pygame.draw.arc(self.canvas, RED, [size[0] - MARGIN - RADIUS * 2, MARGIN, RADIUS * 2, RADIUS * 2], pi / 2,
                            pi / 2 + 2 * pi * self.info['stats']['health_info']['health'] /
                            self.info['stats']['health_info']['max'], 5)

        scale_arg = self.runtime.get_time_dict()['delta']  # Рисуем пульсирующее сердечко
        if not abs(scale_arg) > 0.5 * HEART_PEAK_T:
            scale_factor = ((cos(2 * pi * scale_arg / HEART_PEAK_T) * 0.5 + 1) * (1 - HEART_MIN_R) + HEART_MIN_R)
        else:
            scale_factor = HEART_MIN_R
        if self.info['over']:
            scale_factor = HEART_MIN_R
            if self.info['stats']['health_info']['health'] == 0:  # Здоровье на нуле - сердечко разбито :(
                heart_image = pygame.image.load('Assets/Artwork/UI/Game/heart_broken.png')
                heart_image = pygame.transform.scale(heart_image, (int(RADIUS * 2 * 0.8),) * 2)
                self.heart_sprite = Sprite(heart_image)
                self.heart_sprite.transform(center=(size[0] - MARGIN - RADIUS, MARGIN + RADIUS))

        self.heart_sprite.transform(scale=scale_factor)
        self.heart_sprite.draw(self.canvas)

        # Индикатор прогресса внизу экрана
        pointer_coords = MARGIN + (size[0] - MARGIN * 2) * self.info['stats']['progress'], size[1] - MARGIN
        pygame.draw.polygon(self.canvas, GREEN,
                            [(pointer_coords[0], pointer_coords[1] - 5),
                             (pointer_coords[0] - 20, pointer_coords[1] - 30),
                             (pointer_coords[0] + 20, pointer_coords[1] - 30)])
        pygame.draw.line(self.canvas, WHITE, (MARGIN, size[1] - MARGIN), (size[0] - MARGIN, size[1] - MARGIN), 5)
        waypts = self.runtime.level.get_waypoints()
        for wp in waypts:  # Нарисуем точки резкого изменения мини-игр
            pygame.draw.line(self.canvas, WHITE, [MARGIN + (size[0] - MARGIN * 2) * wp, size[1] - MARGIN + 20],
                             [MARGIN + (size[0] - 80) * wp, size[1] - MARGIN], 5)

    def draw_widgets(self):
        center = [a / 2 for a in self.canvas.get_size()]

        if not self.info['over']:
            self.runtime.draw(self.canvas)

        if self.display_controls:
            self.draw_controls()

        font = pygame.font.Font('Assets/Fonts/Patapon.ttf', 40)

        if self.info['over']:  # Нарисовать экран конца игры
            over_text = font.render('Game over. Press Esc to exit.', 1, WHITE)
            self.canvas.blit(over_text, over_text.get_rect(center=center))
        elif self.runtime.paused:
            if self.settings_popup:  # Всплывающее меню настроек
                self.settings_popup.draw_widgets()
            else:  # Игра стоит на паузе
                pause_text = font.render('Paused', 1, WHITE)
                info_text = font.render('K - settings, M - toggle show controls, Esc - quit', 1, WHITE)
                self.canvas.blit(pause_text, pause_text.get_rect(center=center))
                self.canvas.blit(info_text, (center[0] - info_text.get_size()[0] / 2, center[1] + 40))
예제 #4
0
class LetaMiniGame(AbstractMiniGame):
    def configure(self, config_json):
        pass  # TODO

    def reset(self):
        pass  # TODO

    def __init__(self, life_time, letters=None):
        super().__init__(life_time)
        self.letters = letters

        if letters is None:
            self.letters = self.create_letters(life_time)
        self.len_letters = len(self.letters)

        # whether received data is correct for game logic and fixing it
        if len(self.letters) > (life_time - 1) // 2:
            self.letters = self.letters[:(life_time - 1) // 2]
            self.len_letters = len(self.letters)
        elif self.len_letters < (life_time - 1) // 2:
            self.letters.append(
                self.create_letters((life_time - 1) // 2 - self.len_letters))
            self.len_letters = len(self.letters)
        for i in range(self.len_letters):
            if len(self.letters[i]) > beats_number:
                self.letters[i] = self.letters[i][:beats_number]
            elif len(self.letters[i]) < beats_number:
                for j in range(beats_number - len(self.letters[i])):
                    self.letters[i].append(choice(characters))

        self.counter = 0
        self.letter_counter = 0
        self.background = Sprite(
            pygame.image.load(path.join(img_dir, 'orange.jpg')).convert())
        self.height, self.width = 0, 0
        self.got_or_not = [[0] * beats_number for i in range(self.len_letters)]
        self.font_size = 0

    def update(self, time: dict):
        if time['bars'] > self.counter:
            self.counter += 1
        if time['beats'] > self.letter_counter or time['beats'] == 0:
            self.letter_counter = time['beats']

        delta_health = 0
        delta_score = 0
        if time['beat_type'] in (1, 2) and self.len_letters < self.counter and \
                self.got_or_not[(time['bars'] - 1) % self.len_letters][time['beats']] == 0:
            self.got_or_not[(time['bars'] - 1) %
                            self.len_letters][time['beats']] = -1
            delta_health = -5

        return {'delta_health': delta_health, 'delta_score': delta_score}

    def draw(self, time: dict, canvas):
        # getting proper sizes and background
        self.width, self.height = canvas.get_size()
        background_rect = [a / 2 for a in canvas.get_size()]
        self.background.transform(center=background_rect,
                                  scale=(self.height - 2 * bar_width) /
                                  self.background.image.get_size()[1])
        self.background.draw(canvas)
        self.font_size = int(
            (self.height - 2 * bar_width) / (2 * self.len_letters))

        # displaying letters
        if self.counter <= self.len_letters:
            self.write_letters(canvas, self.counter)
        else:
            # when it s time for printing
            self.write_letters(canvas, self.len_letters)

            # checking some or all lines
            if self.counter < 2 * self.len_letters:
                number_of_lines = (self.counter - 1) % self.len_letters + 1
            else:
                number_of_lines = self.len_letters

            # marking letters
            for i in range(number_of_lines):
                for j in range(beats_number):
                    # circle for pressed ones
                    if self.got_or_not[i][j] == 1:
                        pygame.draw.circle(canvas, (250, 250, 250), [
                            self.width // 2 + int(
                                (j - (len(self.letters[i]) - 1) / 2) *
                                self.font_size),
                            int(1.05 * bar_width) + int(
                                (i + 1) * (self.height - 2 * bar_width) /
                                (self.len_letters + 1))
                        ], int(self.font_size // 2.5),
                                           int(self.font_size // 20))

                    # crosses for missed ones
                    elif self.got_or_not[i][j] == -1:
                        # center x and y for a letter
                        x = self.width // 2 + int(
                            (j -
                             (len(self.letters[i]) - 1) / 2) * self.font_size)
                        y = bar_width + int(
                            (i + 1) * (self.height - 2 * bar_width) /
                            (self.len_letters + 1))

                        pygame.draw.line(
                            canvas, (250, 250, 250),
                            [x + self.font_size // 3, y + self.font_size // 3],
                            [x - self.font_size // 3, y - self.font_size // 3],
                            5)
                        pygame.draw.line(
                            canvas, (250, 250, 250),
                            [x - self.font_size // 3, y + self.font_size // 3],
                            [x + self.font_size // 3, y - self.font_size // 3],
                            5)

    def handle(self, event):
        delta_score = 0
        delta_health = 0
        if self.counter > self.len_letters and event['key']['unicode'] in characters \
                and math.fabs(event['time']['delta']) < 0.2:
            bars = (event['time']['bars'] - 1) % self.len_letters
            beats = event['time']['beats']

            # new press on already pressed correctly letter also counts
            if event['key']['unicode'] == self.letters[bars][beats]:
                if self.got_or_not[bars][beats] == -1:
                    # if the letter was already marked wrong we return health back
                    delta_health += 5

                self.got_or_not[bars][beats] = 1
                delta_score += 5

            # if the event_key was already accepted we dont charge for new wrong
            elif self.letters[bars][beats] != 1:
                delta_health -= 5
                self.got_or_not[bars][beats] = -1

        return {'delta_health': delta_health, 'delta_score': delta_score}

    def write_letters(self, canvas, counter):

        font = pygame.font.Font('Assets/Fonts/Patapon.ttf', self.font_size)

        for i in range(counter):
            # last line only already beated letters if it's first half
            if i == counter - 1 and self.counter <= self.len_letters:
                local_counter = self.letter_counter + 1
            else:
                local_counter = beats_number

            for j in range(local_counter):
                pause_text = font.render(self.letters[i][j], 1,
                                         (250, 250, 250))
                canvas.blit(
                    pause_text,
                    pause_text.get_rect(center=[
                        self.width // 2 + (j -
                                           (len(self.letters[i]) - 1) / 2) *
                        self.font_size, bar_width + (i + 1) *
                        (self.height - 2 * bar_width) / (self.len_letters + 1)
                    ]))

    def create_letters(self, life_time):
        letters = []
        for i in range((life_time - 1) // 2):
            line = []
            for j in range(beats_number):
                line.append(choice(characters))
            letters.append(line)
        return letters
예제 #5
0
class Disclaimer(AbstractUI):
    def __init__(self, canvas):
        super().__init__(canvas)
        self.runtime = AnimationRuntime()
        self.status = Status.TRIANGLE
        ball_surf = pygame.Surface((150, 150))
        pygame.draw.ellipse(ball_surf, (0, 255, 255), (0, 0, 150, 150))
        self.ball_sprite = Sprite(ball_surf)
        self.ball_sprite.transform(center=(400, 400), scale=2)

    def schedule_animations(self):
        center = tuple(a / 2 for a in self.canvas.get_size())
        pygame_logo = Sprite('Assets/Artwork/UI/Disclaimer/pygame_logo.png')
        pygame_logo.transform(center=center, opacity=0)
        noblow_logo = Sprite('Assets/Artwork/UI/Disclaimer/cat_blow.png')
        noblow_logo.transform(center=center, opacity=0)
        times_font = pygame.font.Font('Assets/Fonts/Times New Roman.ttf', 30)
        greet_sprite = Sprite(times_font.render('From creators of lab3.1 and lab3.2', 1, (255,) * 3))
        greet_sprite.transform(center=center, opacity=0)
        self.runtime.add_animation_by_keyframes(self.ball_sprite, {
            1: {'scale': 0}
        })

        self.runtime.add_animation_by_keyframes(pygame_logo, {
            2: {},
            4: {'opacity': 1, 'scale': 1.2},
            6: {'opacity': 0, 'scale': 1.4}
        })
        self.runtime.add_animation_by_keyframes(noblow_logo, {
            7: {},
            9: {'opacity': 1, 'scale': 1.2},
            11: {'opacity': 0, 'scale': 1.4}
        })
        self.runtime.add_animation_by_keyframes(greet_sprite, {
            12: {},
            14: {'opacity': 1, 'scale': 1.2},
            16: {'opacity': 0, 'scale': 1.4},
            17: {}
        })

    def key_press(self, event):
        if self.status == Status.TRIANGLE:
            if event['key'] == pygame.K_ESCAPE:
                return 'EXIT'
            self.status = Status.PRESENT
            self.schedule_animations()
        else:
            self.runtime.delete_all_animations()
            return self.views['menu']

    def update(self):
        self.runtime.update_all(self.canvas)
        if self.status == Status.PRESENT and not self.runtime.is_animating():
            self.status = Status.AWAIT
        if self.status == Status.AWAIT and not self.runtime.is_animating():
            center = tuple(a / 2 for a in self.canvas.get_size())
            times_font = pygame.font.Font('Assets/Fonts/Times New Roman.ttf', 30)
            continue_sprite = Sprite(times_font.render('Press any key to continue', 1, (255,) * 3))
            continue_sprite.transform(center=center, opacity=0)
            self.runtime.add_animation_by_keyframes(continue_sprite, {
                1: {'opacity': 1},
                2: {'opacity': 0}
            })

    def draw_widgets(self):
        if self.status == Status.TRIANGLE:
            delta = (time.time() % 0.5 - 0.25) * 2
            r = (0.5 - abs(delta)) ** 2.1 * 50 + 100
            self.ball_sprite.transform(scale=r / 75)
            self.ball_sprite.draw(self.canvas)