2012-09-12 8 views
6

Sto cercando di eseguire un twisted-server con pygame-clienti:Client contorti all'interno di pygame mainloop?

class ChatClientProtocol(LineReceiver): 
    def lineReceived(self,line): 
     print (line) 

class ChatClient(ClientFactory): 
    def __init__(self): 
     self.protocol = ChatClientProtocol 

def main(): 
    flag = 0 
    default_screen() 
    while True: 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       return 
      elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: 
       return 
      elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: 
       pos = pygame.mouse.get_pos() 
       # some rect.collidepoint(pos) rest of loop... 

E qui è il server:

from twisted.internet.protocol import Factory 
from twisted.protocols.basic import LineReceiver 
from twisted.internet import reactor 

class Chat(LineReceiver): 
    def __init__(self, users, players): 
     self.users = users 
     self.name = None 
     self.players = players 

    def connectionMade(self): 
     new = 'player_' + str(len(self.players) + 1) 
     self.players.append(new) 
     self.sendLine(str(self.players,)) 

class ChatFactory(Factory): 
    def __init__(self): 
     self.users = {} #maps instances to clients 
     self.players = [] 

    def buildProtocol(self, addr): 
     return Chat(self.users,self.players) 


reactor.listenTCP(6000, ChatFactory()) 
reactor.run() 

Io corro questo server con il codice del client con il reactor.CallLater() metodo e codice pygames e il client si connette bene. Sto usando il metodo del reattore sbagliato o c'è qualcosa di strutturalmente sbagliato nel codice pygames? Qualsiasi aiuto sarebbe apprezzato.

Quindi non so se il loop all'interno del bit pygames si rompa mai per chiamare di nuovo il reattore?

+0

Qualcosa non funziona? Dov'è il tuo problema? – sloth

+0

Mi aggiornerò per spiegare più chiaramente. – tijko

risposta

8

È necessario non scrivere il proprio ciclo principale (con while) quando si utilizza twistato. twisted ha il controllo del ciclo principale, e pygame è abbastanza flessibile da non preoccuparsene (non ha bisogno del suo ciclo proprio) .

Si dovrebbe mettere tutto ciò che è all'interno del vostro ciclo principale in una funzione, e shedule con il reattore contorto chiamando reactor.CallLater()

def main(): 
    flag = 0 
    default_screen() 
    reactor.callLater(0.1, tick) 

def tick(): 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      reactor.stop() # just stop somehow 
     elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: 
      reactor.stop() # just stop somehow 
     elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: 
      pos = pygame.mouse.get_pos() 
      # some stuff 
    reactor.callLater(0.1, tick) 

In questo modo, si garantisce le piste del reattore e in grado di gestire gli eventi di rete.


Ecco un piccolo esempio di lavoro di un cliente che sarà solo rendere l'ultima riga ricevuto:

from twisted.internet import reactor 
from twisted.internet.protocol import ClientFactory 
from twisted.protocols.basic import LineReceiver 

import pygame 

class ChatClientProtocol(LineReceiver): 

    def __init__(self, recv): 
     self.recv = recv 

    def lineReceived(self,line): 
     self.recv(line) 

class ChatClient(ClientFactory): 
    def __init__(self, recv): 
     self.protocol = ChatClientProtocol 
     self.recv = recv 

    def buildProtocol(self, addr): 
     return ChatClientProtocol(self.recv) 

class Client(object): 

    def __init__(self): 
     self.line = 'no message' 
     pygame.init() 
     self.screen = pygame.display.set_mode((200, 200)) 
     reactor.callLater(0.1, self.tick) 

    def new_line(self, line): 
     self.line = line 

    def tick(self): 
     self.screen.fill((0,0,0)) 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       reactor.stop() # just stop somehow 
      elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: 
       reactor.stop() # just stop somehow 
     self.screen.blit(pygame.font.SysFont('mono', 12, bold=True).render(self.line, True, (0, 255, 0)), (20,20)) 
     pygame.display.flip() 
     reactor.callLater(0.1, self.tick) 

if __name__ == '__main__': 
    c = Client() 
    reactor.connectTCP('127.0.0.1',6000, ChatClient(c.new_line))  
    reactor.run() 

Ecco un semplice esempio utilizzando LoopingCall, come suggerito Glifo (ho lasciato fuori la protocoll/classi di fabbrica come sono le stesse di sopra):

from twisted.internet.task import LoopingCall 

class Client(object): 

    def __init__(self): 
     self.line = 'no message' 
     pygame.init() 
     self.screen = pygame.display.set_mode((200, 200)) 

    def new_line(self, line): 
     self.line = line 

    def tick(self): 
     self.screen.fill((0,0,0)) 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       reactor.stop() # just stop somehow 
      elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: 
       reactor.stop() # just stop somehow 
     self.screen.blit(pygame.font.SysFont('mono', 12, bold=True).render(self.line, True, (0, 255, 0)), (20,20)) 
     pygame.display.flip() 

if __name__ == '__main__': 
    c = Client() 

    lc = LoopingCall(c.tick) 
    lc.start(0.1) 
    reactor.connectTCP('127.0.0.1',6000, ChatClient(c.new_line))  
    reactor.run() 
+0

Dovrei chiamare 'reactor.run()' dopo il tick e il main? Pensavo di aver bisogno di avviarlo o questo impedirà a main e tick di funzionare sempre? Perché senza questo lo schermo di pygame inizia e quindi esce lo schermo di pygame non viene visualizzato affatto (quindi il main non viene chiamato) – tijko

+1

Basta chiamare 'main()' una volta (o qualsiasi altro codice che si chiama per inizializzare il tuo cliente). La parte importante è che 'reactor.callLater (0.1, tick)' viene chiamato una volta prima di chiamare 'reactor.run()'. – sloth

+0

Ho ancora bisogno di eseguire 'reactor.ConnectTcp ('192.168.1.2', 6000, ChatClient())' e 'reactor.run' dopo la chiamata' main() '? Sono andato avanti e ho provato questo, ma ora gli eventi di pygames non rispondono? – tijko