Ejemplo n.º 1
0
    def __init__(self, game, config):
        self.game = game
        self.screen = None
        self.prepareDrawNeeded = True
        self.updateFpsTime = -2
        self.time = 0

        self.config = config

        self.showTimingHints = config["show-timing-hints"]
        self.bands = tuple(Band() for i in xrange(len(self.game.bands)))
        self.drawHits = []
        self.drawnScore = -1
        self.drawnCombo = -1
        self.drawnBestCombo = -1
        self.resultsFadeIn = 0.0

        self.frontend = game.frontend

        self.bigFont = self.frontend.loadFont(*config["fonts"]["big"])
        self.mediumFont = self.frontend.loadFont(*config["fonts"]["medium"])
        self.smallFont = self.frontend.loadFont(*config["fonts"]["small"])
        self.tinyFont = self.frontend.loadFont(*config["fonts"]["tiny"])

        self.noteGradients = config["note-gradients"]
        self.holdGradients = config["hold-gradients"]
        self.overlayAlpha = config["overlay-alpha"] * 255

        self.notecolors = []
        self.beamcolors = []

        nbb = config["colors"]["notes-by-band"]
        if nbb["enabled"]:
            colors = nbb["notes"]
            colorcount = len(colors)
            bandcount = len(self.bands)

            for i in (a * max(1, int(round(colorcount / bandcount)))
                      for a in xrange(bandcount)):
                note = colors[(i - max(0, (bandcount - colorcount) // 2)) %
                              colorcount]
                beam = mix(note, nbb["hold-mixin"], nbb["hold-mixin-factor"])

                self.notecolors.append(pygame.Color(*note))
                self.beamcolors.append(pygame.Color(*beam))
        else:
            self.notecolors = [pygame.Color(*config["colors"]["note"])] * len(
                self.bands)
            self.beamcolors = [pygame.Color(*config["colors"]["holdbeam"])
                               ] * len(self.bands)

        self.dummySurf = None
Ejemplo n.º 2
0
    def __init__(self, game, config):
        self.game = game
        self.screen = None
        self.prepareDrawNeeded = True
        self.updateFpsTime = -2
        self.time = 0

        self.config = config

        self.showTimingHints = config["show-timing-hints"]
        self.bands = tuple(Band() for i in xrange(len(self.game.bands)))
        self.drawHits = []
        self.drawnScore = -1
        self.drawnCombo = -1
        self.drawnBestCombo = -1
        self.resultsFadeIn = 0.0

        self.frontend = game.frontend

        self.bigFont    = self.frontend.loadFont(*config["fonts"]["big"])
        self.mediumFont = self.frontend.loadFont(*config["fonts"]["medium"])
        self.smallFont  = self.frontend.loadFont(*config["fonts"]["small"])
        self.tinyFont   = self.frontend.loadFont(*config["fonts"]["tiny"])

        self.noteGradients = config["note-gradients"]
        self.holdGradients = config["hold-gradients"]
        self.overlayAlpha = config["overlay-alpha"] * 255

        self.notecolors = []
        self.beamcolors = []

        nbb = config["colors"]["notes-by-band"]
        if nbb["enabled"]:
            colors = nbb["notes"]
            colorcount = len(colors)
            bandcount = len(self.bands)

            for i in (a * max(1, int(round(colorcount / bandcount))) for a in xrange(bandcount)):
                note = colors[(i - max(0, (bandcount - colorcount) // 2)) % colorcount]
                beam = mix(note, nbb["hold-mixin"], nbb["hold-mixin-factor"])

                self.notecolors.append(pygame.Color(*note))
                self.beamcolors.append(pygame.Color(*beam))
        else:
            self.notecolors = [pygame.Color(*config["colors"]["note"])]     * len(self.bands)
            self.beamcolors = [pygame.Color(*config["colors"]["holdbeam"])] * len(self.bands)

        self.dummySurf = None
Ejemplo n.º 3
0
    def draw(self, screen):
        if self.prepareDrawNeeded or screen is not self.screen:
            self.prepareDraw(screen)

        game = self.game
        stats = game.stats
        config = self.config
        colors = config["colors"]
        txtcolors = colors["text"]
        dt = game.clock.deltaTime

        if game.finished:
            self.resultsFadeIn = approach(self.resultsFadeIn, 1.0, dt / 1250.0)
            uiAlpha = 255 * (1 - self.resultsFadeIn)
        else:
            uiAlpha = 255

        if self.time > self.updateFpsTime:
            self.fpsSurf = self.renderText("%i FPS" % game.clock.fps,
                                           self.smallFont,
                                           txtcolors["fps"],
                                           direct=True)
            self.updateFpsTime = self.time + 500

        screen.fill(colors["background"])

        bounds = screen.get_rect()
        bandWidth = self.bandWidth
        noterate = (bounds.height * game.noterate) / 1000

        if self.showTimingHints:
            self.bandAccSurf.fill((0, 0, 0, 0))
            for s in scoreinfo.values:
                toffs = (s.threshold * noterate)
                pygame.draw.rect(self.bandAccSurf, self.scoreInfoColors[s],
                                 (0, bounds.height - self.targetoffs - toffs,
                                  bandWidth, toffs * 2), 0)

        for band in self.bands:
            o = band.offset

            if band.held:
                band.flash = self.time
                flash = 1.0
            else:
                flash = 1.0 - clamp(0, (self.time - band.flash) / 1000.0, 1)

            if flash:
                pygame.draw.rect(
                    screen,
                    mix(colors["background"], colors["bandflash"],
                        flash * flash), (o, 0, bandWidth, bounds.height), 0)

            if self.showTimingHints:
                screen.blit(self.bandAccSurf, (o, 0))

            pygame.draw.rect(screen, colors["bandborder"],
                             (o, 0, bandWidth, bounds.height), 1)
            band.drawngradients = 0

        maxNoteDist = float(bounds.height - self.targetoffs)

        for note in game.beatmap:
            hitdiff = note.hitTime - game.time + self.targetoffs / noterate
            holddiff = hitdiff + note.holdTime

            if holddiff < 0:
                continue

            if hitdiff * noterate > bounds.height + 5:
                break

            if note in game.removeNotes:
                continue

            band = game.bands[note.band]
            vband = self.bands[note.band]
            bandoffs = vband.offset
            o = bounds.height - hitdiff * noterate
            grad = None

            if band.heldNote == note:
                if self.holdGradients:
                    grad = self.highlightGradient
                clr1 = colors["highlight"]
                clr2 = colors["highlight"]
                o = min(o, bounds.height - self.targetoffs - 5)
            else:
                if self.holdGradients:
                    grad = self.gradients[note.band][128]
                clr1 = self.notecolors[note.band]
                clr2 = self.beamcolors[note.band]

            if config["show-nearest-note"] and game.beatmap.nearest(
                    note.band, game.time,
                    muz.game.scoreinfo.miss.threshold) is note:
                clr1 = colors["nearest-note"]
                clr2 = colors["nearest-note"]

            if note.holdTime:
                x = bounds.height - holddiff * noterate
                beam = pygame.Rect(
                    bandoffs + bandWidth * 0.5 - self.holdWidth * 0.5, x,
                    self.holdWidth, o - x + 5)

                pygame.draw.rect(screen, clr2, beam,
                                 1 if self.holdGradients else 0)

                if grad is not None:
                    h = int(beam.height)
                    if h > 0:
                        grad = pygame.transform.flip(grad, False, True)
                        grad = pygame.transform.scale(grad,
                                                      (int(beam.width), h))
                        screen.blit(grad, beam)
                        vband.drawngradients += 1

                pygame.draw.rect(screen, clr1, (bandoffs, x, bandWidth, 5), 0)

            pygame.draw.rect(screen, clr1, (bandoffs, o, bandWidth, 5), 0)

            if self.noteGradients:
                sz = int(bounds.height - self.targetoffs - o)
                if sz > 0:
                    s = self.gradients[note.band][int(
                        clamp(0, (2 - vband.drawngradients * 0.5) *
                              (o / maxNoteDist), 1) * 50.0)]
                    if s is not None:
                        s = pygame.transform.scale(s,
                                                   (int(self.bandWidth), sz))
                        screen.blit(s, (bandoffs, o + 5))
                        vband.drawngradients += 1

        for band in self.bands:
            o = band.offset
            flash = 1.0 - clamp(0, 5 * (self.time - band.flash) / 1000.0, 1)

            if flash:
                self.noteHitSurf.set_alpha(255 * flash)
                screen.blit(self.noteHitSurf,
                            (o, bounds.height - self.targetoffs - 5))

        if game.paused:
            screen.blit(self.pauseOverlaySurf, (0, 0))
        elif game.finished:
            self.pauseOverlaySurf.set_alpha(self.overlayAlpha *
                                            self.resultsFadeIn)
            screen.blit(self.pauseOverlaySurf, (0, 0))
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))
        else:
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))

        ts = self.nameSurf.get_rect()
        screen.blit(
            self.nameSurf,
            ((bounds.width - ts.width) * 0.5, bounds.height - ts.height))

        if stats.score != self.drawnScore:
            self.scoreSurf = self.renderText(str(int(stats.score)),
                                             self.bigFont, txtcolors["score"])
            self.drawnScore = stats.score

        ts = self.scoreSurf.get_rect()
        self.scoreSurf.set_alpha(uiAlpha)
        screen.blit(self.scoreSurf,
                    ((bounds.width - ts.width) * 0.5,
                     bounds.height - self.targetoffs * 0.5 - ts.height * 1.5))

        for hittime, timing in self.drawHits:
            a = 1 - clamp(0, 5 * (self.time - hittime) / 1000.0, 1)
            if a:
                s = self.accPreRendered[timing]
                s.set_alpha(255 * a)
                ts = s.get_rect()
                screen.blit(s,
                            ((bounds.width - ts.width) * 0.5, bounds.height -
                             self.targetoffs * 0.5 - ts.height * 0.5))

                scale = 1 + (1 - a) * 0.5
                s = pygame.transform.scale(
                    s, (int(ts.width * scale), int(ts.height * scale)))
                s.set_alpha(128 * a)
                ts = s.get_rect()
                screen.blit(s,
                            ((bounds.width - ts.width) * 0.5, bounds.height -
                             self.targetoffs * 0.5 - ts.height * 0.5))
            else:
                self.drawHits.remove((hittime, timing))

        if stats.combo or stats.bestCombo:
            combopos = bounds.height - self.targetoffs * 0.5 + self.mediumFont.get_height(
            ) * 0.5

        if stats.combo:
            if stats.combo != self.drawnCombo:
                self.comboSurf = self.renderText("%i combo" % stats.combo,
                                                 self.mediumFont,
                                                 txtcolors["combo"])
                self.drawnCombo = stats.combo

            ts = self.comboSurf.get_rect()
            self.comboSurf.set_alpha(uiAlpha)
            screen.blit(self.comboSurf,
                        ((bounds.width - ts.width) * 0.5, combopos))

        if stats.bestCombo:
            if stats.bestCombo != self.drawnBestCombo:
                self.bestComboSurf = self.renderText(
                    "%i best" % stats.bestCombo, self.smallFont,
                    txtcolors["best-combo"])
                self.drawnBestCombo = stats.bestCombo

            ts = self.bestComboSurf.get_rect()
            self.bestComboSurf.set_alpha(uiAlpha)
            screen.blit(self.bestComboSurf,
                        ((bounds.width - ts.width) * 0.5,
                         combopos + self.mediumFont.get_height()))

        if game.paused:
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))
            ts = self.pausedTextSurf.get_rect()
            screen.blit(self.pausedTextSurf,
                        ((bounds.width - ts.width) * 0.5,
                         (bounds.height - ts.height) * 0.5))
        elif game.finished:
            self.drawResults()

        if game.autoplay:
            screen.blit(
                self.autoplaySurf,
                (0, bounds.height - self.autoplaySurf.get_rect().height))

        ts = self.fpsSurf.get_rect()
        screen.blit(self.fpsSurf,
                    (bounds.width - ts.width, bounds.height - ts.height))

        s = self.renderText(str(int(game.time)),
                            self.smallFont,
                            txtcolors["time"],
                            direct=True)
        ts = s.get_rect()
        screen.blit(s,
                    (bounds.width - ts.width, bounds.height - ts.height * 2))

        self.time += dt
Ejemplo n.º 4
0
    def draw(self, screen):
        if self.prepareDrawNeeded or screen is not self.screen:
            self.prepareDraw(screen)

        game = self.game
        stats = game.stats
        colors = config["colors"]
        txtcolors = colors["text"]
        dt = game.clock.deltaTime

        if game.finished:
            self.resultsFadeIn = approach(self.resultsFadeIn, 1.0, dt / 1250.0)
            uiAlpha = 255 * (1 - self.resultsFadeIn)
        else:
            uiAlpha = 255

        if self.time > self.updateFpsTime:
            self.fpsSurf = self.renderText("%i FPS" % game.clock.fps, self.smallFont, txtcolors["fps"], direct=True)
            self.updateFpsTime = self.time + 500

        screen.fill(colors["background"])

        bounds = screen.get_rect()
        bandWidth = self.bandWidth
        noterate = (bounds.height * game.noterate) / 1000

        if self.showTimingHints:
            self.bandAccSurf.fill((0, 0, 0, 0))
            for s in scoreinfo.values:
                toffs = (s.threshold * noterate)
                pygame.draw.rect(self.bandAccSurf, self.scoreInfoColors[s], (0, bounds.height - self.targetoffs - toffs, bandWidth, toffs * 2), 0)

        for band in self.bands:
            o = band.offset

            if band.held:
                band.flash = self.time
                flash = 1.0
            else:
                flash = 1.0 - clamp(0, (self.time - band.flash) / 1000.0, 1)

            if flash:
                pygame.draw.rect(screen, mix(colors["background"], colors["bandflash"], flash * flash), (o, 0, bandWidth, bounds.height), 0)

            if self.showTimingHints:
                screen.blit(self.bandAccSurf, (o, 0))

            pygame.draw.rect(screen, colors["bandborder"], (o, 0, bandWidth, bounds.height), 1)

        for note in game.beatmap:
            hitdiff  = note.hitTime - game.time + self.targetoffs / noterate
            holddiff = hitdiff + note.holdTime

            if holddiff < 0:
                continue

            if hitdiff * noterate > bounds.height:
                break

            if note in game.removeNotes:
                continue

            band = game.bands[note.band]
            bandoffs = self.bands[note.band].offset
            o = bounds.height - hitdiff * noterate

            if band.heldNote == note:
                clr1 = colors["highlight"]
                clr2 = colors["highlight"]
                o = min(o, bounds.height - self.targetoffs - 5)
            else:
                clr1 = colors["note"]
                clr2 = colors["holdbeam"]

            if config["show-nearest-note"] and game.beatmap.nearest(note.band, game.time, muz.game.scoreinfo.miss.threshold) is note:
                clr1 = (0, 255, 0)
                clr2 = (0, 255, 0)

            if note.holdTime:
                x = bounds.height - holddiff * noterate

                pygame.draw.rect(screen, clr2, (bandoffs + bandWidth * 0.25, x, bandWidth * 0.5, o - x + 5), 0)
                pygame.draw.rect(screen, clr1, (bandoffs, x, bandWidth, 5), 0)

            pygame.draw.rect(screen, clr1, (bandoffs, o, bandWidth, 5), 0)

        for band in self.bands:
            o = band.offset
            flash = 1.0 - clamp(0, 5 * (self.time - band.flash) / 1000.0, 1)

            if flash:
                self.noteHitSurf.set_alpha(255 * flash)
                screen.blit(self.noteHitSurf, (o, bounds.height - self.targetoffs - 5))

        if game.paused:
            screen.blit(self.pauseOverlaySurf, (0, 0))
        elif game.finished:
            self.pauseOverlaySurf.set_alpha(self.overlayAlpha * self.resultsFadeIn)
            screen.blit(self.pauseOverlaySurf, (0, 0))
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))
        else:
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))

        ts = self.nameSurf.get_rect()
        screen.blit(self.nameSurf, ((bounds.width - ts.width) * 0.5, bounds.height - ts.height))

        if stats.score != self.drawnScore:
            self.scoreSurf = self.renderText(str(int(stats.score)), self.bigFont, txtcolors["score"])
            self.drawnScore = stats.score

        ts = self.scoreSurf.get_rect()
        self.scoreSurf.set_alpha(uiAlpha)
        screen.blit(self.scoreSurf, ((bounds.width - ts.width) * 0.5, bounds.height - self.targetoffs * 0.5 - ts.height * 1.5))

        for hittime, timing in self.drawHits:
            a = 1 - clamp(0, 5 * (self.time - hittime) / 1000.0, 1)
            if a:
                s = self.accPreRendered[timing]
                s.set_alpha(255 * a)
                ts = s.get_rect()
                screen.blit(s, ((bounds.width - ts.width) * 0.5, bounds.height - self.targetoffs * 0.5 - ts.height * 0.5))

                scale = 1 + (1 - a) * 0.5
                s = pygame.transform.scale(s, (int(ts.width * scale), int(ts.height * scale)))
                s.set_alpha(128 * a)
                ts = s.get_rect()
                screen.blit(s, ((bounds.width - ts.width) * 0.5, bounds.height - self.targetoffs * 0.5 - ts.height * 0.5))
            else:
                self.drawHits.remove((hittime, timing))

        if stats.combo or stats.bestCombo:
            combopos = bounds.height - self.targetoffs * 0.5 + self.mediumFont.get_height() * 0.5

        if stats.combo:
            if stats.combo != self.drawnCombo:
                self.comboSurf = self.renderText("%i combo" % stats.combo, self.mediumFont, txtcolors["combo"])
                self.drawnCombo = stats.combo

            ts = self.comboSurf.get_rect()
            self.comboSurf.set_alpha(uiAlpha)
            screen.blit(self.comboSurf, ((bounds.width - ts.width) * 0.5, combopos))

        if stats.bestCombo:
            if stats.bestCombo != self.drawnBestCombo:
                self.bestComboSurf = self.renderText("%i best" % stats.bestCombo, self.smallFont, txtcolors["best-combo"])
                self.drawnBestCombo = stats.bestCombo

            ts = self.bestComboSurf.get_rect()
            self.bestComboSurf.set_alpha(uiAlpha)
            screen.blit(self.bestComboSurf, ((bounds.width - ts.width) * 0.5, combopos + self.mediumFont.get_height()))

        if game.paused:
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))
            ts = self.pausedTextSurf.get_rect()
            screen.blit(self.pausedTextSurf, ((bounds.width - ts.width) * 0.5, (bounds.height - ts.height) * 0.5))
        elif game.finished:
            self.drawResults()

        if game.autoplay:
            screen.blit(self.autoplaySurf, (0, bounds.height - self.autoplaySurf.get_rect().height))

        ts = self.fpsSurf.get_rect()
        screen.blit(self.fpsSurf, (bounds.width - ts.width, bounds.height - ts.height))

        s = self.renderText(str(int(game.time)), self.smallFont, txtcolors["time"], direct=True)
        ts = s.get_rect()
        screen.blit(s, (bounds.width - ts.width, bounds.height - ts.height * 2))

        self.time += dt
Ejemplo n.º 5
0
    def draw(self, screen):
        if self.prepareDrawNeeded or screen is not self.screen:
            self.prepareDraw(screen)

        game = self.game
        stats = game.stats
        config = self.config
        colors = config["colors"]
        txtcolors = colors["text"]
        dt = game.clock.deltaTime

        if game.finished:
            self.resultsFadeIn = approach(self.resultsFadeIn, 1.0, dt / 1250.0)
            uiAlpha = 255 * (1 - self.resultsFadeIn)
        else:
            uiAlpha = 255

        if self.time > self.updateFpsTime:
            self.fpsSurf = self.renderText("%i FPS" % game.clock.fps, self.smallFont, txtcolors["fps"], direct=True)
            self.updateFpsTime = self.time + 500

        screen.fill(colors["background"])

        bounds = screen.get_rect()
        bandWidth = self.bandWidth
        noterate = (bounds.height * game.noterate) / 1000

        if self.showTimingHints:
            self.bandAccSurf.fill((0, 0, 0, 0))
            for s in scoreinfo.values:
                toffs = (s.threshold * noterate)
                pygame.draw.rect(self.bandAccSurf, self.scoreInfoColors[s], (0, bounds.height - self.targetoffs - toffs, bandWidth, toffs * 2), 0)

        for band in self.bands:
            o = band.offset

            if band.held:
                band.flash = self.time
                flash = 1.0
            else:
                flash = 1.0 - clamp(0, (self.time - band.flash) / 1000.0, 1)

            if flash:
                pygame.draw.rect(screen, mix(colors["background"], colors["bandflash"], flash * flash), (o, 0, bandWidth, bounds.height), 0)

            if self.showTimingHints:
                screen.blit(self.bandAccSurf, (o, 0))

            pygame.draw.rect(screen, colors["bandborder"], (o, 0, bandWidth, bounds.height), 1)
            band.drawngradients = 0

        maxNoteDist = float(bounds.height - self.targetoffs)

        for note in game.beatmap:
            hitdiff  = note.hitTime - game.time + self.targetoffs / noterate
            holddiff = hitdiff

            if note.holdTime > 0:
                holddiff += note.holdTime

            if holddiff < 0 or (note.isHint and not config["show-hintnotes"]):
                continue

            if hitdiff * noterate > bounds.height + 5:
                break

            if note in game.removeNotes:
                continue

            band = game.bands[note.band]
            vband = self.bands[note.band]
            bandoffs = vband.offset
            o = bounds.height - hitdiff * noterate

            if config["acceleration"]:
                o = ((1.25 * o / bounds.height) ** 2) * bounds.height

            grad = None

            if note.isHint:
                if note.holdTime < 0:
                    clr1 = (128, 128, 200)
                else:
                    clr1 = (128, 128, 128)
                clr2 = clr1
            elif band.heldNote is note:
                if self.holdGradients:
                    grad = self.highlightGradient
                clr1 = colors["highlight"]
                clr2 = colors["highlight"]
                o = min(o, bounds.height - self.targetoffs - 5)
            else:
                if self.holdGradients:
                    grad = self.gradients[note.band][128]
                clr1 = self.notecolors[note.band]
                clr2 = self.beamcolors[note.band]

            if config["show-nearest-note"] and game.beatmap.nearest(note.band, game.time, muz.game.scoreinfo.miss.threshold) is note:
                clr1 = colors["nearest-note"]
                clr2 = colors["nearest-note"]

            if note.holdTime:
                x = bounds.height - holddiff * noterate

                if x > 0 and config["acceleration"]:
                    x = ((1.25 * x / bounds.height) ** 2) * bounds.height

                beam = pygame.Rect(bandoffs + bandWidth * 0.5 - self.holdWidth * 0.5, x, self.holdWidth, o - x + 5)

                pygame.draw.rect(screen, clr2, beam, 1 if grad else 0)

                if grad is not None:
                    h = int(beam.height)
                    if h > 0:
                        grad = pygame.transform.flip(grad, False, True)
                        grad = pygame.transform.scale(grad, (int(beam.width), h))
                        screen.blit(grad, beam)
                        vband.drawngradients += 1

                pygame.draw.rect(screen, clr1, (bandoffs, x, bandWidth, 5), 0)

            pygame.draw.rect(screen, clr1, (bandoffs, o, bandWidth, 5), 0)

            if self.noteGradients and not note.isHint:
                sz = int(bounds.height - self.targetoffs - o)
                if sz > 0:
                    s = self.gradients[note.band][int(clamp(0, (2 - vband.drawngradients * 0.5) * (o / maxNoteDist), 1) * 50.0)]
                    if s is not None:
                        s = pygame.transform.scale(s, (int(self.bandWidth), sz))
                        screen.blit(s, (bandoffs, o + 5))
                        vband.drawngradients += 1

        for band in self.bands:
            o = band.offset
            flash = 1.0 - clamp(0, 5 * (self.time - band.flash) / 1000.0, 1)

            if flash:
                self.noteHitSurf.set_alpha(255 * flash)
                screen.blit(self.noteHitSurf, (o, bounds.height - self.targetoffs - 5))

        if game.paused:
            screen.blit(self.pauseOverlaySurf, (0, 0))
        elif game.finished:
            self.pauseOverlaySurf.set_alpha(self.overlayAlpha * self.resultsFadeIn)
            screen.blit(self.pauseOverlaySurf, (0, 0))
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))
        else:
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))

        ts = self.nameSurf.get_rect()
        screen.blit(self.nameSurf, ((bounds.width - ts.width) * 0.5, bounds.height - ts.height))

        if stats.score != self.drawnScore:
            self.scoreSurf = self.renderText(str(int(stats.score)), self.bigFont, txtcolors["score"])
            self.drawnScore = stats.score

        ts = self.scoreSurf.get_rect()
        self.scoreSurf.set_alpha(uiAlpha)
        screen.blit(self.scoreSurf, ((bounds.width - ts.width) * 0.5, bounds.height - self.targetoffs * 0.5 - ts.height * 1.5))

        for hittime, timing in self.drawHits:
            a = 1 - clamp(0, 5 * (self.time - hittime) / 1000.0, 1)
            if a:
                s = self.accPreRendered[timing]
                s.set_alpha(255 * a)
                ts = s.get_rect()
                screen.blit(s, ((bounds.width - ts.width) * 0.5, bounds.height - self.targetoffs * 0.5 - ts.height * 0.5))

                scale = 1 + (1 - a) * 0.5
                s = pygame.transform.scale(s, (int(ts.width * scale), int(ts.height * scale)))
                s.set_alpha(128 * a)
                ts = s.get_rect()
                screen.blit(s, ((bounds.width - ts.width) * 0.5, bounds.height - self.targetoffs * 0.5 - ts.height * 0.5))
            else:
                self.drawHits.remove((hittime, timing))

        if stats.combo or stats.bestCombo:
            combopos = bounds.height - self.targetoffs * 0.5 + self.mediumFont.get_height() * 0.5

        if stats.combo:
            if stats.combo != self.drawnCombo:
                self.comboSurf = self.renderText("%i combo" % stats.combo, self.mediumFont, txtcolors["combo"])
                self.drawnCombo = stats.combo

            ts = self.comboSurf.get_rect()
            self.comboSurf.set_alpha(uiAlpha)
            screen.blit(self.comboSurf, ((bounds.width - ts.width) * 0.5, combopos))

        if stats.bestCombo:
            if stats.bestCombo != self.drawnBestCombo:
                self.bestComboSurf = self.renderText("%i best" % stats.bestCombo, self.smallFont, txtcolors["best-combo"])
                self.drawnBestCombo = stats.bestCombo

            ts = self.bestComboSurf.get_rect()
            self.bestComboSurf.set_alpha(uiAlpha)
            screen.blit(self.bestComboSurf, ((bounds.width - ts.width) * 0.5, combopos + self.mediumFont.get_height()))

        if game.paused:
            screen.blit(self.overlaySurf, (0, bounds.height - self.targetoffs))
            ts = self.pausedTextSurf.get_rect()
            screen.blit(self.pausedTextSurf, ((bounds.width - ts.width) * 0.5, (bounds.height - ts.height) * 0.5))
        elif game.finished:
            self.drawResults()

        if game.autoplay:
            screen.blit(self.autoplaySurf, (0, bounds.height - self.autoplaySurf.get_rect().height))

        ts = self.fpsSurf.get_rect()
        screen.blit(self.fpsSurf, (bounds.width - ts.width, bounds.height - ts.height))

        s = self.renderText(str(int(game.time)), self.smallFont, txtcolors["time"], direct=True)
        ts = s.get_rect()
        screen.blit(s, (bounds.width - ts.width, bounds.height - ts.height * 2))

        self.time += dt