def update(self): dt = self.clock.deltaTime if self.aggressiveUpdate: while dt > 0: s = clamp(0, self.aggressiveUpdateStep, dt) dt -= s self._update(s) else: self._update(dt)
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
def drawGame(self, win, ofsx, ofsy, width, height): game = self.game targetoffs = height * 0.33 noterate = (height * game.noterate) / 1000 targetoffsline = int(ofsy + height - targetoffs) border = curses.color_pair(curses.COLOR_BLACK + 1) | curses.A_BOLD win.attron(border) win.hline(targetoffsline, ofsx, ord('.'), width) win.attroff(border) bandwidth = int(width / game.beatmap.numbands) holdwidth = bandwidth - 2 for note in game.beatmap: hitdiff = note.hitTime - game.time + targetoffs / noterate holddiff = hitdiff + note.holdTime if holddiff < 0: continue if hitdiff * noterate > height: break if note in game.removeNotes: continue band = game.bands[note.band] vband = self.bands[note.band] o = clamp(ofsy, int(height - hitdiff * noterate), height) nc = curses.color_pair(vband.color) if band.heldNote is note: o = min(o, targetoffsline) win.attron(nc) if note is band.heldNote: win.attron(curses.A_BOLD) if note.holdTime: x = int(height - holddiff * noterate) bx = max(ofsy, x) beam = (2, bx, bandwidth - 3, o - bx) for lnum in xrange(beam[2]): win.vline(beam[1], note.band * bandwidth + beam[0] + lnum, ord('.'), beam[3]) if x >= ofsy: win.hline(x, note.band * bandwidth, ord('#'), bandwidth) win.hline(o, note.band * bandwidth, ord('#'), bandwidth) win.attroff(nc | curses.A_BOLD) for i, band in enumerate(self.bands): if band.held: band.flash = self.time win.attron(border) win.vline(ofsy, (i + 1) * bandwidth, ord(':'), height + 1) win.attroff(border) bc = curses.color_pair(band.color) win.attron(bc) if self.time - band.flash < 100: for j in xrange(bandwidth - 1): if j % 2: win.vline(targetoffsline + 1, 1 + j + i * bandwidth, ord('.'), height - targetoffsline + 1) win.attroff(bc)
def _update(self, dt): if self.paused: return if self.needRestart or self.loopLimit and self.time > self.timeOffset + self.loopLimit: self.needRestart = False self.resetScore() self.start() for s in self.soundplayed: self.soundplayed[s] = False for note in self.removeNotes: try: self.beatmap.remove(note) except Exception: # wtf? log.debug("removing a note failed, wtf?", exc_info=True) del self.removeNotes[:] for note in self.beatmap: d = note.hitTime + note.holdTime - self.time if self.autoplay: if d - note.holdTime <= 0 and self.bands[note.band].heldNote is not note: self.registerHit(self.bands[note.band]) if not note.holdTime: self.registerRelease(self.bands[note.band]) if d <= 0 and self.bands[note.band].heldNote is note: self.registerRelease(self.bands[note.band]) if d - note.holdTime > 0: break if d < -muz.game.scoreinfo.bad.threshold or (d < 0 and note is not self.beatmap.nearest(note.band, self.time, muz.game.scoreinfo.miss.threshold)): #if d < -muz.game.scoreinfo.miss.threshold: self.registerMiss(note, abs(d)) _time = self.time mtime = self.music.position if mtime >= 0: mtime += self.timeOffset if mtime < 0: self.time += dt if not self.finished: self.renderer.gameFinished() self.finished = True elif mtime < 300: self.time = self.lastmtime = mtime elif self.timeSyncAccumulator >= 500: log.debug("forced time sync") self.lastmtime = mtime self.time = mtime self.timeSyncAccumulator = 0 elif mtime == self.lastmtime and config["interpolate-music-time"]: if dt: log.debug("playback pos didn't update fast enough, interpolating time (%i ms)", dt) self.time += dt self.timeSyncAccumulator += dt elif mtime < self.lastmtime: log.debug("music time jumped backwards (%i ms)", mtime - self.lastmtime) self.time = self.lastmtime = self.lastmtime + dt self.timeSyncAccumulator += dt elif mtime > self.oldTime + dt * 2: log.debug("music time jumped forwards (%i ms)", mtime - self.lastmtime) self.time = self.lastmtime = self.lastmtime + dt self.timeSyncAccumulator += dt else: self.lastmtime = mtime self.time = mtime self.timeSyncAccumulator = 0 if int(self.time) < int(self.oldTime): log.debug("time stepped backwards (%i ms)", (self.time - self.oldTime)) d = float(self.time - (_time + dt)) self.time = _time + dt + d * (dt / 1000.0) deltatime = self.time - self.oldTime self._noterate = clamp(0, self._noterate + (self.defaultNoterate + self.stats.combo * self.noteratePerCombo - self._noterate) * (deltatime / 1000.0) * self.noterateGain, self.maxNoterate) self.oldTime = self.time if self.justStarted: del self.removeNotes[:] self.justStarted = False
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
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
def _update(self, dt): if self.paused: return if self.needRestart or self.loopLimit and self.time > self.timeOffset + self.loopLimit: self.needRestart = False self.resetScore() self.start() for s in self.soundplayed: self.soundplayed[s] = False for note in self.removeNotes: try: self.beatmap.remove(note) except Exception: # wtf? log.debug("removing a note failed, wtf?", exc_info=True) del self.removeNotes[:] for note in self.beatmap: d = note.hitTime + note.holdTime - self.time if self.autoplay: if d - note.holdTime <= 0 and self.bands[ note.band].heldNote is not note: self.registerHit(self.bands[note.band]) if not note.holdTime: self.registerRelease(self.bands[note.band]) if d <= 0 and self.bands[note.band].heldNote is note: self.registerRelease(self.bands[note.band]) if d - note.holdTime > 0: break if d < -muz.game.scoreinfo.bad.threshold or ( d < 0 and note is not self.beatmap.nearest( note.band, self.time, muz.game.scoreinfo.miss.threshold)): #if d < -muz.game.scoreinfo.miss.threshold: self.registerMiss(note, abs(d)) _time = self.time mtime = self.music.position if mtime >= 0: mtime += self.timeOffset if mtime < 0: self.time += dt if not self.finished: self.renderer.gameFinished() self.finished = True elif mtime < 300: self.time = self.lastmtime = mtime elif self.timeSyncAccumulator >= 500: log.debug("forced time sync") self.lastmtime = mtime self.time = mtime self.timeSyncAccumulator = 0 elif mtime == self.lastmtime and config["interpolate-music-time"]: if dt: log.debug( "playback pos didn't update fast enough, interpolating time (%i ms)", dt) self.time += dt self.timeSyncAccumulator += dt elif mtime < self.lastmtime: log.debug("music time jumped backwards (%i ms)", mtime - self.lastmtime) self.time = self.lastmtime = self.lastmtime + dt self.timeSyncAccumulator += dt elif mtime > self.oldTime + dt * 2: log.debug("music time jumped forwards (%i ms)", mtime - self.lastmtime) self.time = self.lastmtime = self.lastmtime + dt self.timeSyncAccumulator += dt else: self.lastmtime = mtime self.time = mtime self.timeSyncAccumulator = 0 if int(self.time) < int(self.oldTime): log.debug("time stepped backwards (%i ms)", (self.time - self.oldTime)) d = float(self.time - (_time + dt)) self.time = _time + dt + d * (dt / 1000.0) deltatime = self.time - self.oldTime self._noterate = clamp( 0, self._noterate + (self.defaultNoterate + self.stats.combo * self.noteratePerCombo - self._noterate) * (deltatime / 1000.0) * self.noterateGain, self.maxNoterate) self.oldTime = self.time if self.justStarted: del self.removeNotes[:] self.justStarted = False