# Example client to show how to use TwistedRenderer See how many times
# you can click the button in a 5-second period.
# Written by Ben Olsen
import pygame
from random import randint
from ocempgui.widgets import *
from ocempgui.widgets.Constants import *
from ocempgui.object import BaseObject
from twisted.internet.threadedselectreactor import install
install()
from twisted.internet import reactor
from twisted.spread import pb
REPORT = pygame.locals.USEREVENT + 4
SCORE = pygame.locals.USEREVENT + 5
class NetController (BaseObject, pb.Referenceable):
def __init__ (self, re):
"""
The network controller. Can call remote PB methods, and because
it inherits from pb.Referenceable, can also contain remote
methods callable by the server.
Make sure you set the internal _signals before setting the
manager, otherwise the signals won't get connected to the event
manager.
"""
BaseObject.__init__ (self)
self._signals[SCORE] = []
self.connect_signal (SCORE, self.add_one)
self.manager = re.active_layer[2]
# Set up twisted connection.
self.factory = pb.PBClientFactory ()
d = self.factory.getRootObject ()
d.addCallback (self.setRoot)
reactor.connectTCP ('localhost', 8008, self.factory)
self.root = None
def setRoot (self, root):
self.root = root
reactor.callLater (0, self.resetter)
def add_one (self, data):
# Call the server's score method and update score by 1. Although
# data is passed to this method, it isn't used. Note that it
# sends self as an arg, so that the server can call a remote
# method on this object.
if self.root:
self.root.callRemote ('score', self, 1)
def resetter (self):
# This method is called by the reactor every 5 seconds to reset
# the score on the server.
if self.root:
self.root.callRemote ('reset', self)
self.emit (REPORT, 0)
reactor.callLater (5, self.resetter)
def remote_report (self, score):
# This method is called by the server and emits a REPORT event
# which is picked up by the JumpingButton object.
self.emit (REPORT, score)
def notify (self, event):
self.run_signal_handlers (event.signal, event.data)
class JumpingButton (BaseObject):
def __init__ (self, re):
"""
The Jumping Button game. When the button is clicked, it emits a
SCORE event, which is picked up by the network controller. It
listens for a REPORT event and updates the score display with
the value given by the server.
"""
BaseObject.__init__ (self)
self._signals[REPORT] = []
self.connect_signal (REPORT, self.adjustScore)
self.manager = re.active_layer[2]
# create gui elements
self.btn = self.drawButton ((20, 20))
self.scoreLabel = Label ("Current score: ")
re.add_widget (self.btn)
re.add_widget (self.scoreLabel)
def clicked (self, data):
x = randint (1, 550 - self.btn.width)
y = randint (1, 470 - self.btn.height)
self.btn.topleft = (x, y)
self.emit (SCORE, data.pos)
def drawButton (self, loc):
button = Button ("Click me!")
button.topleft = loc
button.connect_signal (SIG_MOUSEDOWN, self.clicked)
return button
def adjustScore (self, score):
self.scoreLabel.text = "Current score: %s" % score
def notify (self, event):
self.run_signal_handlers (event.signal, event.data)
if __name__ == '__main__':
re = TwistedRenderer ()
re.reactor = reactor
re.create_screen (550, 470)
re.title = "Jumping Button"
re.color = (234, 228, 223)
net = NetController (re)
game = JumpingButton (re)
re.start()
syntax highlighted by Code2HTML, v. 0.9.1