Ejemplo n.º 1
0
                player.go("left")

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_w or event.key == pygame.K_UP:
                player.go("stop up")
            if event.key == pygame.K_d or event.key == pygame.K_RIGHT:
                player.go("stop right")
            if event.key == pygame.K_s or event.key == pygame.K_DOWN:
                player.go("stop down")
            if event.key == pygame.K_a or event.key == pygame.K_LEFT:
                player.go("stop left")

    #if random.randint(0,10*60) == 0:
    #    powerups+=[PowerUp("burst shot", [0, 5], [random.randint(0, width),0])]

    theWalls.update()

    player.update(width, height)
    for powerup in powerups:
        powerup.update(width, height)

    bgColor = r, g, b
    screen.fill(bgColor)

    screen.blit(player.image, player.rect)
    for powerup in powerups:
        screen.blit(powerup.image, powerup.rect)
    for wall in theWalls.walls:
        screen.blit(wall.image, wall.rect)
    pygame.display.flip()
    clock.tick(45)
Ejemplo n.º 2
0
class Game:
    def __init__(self):
        pygame.mixer.pre_init(22050, -16, 2, 1024)
        pygame.init()
        self.music = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "luminary.wav"))
        self.screen = pygame.display.set_mode(c.WINDOW_SIZE)
        pygame.display.set_caption(c.GAME_NAME)
        self.clock = pygame.time.Clock()
        self.name = "WWWW"
        self.max_score = None

        self.port_on_load = get_server_port()
        self.error_message = ""

        self.slowdown = 1.0
        self.effect_slow = 1.0
        self.since_effect = 1000
        self.since_shake = 1000
        self.shake_amp = 0
        self.shake_frequency = 9
        self.shake_offset = 0
        self.score_background = pygame.image.load(
            os.path.join(c.ASSETS_PATH, "score_background.png"))
        self.title_background = pygame.image.load(
            os.path.join(c.ASSETS_PATH, "title.png"))

        self.tear_sounds = [
            pygame.mixer.Sound(os.path.join(c.ASSETS_PATH, "tear1.wav")),
            pygame.mixer.Sound(os.path.join(c.ASSETS_PATH, "tear2.wav")),
            pygame.mixer.Sound(os.path.join(c.ASSETS_PATH, "tear3.wav")),
            pygame.mixer.Sound(os.path.join(c.ASSETS_PATH, "tear4.wav"))
        ]
        self.bad_tear_sounds = [
            pygame.mixer.Sound(os.path.join(c.ASSETS_PATH, "bad_tear1.wav")),
            pygame.mixer.Sound(os.path.join(c.ASSETS_PATH, "bad_tear2.wav"))
        ]
        self.explosion = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "explosion.wav"))
        self.explosion.set_volume(0.8)
        self.dash = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "dashing.wav"))
        self.dash.set_volume(0.4)
        for sound in self.tear_sounds + self.bad_tear_sounds:
            sound.set_volume(0.16)
        self.nope = pygame.mixer.Sound(os.path.join(c.ASSETS_PATH, "nope.wav"))
        self.nope.set_volume(0.3)
        self.fifths = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "fifths.wav"))
        self.typing = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "type.wav"))
        self.bounce = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "bounce_wall.wav"))
        self.bounce.set_volume(0.13)
        self.reset_sound = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "reset.wav"))
        self.reset_sound.set_volume(1.5)
        self.typing.set_volume(0.7)
        self.wings_charged = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "wings_charged.wav"))
        self.wings_used = pygame.mixer.Sound(
            os.path.join(c.ASSETS_PATH, "wings_used.wav"))
        self.sus = pygame.mixer.Sound(os.path.join(c.ASSETS_PATH, "sus.wav"))
        self.retry_button = Button((c.MIDDLE_X, c.MIDDLE_Y + 50),
                                   "Retry",
                                   visible=False)
        self.submit_button = Button((c.MIDDLE_X, c.MIDDLE_Y + 100),
                                    "Submit",
                                    visible=False)
        self.buttons = [self.retry_button, self.submit_button]

        self.name_input()
        self.screen.fill(c.BLACK)
        pygame.display.flip()
        start = time.time()
        while time.time() < start + 2:
            self.update_globals(0.01)
        self.music.play(-1)
        while True:
            self.title_sequence()
            result = 1
            while result == 1:
                result = self.main()

    def launch_factor_multiplier(self):
        if self.score() < 1000:
            return 1
        else:
            return min(10, (self.score() - 1000) / 4000 + 1)

    def title_sequence(self):
        self.error_message = ""
        now = time.time()
        time.sleep(0.001)
        self.phase = c.TITLE
        play = Button((c.MIDDLE_X, c.MIDDLE_Y + 100), "Play", (1, 1))
        scoreboard = Button((c.MIDDLE_X, c.MIDDLE_Y + 155), "High scores",
                            (1, 1))
        while True:
            dt = self.clock.tick(60) / 1000
            dt, events = self.update_globals(dt)
            play.update(dt, events)
            scoreboard.update(dt, events)
            self.screen.blit(self.title_background, (0, 0))
            play.draw(self.screen)
            scoreboard.draw(self.screen)
            self.draw_error_text(self.screen)
            pygame.display.flip()
            if scoreboard.clicked:
                container = []
                self.get_sprocket(container)
                if len(container):
                    self.error_message = ""
                    self.score_phase(container[0])
                    scoreboard.font_size = 40
                    scoreboard.target_font_size = 40
                    scoreboard.scale = 1.0
                else:
                    self.error_message = "No internet connection"
            if play.clicked:
                break
        black = pygame.Surface(c.WINDOW_SIZE)
        black.fill(c.BLACK)
        black.set_alpha(0)
        start = time.time()
        while True:
            dt = self.clock.tick(60) / 1000
            diff = time.time() - start
            dt, events = self.update_globals(dt)
            self.screen.blit(self.title_background, (0, 0))
            play.draw(self.screen)
            scoreboard.draw(self.screen)
            self.screen.blit(black, (0, 0))
            pygame.display.flip()

            black.set_alpha(min(255 * diff * 6, 255))
            if (255 * diff * 6) > 255:
                break

    def name_input(self):
        now = time.time()
        time.sleep(0.001)

        name_font = pygame.font.Font(
            os.path.join(c.ASSETS_PATH, "great_answer.ttf"), 70)
        prompt_font = pygame.font.Font(
            os.path.join(c.ASSETS_PATH, "great_answer.ttf"), 30)

        self.name = ""
        self.phase = c.NAME_PHASE
        continue_button = Button((c.WINDOW_WIDTH // 2, c.WINDOW_HEIGHT - 60),
                                 "continue", (5, 5),
                                 visible=False,
                                 true_scale=0.65)
        while True:
            dt = self.clock.tick(60) / 1000
            dt, events = self.update_globals(dt)
            continue_button.disabled = not len(self.name) > 0
            if self.name:
                continue_button.visible = True
            for word in c.PROFANITY:
                if word.upper() in self.name:
                    continue_button.disabled = True
            continue_button.update(dt, events)
            for event in events:
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RETURN and not continue_button.disabled:
                        continue_button.clicked = True

            self.screen.fill(c.BLACK)

            surf = prompt_font.render("Type your name", 1, (150, 150, 150))
            self.screen.blit(
                surf, (c.MIDDLE_X - surf.get_width() // 2, c.MIDDLE_Y - 85))

            name_render = name_font.render(self.name, 1, c.WHITE)
            self.screen.blit(
                name_render,
                (c.WINDOW_WIDTH // 2 - name_render.get_width() // 2,
                 c.WINDOW_HEIGHT // 2 - name_render.get_height() // 2))
            continue_button.draw(self.screen)

            if self.name and continue_button.clicked:
                break

            for event in events:
                if event.type == pygame.KEYDOWN:
                    k = pygame.key.name(event.key)
                    if k in "abcdefghijklmnopqrstuvwxyz1234567890":
                        self.name += k.capitalize()
                        if len(self.name) < 6:
                            self.typing.play()
                    if k.lower() == "backspace":
                        self.name = self.name[:-1]
            self.name = self.name[:5]
            pygame.display.flip()
        self.fifths.play()

    def tear_sound(self):
        random.choice(self.tear_sounds).play()
        self.explosion.play()

    def bad_tear_sound(self):
        random.choice(self.tear_sounds).play()

    def update_enemies(self, dt, events, n=10):
        while len(self.enemies) < n:
            if len(self.enemies) == 1:
                spacing = int(c.WINDOW_HEIGHT * 0.85)
            else:
                spacing = (c.WINDOW_HEIGHT//4) * (self.enemies[-1].y + 20000)/20000 \
                          + random.random() * c.WINDOW_HEIGHT//3 \
                          - c.WINDOW_HEIGHT//8
            if spacing > c.WINDOW_HEIGHT * 0.8:
                spacing = c.WINDOW_HEIGHT * 0.8
            padding = 60
            x = random.random()*(self.walls.width - 2 * padding) \
                       + c.MIDDLE_X \
                       - (self.walls.width - 2 * padding)/2
            y = self.enemies[-1].y + spacing
            seed = random.random()
            if self.y_offset < 2000:
                if seed < 0.3:
                    new_enemy = Enemy
                elif seed < 0.7:
                    new_enemy = BigEnemy
                else:
                    new_enemy = SmallEnemy
            elif self.y_offset < 5000:
                if seed < 0.5:
                    new_enemy = Enemy
                elif seed < 0.7:
                    new_enemy = BigEnemy
                else:
                    new_enemy = SmallEnemy
            else:
                if seed < 0.7:
                    new_enemy = Enemy
                elif seed < 0.8:
                    new_enemy = BigEnemy
                else:
                    new_enemy = SmallEnemy
            self.enemies.append(new_enemy(self, x=x, y=y))

    def loading_text(self):
        dots = int(time.time() * 2) % 3 + 1
        return f"Connecting{'.' * dots}"

    def draw_tutorial(self, surface):
        if self.y_offset > c.WINDOW_HEIGHT or self.tutorial_offset > c.WINDOW_HEIGHT:
            return
        surf = tutorial_clicked if time.time(
        ) % 1 < 0.5 else tutorial_unclicked
        surf = surf.copy().convert()
        surf.set_colorkey((255, 0, 255))
        surface.blit(surf, (c.MIDDLE_X - surf.get_width() // 2 - 30,
                            c.WINDOW_HEIGHT - surf.get_height() - 60 +
                            self.y_offset // 2 + self.tutorial_offset))

    def draw_loading_text(self, surface):
        self.loading_font = pygame.font.Font(
            os.path.join(c.ASSETS_PATH, "gothland.ttf"), 20)
        w = self.loading_font.render("Connecting.", 1, c.WHITE).get_width()
        surf = self.loading_font.render(self.loading_text(), 1, c.WHITE)
        surface.blit(surf, (c.MIDDLE_X - w // 2, c.WINDOW_HEIGHT - 30))

    def draw_error_text(self, surface):
        self.loading_font = pygame.font.Font(
            os.path.join(c.ASSETS_PATH, "gothland.ttf"), 20)
        surf = self.loading_font.render(self.error_message, 0, c.WHITE)
        if self.phase == c.GAME_PHASE:
            surf = surf.convert()
            surf.set_colorkey(c.BLACK)
            surf.set_alpha(255 - 155 * self.aimingness)
        surface.blit(
            surf, (c.MIDDLE_X - surf.get_width() // 2, c.WINDOW_HEIGHT - 30))

    def reset(self):
        self.y_offset = 0
        self.player = Player(self)
        self.walls = Walls(self)
        self.slice = Slice(self)
        self.enemies = [
            TutorialEnemy(self, y=c.WINDOW_HEIGHT / 2, x=c.MIDDLE_X)
        ]
        self.enemies[0].angle = 0
        self.update_enemies(0, [])
        self.particles = []
        self.text_particles = []
        self.background = Background(self)
        self.player.velocity = (100, 600)
        self.aiming = False
        self.aimingness = 0

        self.score_yoff = 50
        self.score_size = 40
        self.target_score_size = 40
        self.score_bumped = True

        self.shade = pygame.Surface(c.WINDOW_SIZE)
        self.shade.fill(c.BLACK)
        self.shade.set_alpha(0)

        self.shade_2 = pygame.Surface(c.WINDOW_SIZE)
        self.shade.fill(c.BLACK)
        self.shade_2.set_alpha(0)

        self.shade_3 = pygame.Surface(c.WINDOW_SIZE)
        self.shade.fill(c.BLACK)
        self.shade_3.set_alpha(255)

        self.flare = pygame.Surface(c.WINDOW_SIZE)
        self.flare.fill((255, 226, 140))
        self.flare.set_alpha(0)
        self.flare_alpha = 0

        self.multiplier = 1

        self.queue_reset = False

        self.game_end = False

        self.retry_button.visible = False
        self.submit_button.visible = False
        self.closing = False
        self.freeze_surf = None

        for button in self.buttons:
            button.disabled = False

        self.error_message = ""
        self.tutorial = True
        self.tutorial_offset = 0

    def update_tutorial(self, dt, events):
        if not self.tutorial:
            return
        if self.player.y > 150 and self.player.velocity[
                1] >= 0 or self.player.y > 60 and self.player.velocity[1] <= 0:
            self.aiming = True
            self.tutorial = False

    def update_effects(self, dt, events):
        if self.max_score is not None and self.score() > self.max_score:
            self.error_message = "NEW HIGH SCORE"
        self.music.set_volume(0.8 - 0.6 * self.aimingness)

        if self.player_is_dead():
            self.aiming = False
            self.tutorial_offset += dt * 750

        if self.queue_reset and self.player_is_dead():
            self.retry_button.visible = True
            self.submit_button.visible = True

        self.since_effect += dt
        if self.since_effect > 0:
            self.effect_slow = 1.0
        else:
            self.effect_slow = 0.01

        self.since_shake += dt
        self.shake_offset = self.shake_amp * math.cos(
            self.since_shake * self.shake_frequency * 2 * math.pi)
        self.shake_amp *= 0.2**dt
        self.shake_amp = max(self.shake_amp - 200 * dt, 0)

        self.flare_alpha *= 0.7**dt
        self.flare_alpha -= 300 * dt
        self.flare_alpha = max(0, self.flare_alpha)
        self.flare.set_alpha(self.flare_alpha)

        if not self.queue_reset:
            if self.score() % 1000 < 500 and not self.score_bumped:
                self.score_bumped = True
                self.score_size = 120
                self.sus.play()
            if self.score() % 1000 > 500 and self.score_bumped:
                self.score_bumped = False

        ds = self.target_score_size - self.score_size
        if ds > 0:
            self.score_size = min(self.score_size + ds * 5 * dt,
                                  self.target_score_size)
        else:
            self.score_size = max(self.score_size + ds * 5 * dt,
                                  self.target_score_size)

        if self.queue_reset:
            self.target_score_size = 80
            dy = c.MIDDLE_Y - self.score_yoff
            self.score_yoff = min(self.score_yoff + dy * 5 * dt,
                                  c.MIDDLE_Y - 100)

    def score(self):
        if not self.phase == c.GAME_PHASE:
            return -1
        return int(self.y_offset // 10)

    def draw_score(self):
        text = f"{self.score()}"
        self.score_font = pygame.font.Font(
            os.path.join(c.ASSETS_PATH, "no_continue.ttf"),
            int(self.score_size))
        surf = self.score_font.render(text, 0, c.WHITE)
        surf2 = self.score_font.render(text, 0, c.BLACK)
        x = c.MIDDLE_X - surf.get_width() // 2
        y = self.score_yoff

        mpos = pygame.mouse.get_pos()
        padding = 35
        inner_padding = 12
        dx = max(x - mpos[0], mpos[0] - x - surf.get_width())
        dy = max(y - mpos[1], mpos[1] - y - surf.get_height())
        small_alpha = 80
        if dx < inner_padding and dy < inner_padding:
            if self.aiming:
                surf.set_alpha(small_alpha)
                surf2.set_alpha(small_alpha)
        elif dx < padding + inner_padding and dy < padding + inner_padding:
            diff = padding - (max(dx, dy) - inner_padding)
            if self.aiming:
                small_alpha = 255 - (255 - small_alpha) * (diff / padding)
                surf.set_alpha(small_alpha)
                surf2.set_alpha(small_alpha)

        self.screen.blit(surf2, (x, y + self.score_size // 10))
        self.screen.blit(surf, (x, y))

    def slowdown_effect(self, duration=0.4):
        self.since_effect = -duration

    def shake_effect(self, amplitude=20):
        if amplitude < self.shake_amp:
            return
        self.since_shake = 0
        self.shake_amp = max(amplitude, self.shake_amp)

    def update_offset(self, dt, events):
        max_off = c.WINDOW_HEIGHT * 0.7
        if self.player.y > self.y_offset + max_off and type(
                self.enemies[0]) is not TutorialEnemy:
            self.y_offset = self.player.y - max_off

    def update_aim(self, dt, events):
        speed = 7
        da = self.aiming - self.aimingness
        self.aimingness += h.sign(da) * dt * speed
        if self.aimingness > 1:
            self.aimingness = 1
        elif self.aimingness < 0:
            self.aimingness = 0

        self.shade.set_alpha(128 * self.aimingness)
        self.slowdown = 1 - 0.95 * self.aimingness

    def draw_shade(self):
        self.screen.blit(self.shade, (0, 0))

    def flare_up(self, amt):
        self.flare_alpha = amt

    def game_to_screen_y(self, y):
        return c.WINDOW_HEIGHT - y + self.y_offset

    def game_position_to_screen_position(self, pos):
        x = pos[0] + self.shake_offset
        y = self.game_to_screen_y(pos[1]) + self.shake_offset
        return x, y

    def screen_position_to_game_position(self, pos):
        x = pos[0]
        y = c.WINDOW_HEIGHT - pos[1] + self.y_offset
        return x, y

    def mouse_position(self):
        mpos = pygame.mouse.get_pos()
        return self.screen_position_to_game_position(mpos)

    def main(self):
        self.reset()
        self.phase = c.GAME_PHASE

        then = time.time()
        self.clock.tick(c.MAX_FPS)
        time.sleep(0.001)
        since_print = 0
        fpss = []

        while True:
            now = time.time()
            rdt = now - then
            if rdt > 1 / 30: rdt = 1 / 30
            then = now
            since_print += rdt
            fpss.insert(0, 1 / rdt)
            fpss = fpss[:100]
            # if since_print > 1.0:
            #     since_print = 0
            #     print(f"FPS: {sum(fpss)/len(fpss)}")

            # Do things
            dt, events = self.update_globals(rdt)
            self.update_tutorial(dt, events)
            if self.queue_reset:
                new_alpha = self.shade_2.get_alpha() + 500 * dt
                self.shade_2.set_alpha(min(new_alpha, 160))
            for button in self.buttons:
                button.update(rdt, events)
            self.slice.update(rdt, events)
            self.update_effects(rdt, events)
            self.player.update(dt, events)
            self.walls.update(dt, events)
            self.background.update(dt, events)
            self.update_aim(dt, events)
            self.update_offset(dt, events)
            self.update_enemies(dt, events)
            for enemy in self.enemies[::-1]:
                enemy.update(dt, events)
            for particle in self.particles[::-1]:
                particle.update(dt, events)
            for particle in self.text_particles[::-1]:
                particle.update(rdt, events)

            # Draw things
            # self.screen.fill((150, 150, 150))
            self.background.draw(self.screen)
            for particle in self.particles:
                particle.draw(self.screen)
            if self.shade.get_alpha() > 0:
                self.draw_shade()
            for enemy in self.enemies:
                enemy.draw(self.screen)
            self.walls.draw(self.screen)
            for particle in self.text_particles:
                particle.draw(self.screen)
            if self.flare_alpha > 0:
                self.screen.blit(self.flare, (0, 0))
            if self.aiming:
                self.slice.draw(self.screen)
            self.player.draw(self.screen)
            if self.queue_reset:
                self.screen.blit(self.shade_2, (0, 0))
            if self.submit_button.clicked:
                self.freeze_surf = self.screen.copy()
            self.draw_score()
            for button in self.buttons:
                button.draw(self.screen)
            self.draw_error_text(self.screen)
            self.draw_tutorial(self.screen)
            if self.shade_3.get_alpha() > 0:
                self.screen.blit(self.shade_3, (0, 0))
            self.update_screen()

            # Other things?
            if self.submit_button.clicked:
                self.error_message = ""
                status = self.submit_score()
                for button in self.buttons:
                    button.disabled = False
                if status == c.SCORE_RECEIVED:
                    return 0
                elif status == c.NO_CONNECT:
                    self.submit_button.clicked = False
                    self.error_message = "No Internet connection"
                elif status == c.TIMEOUT:
                    self.submit_button.clicked = False
                    self.error_message = "Server timed out"
            if self.retry_button.clicked:
                self.retry_button.clicked = False
                self.closing = True
                self.reset_sound.play()
            if self.closing:
                new_alpha = self.shade_3.get_alpha() + 1000 * dt
                self.shade_3.set_alpha(min(new_alpha, 255))
                if self.shade_3.get_alpha() == 255:
                    return 1
            else:
                new_alpha = self.shade_3.get_alpha() - 1000 * dt
                self.shade_3.set_alpha(max(new_alpha, 0))

            self.clock.tick(c.MAX_FPS)

    def update_globals(self, dt):
        events = pygame.event.get()
        if self.phase == c.GAME_PHASE and self.player.y < self.y_offset - 100:
            self.player.test_wings()
        if self.phase == c.GAME_PHASE and self.player_is_dead():
            self.queue_reset = True
        for event in events:
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit(0)
            if event.type == pygame.MOUSEBUTTONUP and self.phase == c.GAME_PHASE:
                if event.button == 1:  # 1 is left click
                    self.player.dash_toward(self.mouse_position(), 300)
                    self.aiming = False
                    self.aimingness = 0
            if event.type == pygame.MOUSEBUTTONDOWN and self.phase == c.GAME_PHASE and not self.player.cutting and not self.queue_reset:
                if event.button == 1:
                    self.shade_target_alpha = 100
                    self.aiming = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r and self.phase == c.GAME_PHASE:
                    self.queue_reset = True
        return dt * min(self.slowdown, self.effect_slow), events

    def update_screen(self):
        pygame.display.flip()

    def player_is_dead(self):
        return self.player.y < self.y_offset - 50 and not self.player.flying and not self.player.has_wings

    def get_sprocket(self, container):
        try:
            port = get_server_port()
            if not port:
                return
            sprocket = Sprocket(c.SERVER_ADDR, port)
            container.append(sprocket)
        except Exception as e:
            print(e)

    def submit_score(self):
        name = self.name
        container = []
        threading.Thread(target=self.get_sprocket,
                         args=(container, ),
                         daemon=True).start()
        age = 0
        while not container:
            dt = self.clock.tick(60) / 1000
            age += dt
            if age > c.TIMEOUT_TIME:
                return c.TIMEOUT
            if threading.active_count() == 1 and not container:
                return c.NO_CONNECT
            self.screen.blit(self.freeze_surf, (0, 0))
            self.draw_score()
            for button in self.buttons:
                button.disabled = True
                button.update(dt, [])
                button.draw(self.screen)
            self.draw_loading_text(self.screen)
            self.update_globals(dt)
            pygame.display.flip()
        sprocket = container[0]
        sprocket.send(type="push", score=self.score(), name=name)
        result = []
        age = 0
        do_break = False
        while not do_break:
            dt = self.clock.tick(60) / 1000
            age += dt
            self.update_globals(dt)
            if age > c.TIMEOUT_TIME:
                return c.TIMEOUT
            result += sprocket.get()
            for packet in result:
                if packet.has("success") and packet.success:
                    do_break = True
        return self.score_phase(sprocket)

    def draw_scoreboard(self, surface, scoreboard):
        size = 30
        font = pygame.font.Font(os.path.join(c.ASSETS_PATH, "no_continue.ttf"),
                                size)
        scores = scoreboard.data
        spacing = int(1.25 * size)
        x = int(c.WINDOW_WIDTH * 0.55)
        y = int(c.WINDOW_HEIGHT - (size * 10 + (spacing - size) * 9)) // 2 + 50
        green = (60, 210, 100)
        shadow_offset = 3
        self.max_score = scores[9].score
        for item in scores[:10]:
            if item.name == self.name and item.score == self.score():
                color = green
                green = c.WHITE
            else:
                color = c.WHITE
            name = item.name[:5]
            space = ""
            width = 225
            text = f"{name}:"
            surfb = font.render(text, 1, c.BLACK)
            surf = font.render(text, 1, color)
            surface.blit(surfb, (x, y + shadow_offset))
            surface.blit(surf, (x, y))
            surf2 = font.render(f"{item.score}", 1, color)
            surf2b = font.render(f"{item.score}", 1, c.BLACK)
            surface.blit(surf2b,
                         (x + width - surf2.get_width(), y + shadow_offset))
            surface.blit(surf2, (x + width - surf2.get_width(), y))

            y += spacing

    def score_phase(self, sprocket):
        age = 0
        alpha = 255
        self.freeze_surf = self.screen.copy().convert()
        sprocket.send(type="print")
        result = []
        has_result = False
        while alpha > 0 or not has_result:
            dt = self.clock.tick(60) / 1000
            age += dt
            self.screen.fill(c.BLACK)
            alpha = max(0, 255 - age * 900)
            self.freeze_surf.set_alpha(alpha)
            self.screen.blit(self.freeze_surf, (0, 0))
            self.update_globals(dt)

            pygame.display.flip()

            result += sprocket.get()
            for packet in result:
                if packet.has("scores"):
                    scoreboard = packet.scores
                    has_result = True
        shade = pygame.Surface(c.WINDOW_SIZE)
        shade.fill(c.BLACK)
        shade.set_alpha(255)
        age = 0
        back_button = Button((140, c.WINDOW_HEIGHT - 100),
                             "back", (50, 50),
                             visible=True)
        buttons = [back_button]
        while True:
            dt = self.clock.tick(60) / 1000
            age += dt
            _, events = self.update_globals(dt)
            for button in buttons:
                button.update(dt, events)

            shade.set_alpha(255 - min(255, age * 900))
            self.screen.blit(self.score_background, (0, 0))
            self.draw_scoreboard(self.screen, scoreboard)
            for button in buttons:
                button.draw(self.screen)
            self.screen.blit(shade, (0, 0))
            pygame.display.flip()

            if back_button.clicked:
                return c.SCORE_RECEIVED