We will pick up where we left in the networking example. This time we will create a puzzle game that lets us guess a word. This is just a prototype mind you. It still needs a lot of polishing.
The following steps will help you to create the intended puzzle game:
Server changes: The changes in the server are pretty trivial. We just check whether we guessed the correct word:
from twisted.internet import reactor, protocol class Server(protocol.Protocol): def dataReceived(self, msg): resp = '*' * 20 print msg if msg == 'secret': resp = msg self.transport.write(resp) def main(): factory = protocol.ServerFactory() factory.protocol = Server reactor.listenTCP(8888,factory) reactor.run() if __name__ == '__main__': main()
Client changes: The most important changes are the handling of key presses in an input box and handling of the response from the server. The input box lets us type text, edit it with the Backspace key, and submit with the Enter key. A label above the textbox displays the number of attempts and the game status. We use a Twisted looping callback to update the GUI every 30 milliseconds:
from twisted.internet import reactor, protocol from pygame.locals import * import pygame from twisted.internet.task import LoopingCall class Client(protocol.Protocol): def __init__(self): self.STARS = '*' * 20 self.msg = self.STARS self.font = pygame.font.Font(None, 22) self.screen = pygame.display.get_surface() self.label = 'Guess the word:' self.attempts = 0 def sendMessage(self, msg): self.transport.write(msg) def dataReceived(self, msg): self.msg = msg if self.msg != self.STARS: self.label = 'YOU WIN!!!!' self.update_prompt() def update_prompt(self): self.screen.fill((255, 255, 255)) BG = (0, 255, 0) FG = (0, 0, 0) pygame.draw.rect(self.screen, BG, (100, 200, 200, 20)) self.screen.blit(self.font.render(self.msg, 1, FG), (100, 200)) self.screen.blit(self.font.render("%d %s" % (self.attempts, self.label), 1, FG), (140, 180)) pygame.display.flip() def handle_events(p): while True: for event in pygame.event.get(): if event.type == QUIT: reactor.stop() return elif event.type == KEYDOWN: key = event.key if p.msg == '*' * 20: p.msg = '' if key == K_BACKSPACE: p.msg = p.msg[0:-1] p.update_prompt() elif key == K_RETURN: p.attempts += 1 p.sendMessage(p.msg) return elif ord('a') <= key <= ord('z'): p.msg += chr(key) p.update_prompt() def send(p): p.update_prompt() tick = LoopingCall(handle_events, p) tick.start(.03) def main(): pygame.init() screen = pygame.display.set_mode((400, 400)) pygame.display.set_caption('Puzzle Demo') c = protocol.ClientCreator(reactor, Client) c.connectTCP("localhost", 8888).addCallback(send) reactor.run() if __name__ == '__main__': main()
The following screenshot was taken after guessing the word:
Although this seems to be a pretty extensive recipe, only a few lines of the code might require some explanation:
Function |
Description |
---|---|
|
This creates a looping callback. A callback function that is called periodically. |
|
This starts the looping callback with a period of 30 milliseconds. |