def __init__(self, GAME, floorConfig=None, loop=True, cartridgeReader=False, init=True): self.cartridgeReader = cartridgeReader self.loop = loop self.wait = time.sleep if floorConfig is None: conf = LSFloorConfig() conf.selectConfig() else: conf = LSFloorConfig(floorConfig) if conf.containsVirtual() is True: self.REAL_FLOOR = False else: self.REAL_FLOOR = True self.audio = LSAudio(initSound=init) self.display = LSDisplay(conf=conf, eventCallback = self.handleTileStepEvent, initScreen=init) self.ROWS = conf.rows self.COLUMNS = conf.cols os.system('cls' if os.name == 'nt' else 'clear') print("Board size is {:d}x{:d}".format(self.ROWS, self.COLUMNS)) self.GAME = GAME self.moves = [] self.sensorMatrix = defaultdict(lambda: defaultdict(int)) self.currentGame = None self.newGame(self.GAME) #these are for bookkeeping self.frames = 0 self.frameRenderTime = 0 # This lock prevents handleTileStepEvent() from being run by polling loops before init is complete self.initLock.set()
class LSGameEngine(): initLock = threading.Event() SIMULATED_FLOOR = True CONSOLE = False numPlays = numLoops = 0 _warnings = [] def __init__(self, GAME, floorConfig=None, loop=True, cartridgeReader=False, init=True): self.cartridgeReader = cartridgeReader self.loop = loop self.wait = time.sleep if floorConfig is None: conf = LSFloorConfig() conf.selectConfig() else: conf = LSFloorConfig(floorConfig) if conf.containsVirtual() is True: self.REAL_FLOOR = False else: self.REAL_FLOOR = True self.audio = LSAudio(initSound=init) self.display = LSDisplay(conf=conf, eventCallback = self.handleTileStepEvent, initScreen=init) self.ROWS = conf.rows self.COLUMNS = conf.cols os.system('cls' if os.name == 'nt' else 'clear') print("Board size is {:d}x{:d}".format(self.ROWS, self.COLUMNS)) self.GAME = GAME self.moves = [] self.sensorMatrix = defaultdict(lambda: defaultdict(int)) self.currentGame = None self.newGame(self.GAME) #these are for bookkeeping self.frames = 0 self.frameRenderTime = 0 # This lock prevents handleTileStepEvent() from being run by polling loops before init is complete self.initLock.set() def newGame(self, Game): self.lastGame = self.currentGame try: # Game is a list of game classes, pick one at random GAME = random.choice(Game) except: # Game was specified GAME = Game self.currentGame = GAME.__name__ print("LSGameEngine: Starting {:s}...".format(self.currentGame)) self.game = GAME(self.display, self.audio, self.ROWS, self.COLUMNS, self.cartridgeReader) self.startGame = time.time() self.game.sensors = self.sensorMatrix self.numLoops += 1 if not isinstance(self.game, LSScreenSaver): self.numPlays += 1 try: self.game.init() except AttributeError as e: # raise(e) # Debugging self._warnOnce("{:s} has no init() method.".format(self.currentGame)) def beginLoop(self, plays = 0): self.fpsLog = dict() while True: if plays is not 0 and self.numPlays <= plays: self.enterFrame() elif plays is 0: self.enterFrame() else: self.insertCoin() def insertCoin(self): self.gameOver() # TODO: Instead of quitting, go to game/demo screen and wait for someone to reset def gameOver(self): print(" G A M E O V E R ") self.display.clearAll() self.display.setMessage(int(self.display.rows/2)-1,"GAME", start=int(self.display.cols/2)-2) self.display.setMessage(int(self.display.rows/2), "OVER", start=int(self.display.cols/2)-2) self.display.heartbeat() input("--Press any key to exit--\n") # self.display.floor.saveAndExit(0) def handleTileStepEvent(self, row, col, sensorPcnt): self.initLock.wait() if int(sensorPcnt) is 0: try: self.game.stepOff(row, col) except AttributeError as e: # Game has no stepOff() method if "object has no attribute 'stepOff'" in str(e): self._warnOnce("{:s} has no stepOff() method.".format(self.currentGame)) else: raise(e) # print("stepOff: ({:d},{:d})".format(row, col)) # Debugging self.moves = [x for x in self.moves if x[0] is not row and x[1] is not col] else: if self.sensorMatrix[row][col] is 0: if sensorPcnt > _SENSOR_THRESHOLD:# Only trigger > n%, hack to guard against phantom sensors # TODO: This but better # if sensorPcnt > 0: try: self.game.stepOn(row, col) except AttributeError as e: # Game has no stepOn() method if "object has no attribute 'stepOn'" in str(e): self._warnOnce("{:s} has no stepOn() method.".format(self.currentGame)) else: raise(e) # print("stepOn: ({:d},{:d})".format(row, col)) # Debugging m = (row, col) self.moves.append(m) self.sensorMatrix[row][col] = int(sensorPcnt) def pauseGame (self): print("Game is paused.") while self.game.frameRate < 1: pass print("Game resuming...") def enterFrame(self): if self.game.duration is not 0: playTime = (time.time() - self.startGame) if playTime > self.game.duration: self.newGame(self.GAME) startEnterFrame = time.time() if not self.game.ended: self.game.heartbeat(self.moves) self.display.heartbeat() # self.audio.heartbeat() else: self.newGame(SAVERS) # Super hacky, should be in gameOver # self.newGame(self.GAME) frameRenderTime = (time.time() - startEnterFrame) self.wait(self.padFrame(frameRenderTime)) def padFrame(self, renderTime): if self.game.frameRate is 0: self.pauseGame() spaces = " " * (52) fps = 1.0/renderTime fpsEntry = int(fps) if fps < self.game.frameRate else int(self.game.frameRate) if self.numLoops in self.fpsLog.keys(): self.fpsLog[self.numLoops].append(fpsEntry) else: if self.numLoops > 1: try: data = self.fpsLog[self.numLoops-1] avg = int(sum(data)/len(data)) mod = max(set(data), key=data.count) mrg = int(min(data) + max(data)/2) # print(data) # Debugging del(data) print("\nStats for: {:s}".format(self.lastGame)) statsString=" FrameRate: (average: {:d}fps) (mode: {:d}fps) (midrange: {:d}fps)" print(statsString.format(avg, mod, mrg)) print("") except KeyError: pass self.fpsLog[self.numLoops] = [fpsEntry] if fps < self.game.frameRate or self.game.frameRate < 0: print("{1:s}{0:.4f} FPS".format(1.0/renderTime, spaces), end="\r") return(0) else: print("{1:s}{0:.4f} FPS".format(self.game.frameRate, spaces), end="\r") return((1.0/self.game.frameRate)-renderTime) print(spaces * 2, end="\r") def _warnOnce(self, warning): if warning not in self._warnings: print("WARNING: {:s}".format(warning)) self._warnings.append(warning)