class Frogger(QWidget): def __init__(self): super().__init__() Config.mainWindow = self #odma se postavi koji objekat je mainWindow da bi tamo u Rectangle.py Qlabeli znali gde treba da se nacrtaju. Lose je resenje, al radi bar za testiranje self.Menu = None # glavni meni self.InitFlagsAndVariables() self.scoreboard = Scoreboard(self) self.highscore = HighScore() self.highscore.readFromFile() ############################################### self.videoWidget = QVideoWidget(self) self.videoWidget.resize(Config.mapSize * Config.gridSize, Config.mapSize * Config.gridSize + 50) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.setMedia( QMediaContent(QUrl(Config.spriteLocation + "Intro.wmv"))) ############################################### self.setWindowState(Qt.WindowNoState) self.__init_ui__() self.key_notifier = KeyNotifier() self.key_notifier.key_signal.connect(self.__update_position__) self.key_notifier.start() self.ZevsJavljaVremeQueue = Queue() self.procUKomZiviZevs = Zeus.PokreniZevsa( self.ZevsJavljaVremeQueue ) #pokrece proces koji u kju stavlja kakvo vreme treba da bude (sunce, kisa, sneg) def InitFlagsAndVariables(self): self.Map = [] # lista lejnova self.previousWeather = 'n' self.player1 = None self.player2 = None self.player1RectId = -1 # ovo je potrebno za mrezu self.player2RectId = -1 # ovo je potrebno za mrezu self.gamePaused = False self.GameOverBrojac = 0 # za zivote, ako je 2PlayerMode, kad igrac izgubi sve zivote povecava brojac za 1, kad oba izgube sve zivote, brojac je 2 i tad je gameOver # ako je SinglePlayer mod onda je gameOver ako je brojac 1 self.Level = 1 # za levele Config.p1Score = 0 Config.p2Score = 0 Config.p1Lives = 5 Config.p2Lives = 5 try: self.ShutDownHost() except: pass try: self.ShutDownClient() except: pass self.host = None self.client = None self.isHost = False self.isClient = False def initVideo(self): self.videoWidget.show() self.mediaPlayer.play() def __init_ui__(self): self.setWindowTitle('Frogger') self.setWindowIcon(QtGui.QIcon(Config.spriteLocation + 'iconFrog.png')) #ikonica self.resize(Config.mapSize * Config.gridSize, Config.mapSize * Config.gridSize + 50) self.FixWindowSize() self.show() self.initVideo() q = QTimer() q.singleShot(6000, self.DisplayMainMenu) def HsFunkc(self): self.Menu.HsElementsShow(self.highscore.top3) #obicna funkcija za fiksiranje velicine prozora def FixWindowSize(self): self.setMinimumHeight((Config.mapSize + 1) * Config.gridSize) self.setMinimumWidth(Config.mapSize * Config.gridSize) self.setMaximumHeight((Config.mapSize + 1) * Config.gridSize) self.setMaximumWidth(Config.mapSize * Config.gridSize) def RemoveVideoIntro(self): try: self.mediaPlayer.stop() self.videoWidget.setParent(None) self.videoWidget = None except: pass def DisplayMainMenu(self): self.RemoveVideoIntro() self.Menu = None self.Menu = Meni(self, self.SinglePlayerMode, self.TwoPlayerMode, self.HsFunkc, self.MainMenuHostClick, self.MainMenuJoinClick, self.CloseWindow) def PauseGame(self): self.gamePaused = True self.updaterGameObjekataThread.PauseGame() def ResumeGame(self): self.gamePaused = False self.updaterGameObjekataThread.ResumeGame() def RemoveAllGameUIObjects(self): for lejer, lista in Rectangle.allRectangles.items(): for rect in lista: rect.RemoveFromScreen() GameObject.allGameObjects = [] Rectangle.allRectangles = {} Rectangle.ResetId() def SinglePlayerMode(self): self.ClearZeusQueue() self.Menu.HideMainMenu() self.DisplayMap( ) #u displayMap se kreira objekat self.updaterGameObjekataThread i zato DisplayMap mora ici prvi self.createThreadToUpdateGameObjects() self.startThreadForUpdatingGameObjects() self.scoreboard.ShowScore() self.CreatePlayers() Config.collectLilypadsToAdvanceLevel = 1 def ClearZeusQueue(self): while not self.ZevsJavljaVremeQueue.empty(): self.ZevsJavljaVremeQueue.get() def TwoPlayerMode(self, OverNetworkGame=False): self.ClearZeusQueue() self.Menu.HideMainMenu() if not OverNetworkGame: #kad je preko mreze onda updateovanje krece kad klijent bude spreman self.createThreadToUpdateGameObjects() self.startThreadForUpdatingGameObjects() self.DisplayMap(TwoPlayers=True) self.scoreboard.ShowScores() self.CreatePlayers(TwoPlayers=True) Config.collectLilypadsToAdvanceLevel = 3 def MainMenuHostClick(self): self.HostServer(Config.serverAddress, Config.serverPort) def MainMenuJoinClick(self): #self.Menu.JoinWidgetHide() self.setFocus() #ovde sacuvamo ip adresu i port u fajl. da kad se sledeci put upali igra da odma ucita tu ipadresu i port try: with open(Config.lastIp_filename, "w") as f: f.write(str(self.Menu.ipAddr) + ":" + str(self.Menu.port)) except: pass self.JoinServer(self.Menu.ipAddr, int(self.Menu.port)) def CreatePlayers(self, TwoPlayers=False): self.player1 = Frog(Config.player1StartPosition[0], Config.player1StartPosition[1], self.GameOverCheck, self.updateP1Score, self.createGreenLives) self.player1RectId = self.player1.id if TwoPlayers: self.player2 = Frog(Config.player2StartPosition[0], Config.player2StartPosition[1], self.GameOverCheck, self.updateP2Score, self.createPinkLives, isPlayerTwo=True) self.player2RectId = self.player2.id def updateP1Score(self, newScore): self.scoreboard.updateP1Score(newScore) if self.isHost: self.host.SendToClient(Config.network_updateGameScoreAndLives + ":" + "P1S_" + str(newScore)) #P2L => Player 2 Lives def updateP2Score(self, newScore): self.scoreboard.updateP2Score(newScore) if self.isHost: self.host.SendToClient(Config.network_updateGameScoreAndLives + ":" + "P2S_" + str(newScore)) #P2L => Player 2 Lives def createPinkLives(self, lives): self.scoreboard.CreatePinkLives(lives) if self.isHost: self.host.SendToClient(Config.network_updateGameScoreAndLives + ":" + "P2L_" + str(lives)) #P2L => Player 2 Lives def createGreenLives(self, lives): self.scoreboard.CreateGreenLives(lives) if self.isHost: self.host.SendToClient(Config.network_updateGameScoreAndLives + ":" + "P1L_" + str(lives)) #P1L => Player 2 Lives def DisplayMap(self, TwoPlayers=False): self.Map.append(Lane.GenerateSafetyLane()) #prvi je uvek sejf lejn self.GenerateLanes('Road') #fja da generise lejnove za put #self.Map.append(Lane.GenerateSafetyLane()) ##ovaj ce da bude uvek tu da bi se moglo duze igrati ##lejn sa zivotom self.Map.append(Lane.GenerateSafetyLaneWithDeus()) self.GenerateLanes('Water') #fja da generise lejnove za reku if TwoPlayers: self.Map.append(Lane.GenerateFinalLane( self.LevelPassed)) # zadnji je uvek finalLane else: self.Map.append( Lane.GenerateFinalLane( self.LevelPassed, lilyPadPattern=Config.lilypadPatternBO5Standard) ) # zadnji je uvek finalLane def GameOverCheck(self, isPlayerTwo): #fja koja se poziva kada igrac ima 0 zivota, prosledjuje se igracima kroz konstruktor self.GameOverBrojac += 1 if self.player1 != None and self.player2 != None: if self.GameOverBrojac == 1: if isPlayerTwo: self.highscore.checkIfHighScore(self.player2.playerName, self.player2.score) self.player2.RemoveFromScreen() self.player2 = None Config.p2Lives = 0 else: self.highscore.checkIfHighScore(self.player1.playerName, self.player1.score) self.player1.RemoveFromScreen() self.player1 = None Config.p1Lives = 0 elif self.player1 != None: self.highscore.checkIfHighScore(self.player1.playerName, self.player1.score) self.GameOver() elif self.player2 != None: self.highscore.checkIfHighScore(self.player2.playerName, self.player2.score) self.GameOver() def GameOver(self): # javimo klijentu da bi se vratio na meni if self.isHost: self.host.SendToClient(Config.network_ConnectionError) #fja koja se poziva kad su svi igraci igraci ostali bez zivota self.stopThreadForUpdatingObjects() self.DeleteMap(deleteP1=True, deleteP2=True) self.Menu.ShowMainMenu() Lane.ResetLaneStartingIndex() self.scoreboard.HideScores() self.Menu.kisa.hide() self.Menu.sneg.hide() self.scoreboard.CreateGreenLives(0) self.scoreboard.CreatePinkLives(0) self.InitFlagsAndVariables() def ShutDownHost(self): if self.host != None: print("gasim hosta") self.host.StopHosting() self.isHost = False self.host = None def ShutDownClient(self): if self.client != None: self.client.StopClienting() self.isClient = False self.client = None def LevelPassed(self): #fja koja se poziva kad su svih 5 Lilypada popunjena, prosledjuje se u konstruktoru, prvo finalLejnu pa samim objektima self.Level += 1 Lane.ResetLaneStartingIndex() self.GameOverBrojac = 0 self.DeleteMap() if self.player1 != None and self.player2 != None: Config.p1Score = self.player1.score Config.p2Score = self.player2.score Config.p1Lives = self.player1.lives Config.p2Lives = self.player2.lives self.DisplayMap(TwoPlayers=True) self.CreatePlayers(TwoPlayers=True) elif self.player1 != None: Config.p1Score = self.player1.score Config.p1Lives = self.player1.lives self.DisplayMap() self.CreatePlayers() elif self.player2 != None: Config.p2Score = self.player2.score Config.p2Lives = self.player2.lives self.DisplayMap() self.CreatePlayers(TwoPlayers=True) self.player1.RemoveFromScreen() self.player1 = None if self.isHost and self.player2 != None: self.SendClientToReplicateObjects() def DeleteMap(self, deleteP1=False, deleteP2=False): if deleteP1: try: self.player1.RemoveFromScreen() self.player1 = None except: print('P1 vec postavljen na None') if deleteP2: try: self.player2.RemoveFromScreen() self.player2 = None except: print('P2 vec postavljen na None') for lane in self.Map: for obs in lane.obstacles: obs.RemoveFromScreen() lane.obstacles.clear() lane.RemoveFromScreen() for layer, listOfRectanglesInLayer in Rectangle.allRectangles.items(): for rect in listOfRectanglesInLayer: rect.RemoveFromScreen() listOfRectanglesInLayer.clear() self.Map.clear() def DisplayTestMap(self): Lane.ResetLaneStartingIndex() self.Map.append(Lane.GenerateSafetyLane()) self.Map.append(Lane.GenerateEasyLane()) self.Map.append(Lane.GenerateEasyLane()) self.Map.append(Lane.GenerateEasyLane()) self.Map.append(Lane.GenerateSafetyLane()) self.Map.append(Lane.GenerateFinalLane()) self.Map.append( Lane.GenerateFinalLane(lilyPadPattern=Config.lilypadPatternBO3)) self.Map.append( Lane.GenerateFinalLane(lilyPadPattern=Config.lilypadPatternBO5V2)) self.Map.append(Lane.GenerateFinalLane(randomPatternBO5=True)) def keyPressEvent(self, event): if not event.isAutoRepeat(): self.key_notifier.add_key(event.key()) def __update_position__(self, key): if not self.isClient: if key == Qt.Key_Escape and self.gamePaused: self.ResumeGame() elif key == Qt.Key_Escape and not self.gamePaused: self.PauseGame() if self.isClient: #ako sam klijent onda pored pomeranja zabe, hocu da posaljem INPUT serveru if key == Qt.Key_Right: self.client.SendToServer(Config.network_inputKlijentaPrefix + "DESNO") elif key == Qt.Key_Down: self.client.SendToServer(Config.network_inputKlijentaPrefix + "DOLE") elif key == Qt.Key_Up: self.client.SendToServer(Config.network_inputKlijentaPrefix + "GORE") elif key == Qt.Key_Left: self.client.SendToServer(Config.network_inputKlijentaPrefix + "LEVO") if key == Qt.Key_T: for go in GameObject.allGameObjects: print(str(go.id) + "__" + str(go.loadedSprite)) if self.gamePaused: #sve sto je ispod nece biti odradjeno kad je game pauziran return if self.player1 != None: self.player1.KeyPress(key) if self.player2 != None: self.player2.KeyPress(key) def CloseWindow(self): # OVDE TREBA DA SE POZOVE KOD KOJI CE DA ZAUSTAVI ZEVSA # (ako uopste postoji neko toliko jak da zaustavi zevsa) try: self.procUKomZiviZevs.terminate() except: pass try: self.updaterGameObjekataThread.updaterThreadWork = False # self.updaterGameObjekataThread se kreira samo kad pocne IGRA. Ako budes na meniju i nista ne radis nece se kreirati except: pass self.key_notifier.die() def closeEvent(self, event): self.CloseWindow() def createThreadToUpdateGameObjects(self): self.updaterGameObjekataThread = GOUpdater() self.updaterGameObjekataThread.nekiObjekat.connect( self.updateAllGameObjects) #OVO (thread koji updateuje objekte) SE POKRECE KAD KLIJENT BUDE SPREMAN (nakon sto preuzme sve objekte i nacrta ih na ekranu), ili kad pocne neki od lokalnih game modova #self.updaterGameObjekataThread.start() def startThreadForUpdatingGameObjects(self): self.updaterGameObjekataThread.start() def stopThreadForUpdatingObjects(self): try: #na klijentu ovaj objekat za updateovanje ce biti null self.updaterGameObjekataThread.updaterThreadWork = False except: pass def updateAllGameObjects(self, dummy): #callback funkcija for gameObject in GameObject.allGameObjects: gameObject.update() # ako je instanca server i postoje gameobjekti onda da salje klijentu pozicije tih objekata if self.isHost and len(GameObject.allGameObjects) > 0: self.SendRectPositionUpdateToClient() if not self.ZevsJavljaVremeQueue.empty(): self.updateWeather(self.ZevsJavljaVremeQueue.get()) else: return def updateWeather(self, newWeather): if self.isHost: self.host.SendToClient(Config.network_updateWeatherInfo + ":" + newWeather) if newWeather == 'k': if self.previousWeather == 'k': self.ZaustaviKisu() elif self.previousWeather == 's': self.ZaustaviSneg() self.PokreniKisu() elif newWeather == 's': if self.previousWeather == 'k': self.ZaustaviKisu() elif self.previousWeather == 's': self.ZaustaviSneg() self.PokreniSneg() elif newWeather == 'n': if self.previousWeather == 'k': self.ZaustaviKisu() elif self.previousWeather == 's': self.ZaustaviSneg() self.previousWeather = newWeather def createLanes(self, niz, type): #funkcija koja generise lejnove u zavisnosti od prosledjenog niza i karaktera u njemu if type == 'Road': for letter in niz: if letter == 'e': self.Map.append(Lane.GenerateEasyLane()) elif letter == 'm': self.Map.append(Lane.GenerateMediumLane()) elif letter == 'h': self.Map.append(Lane.GenerateHardLane()) elif type == 'Water': for letter in niz: if letter == 'e': self.Map.append(Lane.GenerateEasyWaterLane()) elif letter == 'm': self.Map.append(Lane.GenerateMediumWaterLane()) elif letter == 'h': self.Map.append(Lane.GenerateHardWaterLane()) elif type == 'Random': for letter in niz: if letter == 's': # safe lane self.Map.append(Lane.GenerateSafetyLane()) elif letter == 'e': # easy lane, if generated -1 -> easyWaterLane if 1 easyTrafficLane, isto vazi za ostale samo se menja tezina s,m,h... if [-1, 1][randrange(2)] == -1: self.Map.append(Lane.GenerateEasyWaterLane()) else: self.Map.append(Lane.GenerateEasyLane()) elif letter == 'm': if [-1, 1][randrange(2)] == -1: self.Map.append(Lane.GenerateMediumWaterLane()) else: self.Map.append(Lane.GenerateMediumLane()) elif letter == 'h': if [-1, 1][randrange(2)] == -1: self.Map.append(Lane.GenerateHardWaterLane()) else: self.Map.append(Lane.GenerateHardLane()) def GenerateLanes(self, type): # 6 lejnova, fja u kojoj se odlucuje tezina po levelima, moze da se menja po volji nizTezine = [] if self.Level <= 2: nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') elif self.Level > 2 and self.Level <= 4: nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') type = 'Random' elif self.Level > 4 and self.Level <= 6: nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') elif self.Level > 6 and self.Level <= 8: nizTezine.append('e') nizTezine.append('e') nizTezine.append('e') nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') type = 'Random' elif self.Level > 8 and self.Level <= 10: nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') elif self.Level > 10 and self.Level <= 12: nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') type = 'Random' elif self.Level > 12 and self.Level <= 14: nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') elif self.Level > 12 and self.Level <= 14: nizTezine.append('m') nizTezine.append('m') nizTezine.append('m') nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') type = 'Random' elif self.Level > 14 and self.Level <= 16: nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') elif self.Level > 16: nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') nizTezine.append('h') type = 'Random' shuffle(nizTezine) #permutuj niz da lejnovi budu random self.createLanes(nizTezine, type) def PokreniKisu(self): #Fja da se prikaze kisa self.Menu.PrikaziPadavinu('kisa') for lane in self.Map: if lane.laneType == Config.laneTypeWater: lane.ChangeSpeed( Config.speedChange) #brzina drveca se povecava kad je kisa elif lane.laneType == Config.laneTypeTraffic or lane.laneType == Config.laneTypeTrafficTop or lane.laneType == Config.laneTypeTrafficBottom: lane.ChangeSpeed(-Config.speedChange ) #brzina automobila se smanjuje kad je kisa def PokreniSneg(self): #Fja da se prikaze sneg self.Menu.PrikaziPadavinu('sneg') for lane in self.Map: if lane.laneType == Config.laneTypeWater: lane.ChangeSpeed(-Config.speedChange ) #brzina drveca se smanjuje kad je sneg elif lane.laneType == Config.laneTypeTraffic or lane.laneType == Config.laneTypeTrafficTop or lane.laneType == Config.laneTypeTrafficBottom: lane.ChangeSpeed(Config.speedChange ) #brzina automobila se povecava kad je sneg def ZaustaviKisu(self): #Fja da se zaustavi kisa self.Menu.SakrijPadavinu('kisa') for lane in self.Map: if lane.laneType == Config.laneTypeWater: lane.ChangeSpeed( -Config.speedChange ) #obrnuto, ako smo bili povecali brzinu drveca kad je kisa pocela, sad je smanjujemo, vracamo na default elif lane.laneType == Config.laneTypeTraffic or lane.laneType == Config.laneTypeTrafficTop or lane.laneType == Config.laneTypeTrafficBottom: lane.ChangeSpeed( Config.speedChange ) #obrnuto, ako smo bili smanjili brzinu automobila kad je kisa pocela, sad je povecavamo, vracamo na default def ZaustaviSneg(self): #Fja da se zaustavi sneg self.Menu.SakrijPadavinu('sneg') for lane in self.Map: if lane.laneType == Config.laneTypeWater: lane.ChangeSpeed( Config.speedChange ) #obrnuto, ako smo bili smanjili brzinu drveca kad je poceo sneg, sad je povecavamo, vracamo na default elif lane.laneType == Config.laneTypeTraffic or lane.laneType == Config.laneTypeTrafficTop or lane.laneType == Config.laneTypeTrafficBottom: lane.ChangeSpeed( -Config.speedChange ) #obrnuto, ako smo bili povecali brzinu automobila kad je poceo sneg, sad je smanjujemo, vracamo na default ################################################################################ #FUNKCIJE ISPOD SE KORISTE SAMO ZA MULITPLAYER ################################################################################ def HostServer(self, address, port): self.isHost = True self.host = Host(address, port) self.host.receiveCallBack.connect(self.ReceiveFromClient) self.host.start() def JoinServer(self, address, port): self.isClient = True self.client = Client(address, port) self.client.receiveCallBack.connect(self.ReceiveFromServer) self.client.start() def SendClientToReplicateObjects(self): self.host.SendToClient(Config.network_kreirajSveObjekteNaKlijentu + ":" + self.CreateInitObjectsString()) # ovo ce biti pozvano kad server primi poruku od klijenta def ReceiveFromClient(self, data): # print("Primio od klijenta: " + str(data)) if data == Config.network_clientIsReady: # kad primi ovo znaci da se klijent povezao self.TwoPlayerMode(OverNetworkGame=True) self.player2.keyBoardInputEnabled = False self.SendClientToReplicateObjects( ) #da ne generise updater svaki put kad se predje level, vec samo incijalno kad se uspostavi veza elif data == Config.network_potvrdaKlijentaDaJeNapravioSveObjekte and self.Level == 1: # klijent je potvrdio da je napravio sve objekte i sad pokrecemo igru (pravimo i pokrecemo thread koji updateuje igru) self.createThreadToUpdateGameObjects() self.startThreadForUpdatingGameObjects() elif Config.network_inputKlijentaPrefix in data and self.player2 != None: #ovo da li je igrac razlicit od None je ustvari provera da li je ziv if Config.network_inputKlijentaPrefix + "DESNO" == data: self.player2.GoRight() elif Config.network_inputKlijentaPrefix + "DOLE" == data: self.player2.GoDown() elif Config.network_inputKlijentaPrefix + "GORE" == data: self.player2.GoUp() elif Config.network_inputKlijentaPrefix + "LEVO" == data: self.player2.GoLeft() elif Config.network_ConnectionError == data: print("Klijent je otiso :(") self.ResetGameStateOnError() # ovo ce biti pozvano kad klijent primi poruku od servera def ReceiveFromServer(self, data): #print("Primio od servera: " + str(data)) if data == Config.network_serverWelcomeMsg: # znaci da smo se uspesno povezali sa serverom i inicijalizujemo gejm self.InitNetworkGame() elif Config.network_kreirajSveObjekteNaKlijentu in data: self.GenerateObjects(data.split(":")[1]) self.client.SendToServer( Config.network_potvrdaKlijentaDaJeNapravioSveObjekte) elif Config.network_updateSveObjekteNaKlijentu in data: self.UpdateObjectsPosition(data.split(":")[1]) elif Config.network_updateGameScoreAndLives in data: #ako ovde udje PAYLOAD moze da izgleda ovako: #P2L_3 #P1S_2 #P2S_4 #P1L_1 payload = data.split(":")[1] player, scoreOrLives = payload.split('_') #print(str(payload)) if "P1" in player: if "S" in player: self.updateP1Score(scoreOrLives) elif "L" in player: self.createGreenLives(int(scoreOrLives)) elif "P2" in player: if "S" in player: self.updateP2Score(scoreOrLives) elif "L" in player: self.createPinkLives(int(scoreOrLives)) elif Config.network_updateWeatherInfo in data: self.updateWeather(data.split(":")[1]) elif Config.network_ConnectionError == data: self.ResetGameStateOnError() #ovo se poziva na klijentu. def InitNetworkGame(self): self.TwoPlayerMode( OverNetworkGame=True ) #nije potrebno ovo True, al da se dzabe nebi pravio thread koji se ne koristi :D #sklanjamo sve objekte, jer ce nam server poslati sta je on generisao (velicine, pozicije, sprajtove) for go in GameObject.allGameObjects: go.RemoveFromScreen() GameObject.allGameObjects.clear() #klijent javi serveru da je spreman (spreman da primi podatke o svim objektima) self.client.SendToServer(Config.network_clientIsReady) #poziva se ako dodje do greske prilikom komunikacije sa klijentom def ResetGameStateOnError(self): self.RemoveAllGameUIObjects() self.GameOver() #poziva se samo na serveru def SendRectPositionUpdateToClient(self): self.host.SendToClient(Config.network_updateSveObjekteNaKlijentu + ":" + self.CreateUpdateObjectsString()) #ova metoda moze ici u GameObject Klasu def CreateInitObjectsString(self): objektiUString = [] for go in GameObject.allGameObjects: #saljemo podatke koji su potrebni da bi se napravili objekti na klijentu objektiUString.append( str(go.id) + "%" + go.loadedSprite + "%" + str(go.x) + "%" + str(go.y) + "%" + str(go.w) + "%" + str(go.h)) return "#".join(objektiUString) # ova metoda moze ici u GameObject Klasu def CreateUpdateObjectsString(self): objektiUString = [] for go in GameObject.allGameObjects: #saljemo podatke koji su potrebni da bi se updateovale pozicije objekata na klijentu #optimizovano, ne saljem update za sve gameObjecte vec samo one koji su u lejeru prepreke i imaju neku brzinu if go.layer == Config.layerPrepreke and go.speed != 0: objektiUString.append( str(go.id) + "%" + str(go.x) + "%" + str(go.y)) elif go.layer == Config.layerZabe or go.layer == Config.layerLilypad: #igraci i lokvanji mogu da promene sprite i zato saljem i sprite :D objektiUString.append( str(go.id) + "%" + str(go.x) + "%" + str(go.y) + "%" + str(go.loadedSprite)) # ovo je dodato ako neki od igraca umre da ga klijent skloni sa ekrana (sprite se stavi na prazan string) if self.player1 == None and self.player1RectId != -1: objektiUString.append( str(self.player1RectId) + "%" + str(0) + "%" + str(0) + "%DEAD") self.player1RectId = -1 if self.player2 == None and self.player2RectId != -1: objektiUString.append( str(self.player2RectId) + "%" + str(0) + "%" + str(0) + "%DEAD") self.player2RectId = -1 return "#".join(objektiUString) #ova funkcija se poziva na klijentu, da napravi objekte iste kao sto su na serveru. Pozove se samo na pocetku def GenerateObjects(self, data): for layer, listOfRects in Rectangle.allRectangles.items(): for rect in listOfRects: rect.RemoveFromScreen() listOfRects.clear() objs = data.split("#") Rectangle.ResetId() for obj in objs: objData = obj.split("%") r = Rectangle(float(objData[2]), float(objData[3]), int(objData[4]), int(objData[5]), objData[1], layer=objData[0], forceId=int(objData[0])) r.Show() #ova funkcija se poziva na klijentu, sluzi za updateovanje (samo X i Y kordinate) svih rectanglova na klijentu. #server ce ovo slati klijentu svaki frejm (30 puta u sekundi) def UpdateObjectsPosition(self, data): objs = data.split("#") dictObj = {} for obj in objs: objData = obj.split("%") if len(objData) == 4: dictObj[objData[0]] = (float(objData[1]), float(objData[2]), objData[3]) elif len(objData) == 3: dictObj[objData[0]] = (float(objData[1]), float(objData[2])) for go in GameObject.allGameObjects: strId = str(go.id) if strId in dictObj.keys(): go.SetPosition(dictObj[strId][0], dictObj[strId][1]) if len(dictObj[strId] ) == 3: #ako je 3 znaci da imamo i sprite poslat go.ChangeSprite(dictObj[strId][2])
class Player(QWidget): """Sub-class of QWidget""" def __init__(self, parent=None, *args, **kwargs): """Initialize class attributes""" super(Player, self).__init__(parent, *args, **kwargs) self.init_ui() def init_ui(self): """Create local components""" # loop self.loop = False # time label text self.time_text = '{:0>2d}:{:0>2d}:{:0>2d}/{:0>2d}:{:0>2d}:{:0>2d}' self.hours = self.minutes = self.seconds = 0 # create media player object self.mediaPlayer = QMediaPlayer(self, QMediaPlayer.VideoSurface) # create videowidget object self.videoWidget = QVideoWidget() # create open button self.btn_size = QSize(16, 16) openButton = Button("Open") openButton.setToolTip("Open Media File") openButton.setStatusTip("Open Media File") openButton.setFixedHeight(24) openButton.setIconSize(self.btn_size) openButton.setIcon( QIcon.fromTheme("document-open", QIcon("Icons/Open.bmp"))) # openButton.setStyleSheet("background-color: #B0C4DE") openButton.clicked.connect(self.abrir) # create play button self.playButton = Button() self.playButton.setEnabled(False) self.playButton.setFixedHeight(24) self.playButton.setIconSize(self.btn_size) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) # self.playButton.setStyleSheet("background-color: #B0C4DE") self.playButton.clicked.connect(self.play) # create slider self.positionSlider = PositionSlider(self.mediaPlayer, Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.setObjectName("positionSlider") # create status bar self.statusBar = QStatusBar() self.statusBar.setFont(QFont("Noto sans", 8)) self.statusBar.setFixedHeight(14) self.statusBar.setStyleSheet('color:#ffffff') # create duration time label self.durationLabel = QLabel() self.durationLabel.setStyleSheet( 'background-color:rgba(255, 255, 255, 0)') self.durationLabel.setText('00:00:00/00:00:00') # create hbox layout controlLayoutWidget = QWidget(self) controlLayout = QHBoxLayout(controlLayoutWidget) controlLayoutWidget.setLayout(controlLayout) controlLayout.setContentsMargins(2, 2, 2, 2) # set widgets to the hbox layout controlLayout.addWidget(openButton) controlLayout.addWidget(self.playButton) controlLayout.addWidget(self.positionSlider) controlLayout.addWidget(self.durationLabel) # change hbox color controlLayoutWidget.setStyleSheet( 'background-color:rgba(255, 255, 255, 50)') controlLayoutWidget.setWindowOpacity(0.1) # create vbox layout self.layout = QVBoxLayout() self.layout.setSpacing(0) # set widgets to vbox layout self.layout.addWidget(self.videoWidget) self.layout.addWidget(controlLayoutWidget) self.sub_controls() self.layout.addWidget(self.statusBar) self.setLayout(self.layout) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) self.mediaPlayer.error.connect(self.handleError) self.statusBar.showMessage('{:->33s}{:-<33s}'.format("Have Fun", "")) self.key_bindings() def key_bindings(self): # bind Keys to methods self.onplaypause = self.create_shortcut(Qt.Key_Space, self.videoWidget, self.play) # Space key for self.on_fscreen = self.create_shortcut( Qt.Key_F, self.videoWidget, self.toggle_fullscreen) # F key for fullscreen on self.onforward = self.create_shortcut( Qt.Key_Right, self.videoWidget, self.forward) # Right key for forward self.redvolume = self.create_shortcut( Qt.Key_Down, self.videoWidget, self.red_volume) # Down key reduce volume self.incvolume = self.create_shortcut( Qt.Key_Up, self.videoWidget, self.inc_volume) # Up key increase volume self.onsetloop = self.create_shortcut( "L", self.videoWidget, # L key for repeat on, (lambda self=self: self.repeat.toggle() or self.play_again())) self.onrewind = self.create_shortcut( Qt.Key_Left, self.videoWidget, self.rewind) # Left key for rewind self.volmute = self.create_shortcut(Qt.Key_M, self.videoWidget, self.mute) # M for mute and unmute self.onopen = self.create_shortcut('Ctrl+O', self.videoWidget, self.abrir) # Ctrl+O for open self.onstop = self.create_shortcut(Qt.Key_S, self.videoWidget, self.stop_media) # S key for stop def create_shortcut(self, sequence, widget, obj): """generate key shortcuts""" return QShortcut(QKeySequence(sequence), widget, obj, context=Qt.ApplicationShortcut) def sub_controls(self): """Repeat, volume, and mute controls""" # repeat button self.repeat = Button() self.repeat.setCheckable(True) self.repeat.toggle() self.repeat.setIconSize(self.btn_size) self.repeat.setFixedHeight(24) self.repeat.setFixedWidth(26) self.repeat.setToolTip("repeat") self.repeat.setStatusTip("repeat") # Icons to correspond with button state icon = QIcon() icon.addPixmap(QPixmap(os.path.join(FOLDER, "Icons/repeat(1).png")), QIcon.Normal, QIcon.On) icon.addPixmap(QPixmap(os.path.join(FOLDER, "Icons/repeat(2).png")), QIcon.Active) self.repeat.setIcon(icon) # self.repeat.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;") self.repeat.clicked.connect(self.play_again) # stop button self.stop = Button() self.stop.setIconSize(self.btn_size) self.stop.setFixedHeight(24) self.stop.setFixedWidth(26) self.stop.setToolTip("Stop playing media") self.stop.setStatusTip("Stop playing media") self.stop.setIcon(self.style().standardIcon(QStyle.SP_MediaStop)) # self.stop.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;") self.stop.clicked.connect(self.stop_media) # volume slider self.volumeSlider = VolumeSlider(self.mediaPlayer, Qt.Horizontal) self.volumeSlider.setRange(0, 100) self.volumeSlider.setFixedWidth(200) self.mediaPlayer.setVolume(50) self.volumeSlider.sliderMoved.connect(self.set_volume) # volume button self.volume = Button(self) self.volume.setIconSize(self.btn_size) self.volume.setFixedHeight(24) self.volume.setFixedWidth(26) self.volume.setToolTip("Mute or Unmute") self.volume.setStatusTip("Mute or Unmute") self.volume.setIcon(self.style().standardIcon(QStyle.SP_MediaVolume)) # self.volume.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;") self.volume.clicked.connect(self.mute) # create control widget subControlWidget = QWidget(self) subControlWidget.setStyleSheet( 'background-color:rgba(255, 255, 255, 30)') # create Horizontal Layout subControlLayout = QHBoxLayout(subControlWidget) subControlLayout.setContentsMargins(0, 0, 0, 0) subControlLayout.addWidget(self.repeat, 0, Qt.AlignLeft) subControlLayout.addWidget(self.stop, 1, Qt.AlignLeft) # sub layout for volume control self.sub_layout = QHBoxLayout() self.sub_layout.addWidget(self.volume) self.sub_layout.addWidget(self.volumeSlider) subControlLayout.addLayout(self.sub_layout) subControlLayout.setContentsMargins(2, 2, 2, 2) self.layout.addWidget(subControlWidget) def abrir(self, event=None, url=None): """" Equivalent to open for most GUIs""" fileName = None if self.videoWidget.isFullScreen(): self.toggle_fullscreen() if not url: fileName, _ = QFileDialog.getOpenFileName(self, "Select media") if fileName: self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(fileName))) else: self.mediaPlayer.setMedia(QMediaContent(QUrl(url))) if url or fileName: self.volumeSlider.setValue(self.mediaPlayer.volume()) self.playButton.setEnabled(True) self.statusBar.showMessage((fileName or url)) if not self.loop: self.play() def play(self): """Start media player""" if self.playButton.isEnabled(): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): """Callback for media player state change""" if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) if state == QMediaPlayer.StoppedState and self.loop: self.play() def positionChanged(self, position): """Callback for media player position change""" if self.mediaPlayer.state() == QMediaPlayer.StoppedState: position = 0 self.positionSlider.setValue(position) hours, position = position // 3600000, position % 3600000 minutes, position = position // 60000, position % 60000 seconds = position // 1000 self.durationLabel.setText( self.time_text.format(hours, minutes, seconds, self.hours, self.minutes, self.seconds)) def durationChanged(self, duration): """Callback for media player duration of media change""" self.positionSlider.setRange(0, duration) self.hours, duration = duration // 3600000, duration % 3600000 self.minutes, duration = duration // 60000, duration % 60000 self.seconds = duration // 1000 self.durationLabel.setText( self.time_text.format(0, 0, 0, self.hours, self.minutes, self.seconds)) def setPosition(self, position): """set media player play position""" self.mediaPlayer.setPosition(position) def handleError(self): """Callback for multiplayer errors""" self.playButton.setEnabled(False) self.statusBar.showMessage("Error: " + self.mediaPlayer.errorString()) def play_again(self): """Set repeat on or off""" self.loop = not self.loop def stop_media(self): """Callback for stop button""" if self.loop: self.loop = False self.repeat.toggle() self.mediaPlayer.stop() def toggle_fullscreen(self): """Toggle in or out of fullscreen mode""" self.videoWidget.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) if self.videoWidget.isFullScreen(): self.videoWidget.setFullScreen(False) self.videoWidget.setWindowState(Qt.WindowNoState) self.videoWidget.setParent(self) self.layout.insertWidget(0, self.videoWidget) self.videoWidget.showNormal() self.show() else: self.videoWidget.setFullScreen(True) self.hide() def rewind(self, lapse=2500): """Rewind the current media file by 1 second""" new_position = self.mediaPlayer.position() - lapse self.setPosition(new_position) def forward(self, lapse=2500): """Forward media file by 1 second""" new_position = self.mediaPlayer.position() + lapse self.setPosition(new_position) def set_volume(self, vol=0): """Set media player volume volume""" if vol: self.mediaPlayer.setVolume(vol) def red_volume(self, vol=1): """Reduce volume by a factor of 0.01""" volume = self.mediaPlayer.volume() if volume >= 0: new_volume = volume - 1 self.volumeSlider.setValue(new_volume) self.set_volume(new_volume) def inc_volume(self, vol=1): """Increase volume by a factor of 0.01""" volume = self.mediaPlayer.volume() if self.mediaPlayer.isMuted(): self.mediaPlayer.setMuted(False) self.volume.setIcon(self.style().standardIcon( QStyle.SP_MediaVolume)) if volume <= 100: new_volume = volume + 1 self.volumeSlider.setValue(new_volume) self.set_volume(new_volume) def mute(self): """Mute media player""" if self.mediaPlayer.isMuted(): self.mediaPlayer.setMuted(False) self.volume.setIcon(self.style().standardIcon( QStyle.SP_MediaVolume)) else: self.mediaPlayer.setMuted(True) self.volume.setIcon(self.style().standardIcon( QStyle.SP_MediaVolumeMuted))
class MindReaderApp(QtWidgets.QMainWindow, design.Ui_MainWindow): def __init__(self): # Это здесь нужно для доступа к переменным, методам # и т.д. в файле design.py super().__init__() self.setupUi(self) # Это нужно для инициализации нашего дизайна self.setWindowTitle("MindReader") self.startButton.clicked.connect(self.start_timer) self.timer = None self.time = QtCore.QTime(0, 0, 0) self.maxTimer = 0.0 # настраиваем графики self.plot1 = self.graphic1.addPlot() self.curve1 = self.plot1.plot() self.plot2 = self.graphic2.addPlot() self.curve2 = self.plot2.plot() self.setGraphs() # задаем массивы для хранения данных self.data1 = [] self.data2 = [] self.timings = [] self.emotions = [] self.counter = 0 self.counter1 = 0 # для кнопки self.clicked = False # настройка видео self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.setVideoOutput(self.videoWidget) self.qw = QWidget() self.qw.setGeometry(10, 360, 611, 280) self.qw.setParent(self) self.faceVideoWidget = QVideoWidget() self.faceVideoWidget.setParent(self.qw) self.faceVideoWidget.show() self.facePlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.facePlayer.setVideoOutput(self.faceVideoWidget) self.facePlayer.durationChanged.connect(self.getDuration) self.chooseVideo.triggered.connect(self.openFile) self.videoChosed = False # для записи лица self.videoTimer = None self.frame = None self.capture = None self.fps = int(30) self.videoSaver = None if not os.path.exists('Recordings'): os.makedirs('Recordings') # настройка порта self.ser = serial.Serial() self.ser.baudrate = 57600 self.port = "" self.choosePort.triggered.connect(self.inputCom) # файл if not os.path.exists('Sessions'): os.makedirs('Sessions') self.vidFileName = "" self.faceFileName = "" # для считки self.fromFile = False act = QAction("Выбрать файл", self) act.triggered.connect(self.loadFile) self.openPrevSession.addAction(act) act1 = QAction("Очистить", self) act1.triggered.connect(self.cancel) self.openPrevSession.addAction(act1) # файл настроек self.sname = 'settings.txt' self.emotions = [] if not os.path.isfile(self.sname): self.f = open(self.sname, 'w') self.f.close() self.f = open(self.sname, 'r') #для считки настроек из файла self.settings.addAction(self.setEmotions) self.setEmotionsData.triggered.connect(self.loadSettings) # эмоции self.settings = SettingsWindow() self.setEmotions.triggered.connect(self.openSettings) self.emotionsList = [] def cancel(self): self.fromFile = False def stop(self): self.startButton.setText("Запустить") self.timer.stop() self.timer.deleteLater() self.pause_video() self.mediaPlayer.stop() self.facePlayer.stop() self.clicked = False # show all in graphics xdict = dict(enumerate(self.timings)) self.plot1.getAxis('bottom').setTicks([xdict.items()]) self.curve1.setData(self.data1) self.plot2.getAxis('bottom').setTicks([xdict.items()]) self.curve2.setData(self.data2) # close file self.f.close() # запускает таймер, который работает сколько влезет, пауза кнопкой def start_timer(self): if self.clicked: self.stop() else: if self.fromFile: try: self.faceWidget.hide() self.facePlayer.setMedia( QMediaContent(QUrl.fromLocalFile(self.faceFileName))) self.qw.show() self.facePlayer.play() self.start = time.time() except Exception as e: QMessageBox.about(self, "Ошибка!", "Видеофайл отсутствует или поврежден.") if not self.fromFile: if self.port == "": QMessageBox.about(self, "Ошибка!", "Выберите COM порт!") return if not self.videoChosed: QMessageBox.about( self, "Ошибка!", "Выберите видеофайл для воспроизведения!") return # открытие порта self.ser.port = self.port if not self.ser.isOpen(): try: self.ser.open() except serial.SerialException: QMessageBox.about(self, "Ошибка!", "Выберите работающий COM порт!") return self.qw.hide() self.faceWidget.show() self.set_camera(self.frame) # reset data for graphs self.data1 = [] self.data2 = [] self.timings = [] self.emotions = [] self.plot1.getAxis('bottom').setTicks([]) self.plot2.getAxis('bottom').setTicks([]) # new file self.fname = str( len([ name for name in os.listdir('Sessions') if os.path.isfile(os.path.join('Sessions', name)) ])) + '.emtn' if not os.path.isfile('Sessions/' + self.fname): self.f = open('Sessions/' + self.fname, 'w') self.f.close() self.f = open('Sessions/' + self.fname, 'r') self.f = open('Sessions/' + self.fname, 'w') self.f.write(self.vidFileName + "\n") self.f.write(os.getcwd() + '/Recordings/{}.avi'.format(self.faceFileName) + "\n") self.startButton.setText("Остановить") self.counter = 0 self.counter1 = 0 self.emotionsList = self.settings.emotions self.mediaPlayer.setMedia( QMediaContent(QUrl.fromLocalFile(self.vidFileName))) self.time = QtCore.QTime(0, 0, 0) self.timer = QtCore.QTimer() self.timer.timeout.connect(self.update) self.timer.start(4) self.mediaPlayer.play() self.clicked = True def set_camera(self, frame): try: if not self.fromFile: self.capture = cv2.VideoCapture(0) self.width = self.capture.get(cv2.CAP_PROP_FRAME_WIDTH) self.height = self.capture.get(cv2.CAP_PROP_FRAME_HEIGHT) self.fps = self.capture.get(cv2.CAP_PROP_FPS) if self.fps == 0 or self.fps == -1: self.fps = int(25) print( "Warning: OpenCV failed to get your camera's frame rate, set to {}." .format(self.fps)) # start fourcc = cv2.VideoWriter_fourcc(*'XVID') self.faceFileName = len([ name for name in os.listdir('Recordings') if os.path.isfile(os.path.join('Recordings', name)) ]) self.videoSaver = cv2.VideoWriter( 'Recordings/{}.avi'.format(self.faceFileName), fourcc, cv2.CAP_PROP_FPS, (int(self.width), int(self.height))) self.start_video() except Exception as e: self.capture = None QMessageBox.about(self, "Ошибка!", "Невозможно использовать вашу камеру.") print(str(e)) def _draw_frame(self, frame): # convert to pixel cvtFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = QImage(cvtFrame, self.width, self.height, QImage.Format_RGB888) pix = QPixmap.fromImage(img) self.faceWidget.setPixmap(pix) outFrame = cv2.cvtColor(cvtFrame, cv2.COLOR_BGR2RGB) self.videoSaver.write(outFrame) QtGui.QApplication.processEvents() def _next_frame(self): try: if self.capture is not None: _ret, frame = self.capture.read() if frame is None: QMessageBox.about(self, "Ошибка!", "Ошибка считывания изображения.") print( "ERROR: Read next frame failed with returned value {}." .format(_ret)) # Draw. self._draw_frame(frame) except Exception as e: QMessageBox.about(self, "Ошибка!", "Ошибка считывания изображения.") print(str(e)) # Saving output video if self.videoSaver: self.videoSaver.release() def start_video(self): self.videoTimer = QtCore.QTimer() self.videoTimer.timeout.connect(self._next_frame) self.videoTimer.start(1000 // self.fps) def pause_video(self): try: if self.capture != None: self.capture.release() self.capture = None self.faceWidget.clear() self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.mediaPlayer.setVideoOutput(self.videoWidget) self.qw.show() self.faceWidget.show() self.videoSaver = None cv2.destroyAllWindows() self.clicked = False print("INFO: Streaming paused.") except Exception as e: print(str(e)) def getDuration(self): self.maxTimer = float(self.facePlayer.duration() / 1000) print(self.maxTimer) # то что происходит каждый тик таймера def update(self): self.counter += 1 # заглушка для считываемого потока # x = random.randint(0, 100) # y = random.randint(0, 100) ######################## if not self.fromFile: # считка с устройства ch1, ch2 = self.readFromEEG() # получаем эмоцию emtn = self.getEmotion(ch1, ch2) # точки выводятся каждые 100 мс interval = 100 / 4 if not self.fromFile: interval = 0.1 / 4 if self.counter >= interval: interval *= 4 self.counter = 0 # добавляем точки только если их надо считывать if not self.fromFile: self.time = self.time.addMSecs(interval * 1000) self.timings.append(self.time.toString('mm:ss.zzz')) self.emotions.append(emtn) self.data1.append(ch1) self.data2.append(ch2) # запись в файл self.f.write( str(ch1) + "|" + str(ch2) + "|" + self.time.toString('mm:ss.zzz') + "|" + emtn + "\n") # все отображается по готовому набору данных и прокручивается каунтером1 if (self.counter1 < len(self.data1)): self.EmotionLabel.setText("Текущая эмоция: " + self.emotions[self.counter1]) self.updateGraphs() self.counter1 += 1 curTime = time.time() # если все данные уже показаны то стоп if self.fromFile and (curTime - self.start ) > self.maxTimer and self.counter1 >= len( self.data1): self.stop() def updateGraphs(self): numbp = 200 # скорость прокрутки - выводятся последние numbp точек pos = int(self.counter1 - numbp) if pos < 0: pos = 0 xdict = dict(enumerate(self.timings[pos:self.counter1])) self.curve1.setData(self.data1[pos:self.counter1]) self.plot1.getAxis('bottom').setTicks([xdict.items()]) self.plot1.setXRange(0, numbp) self.curve2.setData(self.data2[pos:self.counter1]) self.plot2.getAxis('bottom').setTicks([xdict.items()]) self.plot2.setXRange(0, numbp) def getEmotion(self, ch1, ch2): for emt in self.emotionsList: isRight = False if emt.from_strength <= ch1 <= emt.to_strength: if emt.from_color <= ch2 <= emt.to_color: isRight = True if isRight: return emt.name return "не определена" def setGraphs(self): # self.win.setWindowTitle('pyqtgraph example: Scrolling Plots') # Use automatic downsampling and clipping to reduce the drawing load self.plot1.setDownsampling(mode='peak') self.plot1.setClipToView(True) self.plot1.setRange(xRange=[0, 100]) self.plot1.setLimits(xMin=0) self.plot2.setDownsampling(mode='peak') self.plot2.setClipToView(True) self.plot2.setRange(xRange=[0, 100]) self.plot2.setLimits(xMin=0) def openFile(self): self.vidFileName, _ = QFileDialog.getOpenFileName( self, "Открыть видео", QDir.homePath(), "video files (*.avi *.mp4 *.gif)") if self.vidFileName != '': self.videoChosed = True def butter_bandpass(self, lowcut, highcut, fs, order=5): nyq = 0.5 * fs low = lowcut / nyq high = highcut / nyq b, a = butter(order, [low, high], btype='band') return b, a def butter_bandpass_filter(self, data, lowcut, highcut, fs=256, order=5): b, a = self.butter_bandpass(lowcut, highcut, fs, order=order) y = lfilter(b, a, data) return y def filter(self, data, hi, lo): fs = np.fft.rfft(data) q = np.fft.rfftfreq(len(data), 256) fs[(q > hi)] = 0 fs[(q < lo)] = 0 return np.fft.irfft(fs) def readFromEEG(self): n = 26 strArr = np.zeros(n) pArr = np.zeros(n) for i in range(0, n): gotBegin = False # seek start while not gotBegin: # 1 x = self.ser.read() while int.from_bytes(x, byteorder='big') != 165: x = self.ser.read() gotBegin = True # 2 x = self.ser.read() gotBegin = gotBegin and int.from_bytes(x, byteorder='big') == 90 # 3 x = self.ser.read() gotBegin = gotBegin and int.from_bytes(x, byteorder='big') == 2 # 4 self.ser.read() def conv2sig(xb, yb): xi = int.from_bytes(xb, byteorder='big') yi = int.from_bytes(yb, byteorder='big') a = format(xi, 'b') + format(yi, 'b') return int(a, 2) # 5 and 6 ch1 = conv2sig(self.ser.read(), self.ser.read()) strArr[i] = ch1 # 7 and 8 ch2 = conv2sig(self.ser.read(), self.ser.read()) pArr[i] = ch2 out1 = self.butter_bandpass_filter(strArr, 8, 12) out2 = self.butter_bandpass_filter(pArr, 12, 30) # out1 = self.filter(strArr, 8, 12) # out2 = self.butter_bandpass_filter(strArr, 8, 12) a1 = np.mean(out1) a2 = abs(out1.min()) + abs(out1.max()) a3 = out1[len(out1) - 1] b1 = np.mean(out2) b2 = abs(out2.min()) + abs(out2.max()) b3 = out2[len(out2) - 1] return a2, b2 def inputCom(self): text, ok = QInputDialog.getText( self, 'Выбор COM порта', 'Введите номер COM порта, к которому подключено устройство:') if ok: if sys.platform.startswith('win'): self.port = 'COM' + text elif sys.platform.startswith('linux') or sys.platform.startswith( 'cygwin'): self.port = '/dev/ttyUSB' + text elif sys.platform.startswith('darwin'): self.port = '/dev/ttyUSB' + text else: raise EnvironmentError('Unsupported platform') self.ser.port = self.port if not self.ser.isOpen(): try: self.ser.open() except serial.SerialException: QMessageBox.about(self, "Ошибка!", "Выберите работающий COM порт!") def loadFile(self): path, _ = QFileDialog.getOpenFileName(self, "Открыть файл", QDir.homePath(), "Emotion Files (*.emtn)") if path != '': self.fromFile = True f = open(path, 'r', encoding='utf-8', errors='ignore') allLines = f.readlines() f.close() try: self.vidFileName = allLines[0] self.vidFileName = self.vidFileName[:-1] self.faceFileName = allLines[1] self.faceFileName = self.faceFileName[:-1] allLines.remove(allLines[0]) allLines.remove(allLines[0]) # reset data for graphse self.data1 = [] self.data2 = [] self.timings = [] self.emotions = [] self.plot1.getAxis('bottom').setTicks([]) self.plot2.getAxis('bottom').setTicks([]) for line in allLines: x = line.split('|') self.data1.append(float(x[0])) self.data2.append(float(x[1])) self.timings.append(x[2]) self.emotions.append(x[3]) except Exception as e: QMessageBox.about(self, "Ошибка!", "Файл поврежден или неверно сформирован.") def loadSettings(self): path, _ = QFileDialog.getOpenFileName(self, "Открыть настройки", QDir.homePath(), "txt files (*.txt)") if path != '': f = open(path, 'r') allLines = f.readlines() f.close() # считываем данные из файла и записываем эмоции self.emotions.clear() for line in allLines: s = line.rstrip("\r\n") x = s.split('|') emotion = Emotion(x[0], int(x[1]), int(x[2]), int(x[3]), int(x[4])) self.emotions.append(emotion) self.settings.loadEmotions(self.emotions) msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("Настройки загружены из файла.") msg.setWindowTitle("Уведомление") msg.exec_() self.openSettings() def openSettings(self): self.settings.show()
class VideoWindow(QWidget): def __init__(self, vidPath): super().__init__() self.fullPath = vidPath self.startTime = 0 self.endTime = 0 self.init_ui() def init_ui(self): layout = QVBoxLayout() self.setLayout(layout) self.setWindowTitle(self.fullPath) self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface) self.videoWidget = QVideoWidget() self.playButton = QPushButton() self.playButton.setEnabled(True) self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay)) self.playButton.setFixedWidth(100) self.playButton.setFixedHeight(50) self.playButton.clicked.connect(self.play) self.trimButton = QPushButton("Trim") self.trimButton.setFixedWidth(150) self.trimButton.setFixedHeight(50) self.trimButton.clicked.connect(self.trimVid) self.positionSlider = QSlider(QtCore.Qt.Horizontal) self.positionSlider.setRange(0, 0) self.positionSlider.sliderMoved.connect(self.setPosition) self.rangeSlider = qrangeslider.QRangeSlider() self.rangeSlider.setRange(0, 0) self.rangeSlider.endValueChanged.connect(self.adjustForEnd) self.rangeSlider.startValueChanged.connect(self.adjustForStart) self.rangeSlider.setFixedHeight(15) self.startTimeInput = QTimeEdit() self.endTimeInput = QTimeEdit() self.startTimeInput.setDisplayFormat('hh:mm:ss.zzz') self.endTimeInput.setDisplayFormat('hh:mm:ss.zzz') self.startTimeInput.timeChanged.connect(self.startInputChanged) self.endTimeInput.timeChanged.connect(self.endInputChanged) self.mediaPlayer.setMedia( QMediaContent(QtCore.QUrl.fromLocalFile(self.fullPath))) layout.addWidget(self.videoWidget) self.mediaPlayer.setVideoOutput(self.videoWidget) self.mediaPlayer.setNotifyInterval(10) self.mediaPlayer.stateChanged.connect(self.mediaStateChanged) self.mediaPlayer.positionChanged.connect(self.positionChanged) self.mediaPlayer.durationChanged.connect(self.durationChanged) controlLayout = QVBoxLayout() controlLayout.setContentsMargins(0, 0, 0, 0) controlLayout.addWidget(self.rangeSlider) controlLayout.addWidget(self.positionSlider) timeInputLayout = QHBoxLayout() timeInputLayout.addWidget(self.playButton) timeInputLayout.addWidget(self.startTimeInput) timeInputLayout.addWidget(self.endTimeInput) timeInputLayout.addWidget(self.trimButton) controlLayout.addLayout(timeInputLayout) layout.addLayout(controlLayout) self.mediaPlayer.play() self.resize(1024, 700) self.show() def closeEvent(self, event): self.mediaPlayer.stop() self.videoWidget.setParent(None) self.mediaPlayer.setParent(None) self.mediaPlayer.deleteLater() self.videoWidget.deleteLater() def trimVid(self): self.trimButton.setEnabled(False) outName = mytools.getAvailableName(self.fullPath, 'Trim') print(outName) trimStartTime = self.startTimeInput.time().toString('hh:mm:ss.zzz') trimEndTime = self.endTimeInput.time().toString('hh:mm:ss.zzz') try: ff = FFmpeg(inputs={self.fullPath: None}, outputs={ outName: [ '-ss', trimStartTime, '-to', trimEndTime, '-c:v', 'copy', '-c:a', 'copy', ] }) ff.run() except Exception as e: msg = QMessageBox() msg.setWindowTitle("Trim Failed") msg.setText(str(e)) msg.setIcon(QMessageBox.Critical) showMsg = msg.exec_() self.trimButton.setEnabled(True) def play(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.mediaPlayer.pause() else: self.mediaPlayer.play() def mediaStateChanged(self, state): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPause)) else: self.playButton.setIcon(self.style().standardIcon( QStyle.SP_MediaPlay)) def positionChanged(self, position): self.positionSlider.setValue(position) if position > self.endTime: self.mediaPlayer.setPosition(self.startTime) def adjustForStart(self, startPos): self.startTime = startPos self.mediaPlayer.setPosition(startPos) self.startTimeInput.setTime(QtCore.QTime(0, 0).addMSecs(startPos)) self.endTimeInput.setMinimumTime(QtCore.QTime(0, 0).addMSecs(startPos)) def adjustForEnd(self, endPos): self.endTime = endPos if self.positionSlider.value() > endPos: self.mediaPlayer.setPosition(endPos) self.endTimeInput.setTime(QtCore.QTime(0, 0).addMSecs(endPos)) self.startTimeInput.setMaximumTime(QtCore.QTime(0, 0).addMSecs(endPos)) def startInputChanged(self, inputTime): self.rangeSlider.setStart(QtCore.QTime(0, 0, 0, 0).msecsTo(inputTime)) def endInputChanged(self, inputTime): self.rangeSlider.setEnd(QtCore.QTime(0, 0, 0, 0).msecsTo(inputTime)) def durationChanged(self, duration): self.positionSlider.setRange(0, duration) self.rangeSlider.setMax(duration) self.rangeSlider.setEnd(duration) self.startTimeInput.setMinimumTime(QtCore.QTime(0, 0)) self.endTimeInput.setMinimumTime(QtCore.QTime(0, 0)) self.endTimeInput.setTime(QtCore.QTime(0, 0).addMSecs(duration)) self.startTimeInput.setMaximumTime( QtCore.QTime(0, 0).addMSecs(duration)) self.endTimeInput.setMaximumTime(QtCore.QTime(0, 0).addMSecs(duration)) def setPosition(self, position): self.mediaPlayer.setPosition(position)