def __init__(self, app, parent, universe, target=None, replay=False): ''' Called upon creation of a ViewManager object. screen is a pygame screen object. universe is the Universe object to draw. target is either a point, a PlayerSprite object, or None. If target is None, the view manager will follow the action, otherwise it will follow the specified point or player. ''' super(ViewManager, self).__init__(app) self.universe = universe self.parent = parent self.replay = replay # self._focus represents the point where the viewManager is currently # looking. if self.universe.map: self._focus = (universe.map.layout.centreX, universe.map.layout.centreY) else: self._focus = (0, 0) self._oldTargetPt = self._focus self.lastUpdateTime = timeNow() self.autoFocusInfo = (0, set(), set()) self.speed = 0 # Speed that the focus is moving. self.loadingScreen = None self.loadingPlayer = None self.pauseMessage = None self.backgroundDrawer = BackgroundDrawer(app, universe) self.sRect = None # Now fill the backdrop with what we're looking at now. self.appResized() self.setTarget(target)
def respawned(self): time = timeNow() if self.lastTimeDied is not None: self.timeDead += (time - self.lastTimeDied) self.lastTimeRespawned = time
def run_twisted(self, reactor=None): '''Runs the application using Twisted's reactor.''' if reactor is None: from twisted.internet import reactor def _stop(): if not self._running: if reactor.running: log.warning( 'stop() called twice. Terminating immediately.') reactor.stop() return self._running = False # Give time for shutdown sequence. reactor.callLater(0.3, reactor.stop) self._stop = _stop self.lastTime = self.lastFPSLog = timeNow() self.jitterLogger.noteGap() self.targetFrameInterval = 1. / TARGET_FRAME_RATE reactor.callLater(self.targetFrameInterval, self.twisted_tick, reactor) self._running = True reactor.run() pygame.display.quit() pygame.quit()
def applyOrderToLocalState(self, localState, world): now = timeNow() try: sendTime = localState.pings.pop(self.data) except KeyError: return localState.gotPingTime(now - sendTime)
def run_twisted(self, reactor=None): '''Runs the application using Twisted's reactor.''' if reactor is None: from twisted.internet import reactor def _stop(): if not self._running: if reactor.running: log.warning( 'stop() called twice. Terminating immediately.') reactor.stop() return self._running = False # Give time for shutdown sequence. reactor.callLater(0.3, reactor.stop) self._stop = _stop self.lastTime = self.lastFPSLog = timeNow() # panda stuff self.displayLoop = task.LoopingCall(self.displayStep, reactor) self.displayLoop.clock = reactor self.displayLoop.start(0) # self-limiting self._running = True reactor.run()
def _tick(self): '''Processes the events in the pygame event queue, and causes the application to be updated, then refreshes the screen. This routine is called as often as possible - it is not limited to a specific frame rate.''' if not self._running: return now = timeNow() self.ticksSinceFPSLog += 1 if LOG_FPS and now - self.lastFPSLog > 1: log.warning('%.2f FPS', self.ticksSinceFPSLog / (now - self.lastFPSLog)) self.lastFPSLog = now self.ticksSinceFPSLog = 0 # Process the events in the event queue. for event in pygame.event.get(): try: event = self.musicManager.processEvent(event) if not self._running: return if event is not None: event = self.screenManager.processEvent(event) if not self._running: return if event is not None: # Special events. if event.type == pygame.QUIT: self.stop() return except ApplicationExit: raise except Exception: log.exception('Error during Pygame event processing') if not self._running: return # Give things an opportunity to update their state. deltaT = now - self.lastTime self.lastTime = now try: self.screenManager.tick(deltaT) except ApplicationExit: raise except Exception: log.exception('Error drawing screen') if not self._running: return if pygame.display.get_active(): # Update the screen. try: self.screenManager.draw(self.screenManager.screen) except pygame.error: # Surface may have been lost (DirectDraw error) log.exception('Error in screenManager.draw()')
def updateFocus(self): '''Updates the location that the ViewManager is focused on. First calculates where it would ideally be focused, then moves the focus towards that point. The focus cannot move faster than self.maxSpeed pix/s, and will only accelerate or decelerate at self.acceleration pix/s/s. This method returns the negative of the amount scrolled by. This is useful for moving the backdrop by the right amount. ''' # Calculate where we should be looking at. if isinstance(self.target, PlayerSprite): # Take into account where the player's looking. targetPt = self.target.pos # If the player no longer exists, look wherever we want. if not self.universe.hasPlayer(self.target.player): self.setTarget(None) elif isinstance(self.target, (tuple, list)): targetPt = self.target else: targetPt = self.followAction() # Calculate time that's passed. now = timeNow() deltaT = now - self.lastUpdateTime self.lastUpdateTime = now # Calculate distance to target. self._oldTargetPt = targetPt sTarget = sum((targetPt[i] - self._focus[i])**2 for i in (0, 1))**0.5 if sTarget == 0: return (0, 0) if self.target is not None: s = sTarget else: # Calculate the maximum velocity that will result in deceleration # to reach target. This is based on v**2 = u**2 + 2as vDecel = (2. * self.acceleration * sTarget)**0.5 # Actual velocity is limited by this and maximum velocity. self.speed = min(self.maxSpeed, vDecel, self.speed + self.acceleration * deltaT) # Distance travelled should never overshoot the target. s = min(sTarget, self.speed * deltaT) # How far does the backdrop need to move by? # (This will be negative what the focus moves by.) deltaBackdrop = tuple(-s * (targetPt[i] - self._focus[i]) / sTarget for i in (0, 1)) # Calculate the new focus. self._focus = tuple( round(self._focus[i] - deltaBackdrop[i], 0) for i in (0, 1))
def toggleTerminal(self): if self.terminal is None: locs = {'app': self.app} if hasattr(self.app, 'getConsoleLocals'): locs.update(self.app.getConsoleLocals()) self.terminal = console.TrosnothInteractiveConsole( self.app, self.app.screenManager.fonts.consoleFont, Region(size=Screen(1, 0.4), bottomright=Screen(1, 1)), locals=locs) self.terminal.interact().addCallback(self._terminalQuit) from trosnoth.utils.utils import timeNow if self.terminal in self.elements: if timeNow() > self._termWaitTime: self.elements.remove(self.terminal) else: self._termWaitTime = timeNow() + 0.1 self.elements.append(self.terminal) self.setFocus(self.terminal)
def gotTick(self): now = timeNow() if self.ignoreUntil is not None: if now > self.ignoreUntil: self.reset() else: return self.ticks.append(now) limit = now - self.TIME_SPAN while self.ticks[0] < limit: self.ticks.pop(0)
def notePeriod(self): ''' Called periodically to allow the analyser to notice if the reactor is not running smoothly. ''' now = timeNow() if self.lastNote is None: self.lastNote = now return period = now - self.lastNote self.lastNote = now if period - self.NOTE_TIME >= self.NOTE_TIME: # Reactor congestion: reset tally self.ignoreUntil = now + self.NOTE_TIME
def died(self, killer, deathType): self.deaths += 1 self.playerDeaths[killer] += 1 time = timeNow() self._updateStreaks(True) self.lastTimeDied = time if self.timeAlive >= 1000: self.sendAchievementProgress('totalAliveTime') if self.timeAlive >= 300 and self.timeAlive >= (self.timeAlive + self.timeDead) * 0.75: self.sendAchievementProgress('stayingAlive')
def observation(self, expectedTime, resume=False): if resume: self.noteGap() now = timeNow() if self.lastTime: value = now - self.lastTime - expectedTime self.thisMax = max(self.thisMax, value) self.thisCount += 1 if self.thisCount >= self.cycle: self.jitter = self.thisMax self.thisCount = 0 self.thisMax = 0 self.lastTime = now
def run(self): '''Runs the application.''' def _stop(): self._running = False raise ApplicationExit self._stop = _stop self._running = True self.lastTime = self.lastFPSLog = timeNow() while self._running: try: self.tick() self.doFlip() except ApplicationExit: break pygame.quit()
def __init__(self, game): self.game = game self.world = world = game.world self.lastSave = timeNow() # All players recorded this game, indexed by user id. self.allPlayers = {} defs = self.achievementDefs self.oncePerGameAchievements = [c(world) for c in defs.oncePerGame] self.oncePerTeamPerGameAchievements = [ c(world, team) for c in defs.oncePerTeamPerGame for team in world.teams ] self.loop = WeakLoopingCall(self, 'save') self.started = False self.stopped = False
def verify(self): ''' If more than GAME_VERIFY_TIME has passed since the last verification, connects to the game to check whether it is still running. Returns a deferred whose callback will be executed with True or False depending on whether the game is still running. ''' t = timeNow() if t - self.lastVerified < GAME_VERIFY_TIME: defer.returnValue(self.running) return self.lastVerified = t try: yield ClientCreator(reactor, Protocol).connectTCP(self.host, self.port, timeout=5) except ConnectError: self.running = False defer.returnValue(False) return self.running = True defer.returnValue(True)
def _updateStreaks(self, updateAlive): ''' updateAlive will be set to True in three situations: 1. if the player has just died 2. if the player was alive when the game ended 3. if the player was alive when they disconnected ''' self.killStreak = max(self.killStreak, self.currentKillStreak) self.tagStreak = max(self.tagStreak, self.currentTagStreak) time = timeNow() if updateAlive and self.lastTimeRespawned: lastLife = time - self.lastTimeRespawned self.aliveStreak = max(self.aliveStreak, lastLife) self.timeAlive += lastLife if lastLife >= 180: self.sendAchievementProgress('aliveStreak') elif self.lastTimeDied is not None: self.timeDead += time - self.lastTimeDied self.currentKillStreak = 0 self.currentTagStreak = 0
def reset(self): self.startTime = timeNow() self.ticks = [self.startTime]
def applyRequestToLocalState(self, localState): localState.pings[self.data] = timeNow()