twisted pygame
Perspective Broker
Für mein erstes Netzwerkspiel (ok, Spiel ist vielleicht etwas übertrieben) habe ich zunächst ein kleines Spiel geschrieben, bei dem es zwei Objekte gibt. Jeder Spieler kann eines dieser Objekte bewegen, wobei es hier erstmal nur einen Spieler gibt, das andere Objekt ist quasi tot.
Im nächsten Schritt habe ich die Netzwerkfunktionalität in einer weiteren Datei implementiert. Als Ausgangspunkt habe ich dieses Pseudoscript genommen. Und nun kommt der interessante (und auch unsaubere) Teil. Die Klasse PygameTimer funktioniert sowohl als Server als auch als Client, je nach gesetztem START_SERVER Flag. Der Server ist in diesem Falle passiv und stellt nur Methoden bereit, über die der Client dann aktiv Daten abfragen und setzen kann.
Hier mein erster Code, der noch sehr zusammengahackt und unsauber ist:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | #!/usr/bin/env python
# coding: utf-8
"""
My first test with pygame and twisted
game part
(cc) by Julian Habrock, 23.1.09
bytemuehle.de
"""
import sys, pygame, time, os
from pygame.locals import *
BG_COLOR = (0, 0, 0)
def load_image(name, colorkey=None):
fullname = name#os.path.join('data', name)
try:
image = pygame.image.load(fullname)
except pygame.error, message:
print 'Cannot load image:', fullname
raise SystemExit, message
image = image.convert()
if colorkey is not None:
if colorkey is -1:
colorkey = image.get_at((0,0))
print "colorkey: ", colorkey
image.set_colorkey(colorkey, RLEACCEL)
return image, image.get_rect()
class Player(pygame.sprite.Sprite):
"""
Simple game object
you can move your player (self.local == True) between 2 positions with
the "<-" and "->" keys
"""
positions = {"left":100, "right":540}
colors = {"red":(199, 3, 3), "green":(1, 243, 1)}
rows = {"top":150, "bottom":250}
def __init__(self, pos, color, row, local=0):
pygame.sprite.Sprite.__init__(self)
self.image, self.rect = load_image("player.gif", -1)
pxarray = pygame.PixelArray(self.image)
pxarray.replace((255, 0, 0), self.colors[color])
self.image = pxarray.make_surface()
self.image.set_colorkey(self.image.get_at((0,0)), RLEACCEL)
self.image.convert()
self.position = pos
self.row = row
self.rect.centery = self.rows[row]
self.local = local
def update(self, events):
if self.local:
for event in events:
if event.type == KEYDOWN:
if event.key == K_LEFT:
self.position = "left"
elif event.key == K_RIGHT:
self.position = "right"
else:
print event.key
self.rect.centerx = self.positions[self.position]
class Game():
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((640, 400))
pygame.display.set_caption('title')
pygame.mouse.set_visible(1)
#Create The Backgound
self.background = pygame.Surface(self.screen.get_size())
self.background = self.background.convert()
#background.fill((250, 250, 250))
self.background.fill(BG_COLOR)
#Put Text On The Background, Centered
if pygame.font:
font = pygame.font.Font(None, 36)
text = font.render("twisted pygame", 1, (10, 10, 10))
textpos = text.get_rect(centerx=self.background.get_width()/2)
self.background.blit(text, textpos)
#Display The Background
self.screen.blit(self.background, (0, 0))
pygame.display.flip()
#Prepare Game Objects
self.clock = pygame.time.Clock()
# boom_sound = load_sound('boom.wav')
self.allsprites = pygame.sprite.RenderPlain()
self.player = Player("right", "green", "bottom", 1)
self.player2 = Player("left", "red", "top")
self.allsprites.add(self.player, self.player2)
self.running = True
def update(self):
#Handle Input Events
events = pygame.event.get()
for event in events:
if event.type == QUIT:
self.running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
self.running = False
self.allsprites.update(events)
#Draw Everything
self.screen.blit(self.background, (0, 0))
self.allsprites.draw(self.screen)
pygame.display.flip()
def main():
"""this function is called when the program starts.
it initializes everything it needs, then runs in
a loop until the function returns."""
#Initialize Everything
game = Game()
#Main Loop
while 1:
game.clock.tick(100)
game.update()
if not game.running:
break
#Game Over
#this calls the 'main' function when this script is executed
if __name__ == '__main__': main()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #!/usr/bin/env python
# coding: utf-8
"""
My first test with pygame and twisted
network part
(c) by Julian Habrock, 23.1.09
bytemuehle.de
"""
import sys
from pygame import time
from twisted.internet import reactor
from twisted.spread import pb
import simple_game
help1 = """
twisted PyGame
================
usage:
$python twisted_game.py [arg]
arg must be one of:
'server' or 's' to start the server
'client' or 'c' to start the client
-----------
(c) by Julian Habrock
bytemuehle.de"""
help2 = """
arg must be one of:
'server' or 's' to start the server
'client' or 'c' to start the client
"""
if len(sys.argv) != 2:
print help1
START_SERVER = None
else:
arg = sys.argv[1]
if arg in ("server", "s"):
START_SERVER = True
elif arg in ("client", "c"):
START_SERVER = False
else:
print help2
START_SERVER = None
def clientfunc(func):
def dummy(*args):pass
if not START_SERVER:
return func
else: return dummy
def serverfunc(func):
def dummy(*args):pass
if not START_SERVER:
return dummy
else: return func
class PygameTimer(pb.Root):
def __init__(self, factory=None):
self.clock = time.Clock()
self.game = simple_game.Game()
self.factory = factory
if not START_SERVER:
assert self.factory != None
self.update_game()
def update_game(self):
"""
replaces the pygame event loop
"""
# self.clock.tick()
# self.ms = self.clock.get_rawtime()
# framespeed = (1.0/100.0) * 1000
# lastspeed = self.ms
# next = framespeed - lastspeed
# print "framespeed", framespeed, "ms", self.ms, "next", next, "fps",\
# self.clock.get_fps()
self.get_pos()
self.game.update()
self.send_pos()
if self.game.running:
reactor.callLater(0.05, self.update_game)
else:
reactor.stop()
def setpos(self, pos):
self.game.player2.position = pos
def dummy(self, *args):
print "dummy: ", args
# CLIENT PART
@clientfunc
def send_pos(self):
d = factory.getRootObject()
d.addCallback(lambda object: object.callRemote('setpos',
self.game.player.position))
@clientfunc
def get_pos(self):
d = factory.getRootObject()
d.addCallback(lambda object: object.callRemote('getpos'))
d.addCallback(self.setpos)
# SERVER PART
@serverfunc
def remote_getpos(self):
#print 'getdir'
return self.game.player.position
@serverfunc
def remote_setpos(self, new_pos):
#print "setting position: ", new_pos
self.game.player2.position = new_pos
return True
if __name__ == '__main__' and START_SERVER is not None:
if START_SERVER:
pt = PygameTimer()
reactor.listenTCP(8789, pb.PBServerFactory(pt))
else:
factory = pb.PBClientFactory()
pt = PygameTimer(factory)
reactor.connectTCP("localhost", 8789, factory)
reactor.run()
|
Player.gif
