Added a label to the widget, fiddled with the text rendering and cleaned
[krufty_fps.git] / more_twisted.py
blob7e4243347fb48a8c8de8e93e9c8e98a06a1f8f92
1 #!/usr/bin/python
3 # PyOpenGL + Pygame
5 CONFIG = 'game_config.xml'
7 WINDOW_SIZE = (640, 480)
8 WINDOW_CAPTION = "Testing stuff"
10 BROADCAST = 50030
11 BROADCAST_BIND = 50031
12 MESSAGE = 40030
14 BUFSIZE = 120
16 ECHO_TIME = 5
18 TIMEOUT = .1
20 BROADCAST = ''
21 MULTICAST = '234.0.0.1'
23 SERVER_TIMEOUT = 0
25 # this will change
27 SERVERREQUEST = "i_want_server"
28 SERVEROFFER = "Want_server?"
29 SERVERKILL = "DIE_server!!"
30 YOUTHERE = "you_there?"
31 IMHERE = "yeah,i'm_here"
32 WANTIN = "i_want_in"
33 YOUREIN = "urine"
34 IMOUT = "i_leave"
35 GETLIST = "get_list"
36 LIST = "peoples_on_server"
37 SOMEONEJOINED = "dude,someone_joined"
38 SOMEONELEFT = "someone_left"
39 YOUROUT = "get_lost_punk"
40 LETTER = "listen_to_me"
41 SERVER_GONE = 'its_gone'
43 the_functions = {}
44 in_script = 0
46 import os, sys
47 from os import *
48 from os.path import *
50 import threading
51 from socket import *
52 from xml.dom.minidom import parse, parseString
53 from threading import Lock
54 from signal import *
55 from zipfile import *
57 from twisted.internet.protocol import DatagramProtocol
58 from twisted.internet import reactor
59 from twisted.internet import task
61 import pygame
62 from pygame import *
64 import pgu
65 from pgu import gui as pgui
67 import lamina
69 import OpenGL
70 import OpenGL.GL
71 from OpenGL.GL import *
72 import OpenGL.GLU
73 from OpenGL.GLU import *
75 import StringIO
77 def getBroadcast(ip):
78 global BROADCAST
79 BROADCAST = ip
81 print "getBroadcast(): Broadcast is reported to be", ip
82 return
84 reactor.resolve('<broadcast>').addCallback(getBroadcast)
86 the_event_receiver = 0
88 global the_engine
89 global the_client
91 class QueueLock:
92 def __init__(self):
94 self.items = []
95 self.items_lock = Lock()
97 def size(self):
99 return len(self.items)
101 def getItem(self):
103 self.items_lock.acquire()
104 the_item = self.items.pop(0)
105 self.items_lock.release()
107 return the_item
109 def addItem(self, new_item):
111 self.items_lock.acquire()
112 self.items.append(new_item)
113 self.items_lock.release()
115 return
117 class EventReceiver(QueueLock):
119 def getEvent(self):
120 return self.getItem()
121 def addEvent(self, event):
123 self.addItem(event)
124 return
126 class CommandLine(QueueLock):
128 def getCommand(self):
129 return self.getItem()
130 def addCommand(self, command):
131 self.addItem(command)
132 return
134 class Multicast(DatagramProtocol):
136 def startProtocol(self):
137 self.transport.joinGroup(MULTICAST)
139 def datagramReceived(self, datagram, address):
141 pass
143 class Client(DatagramProtocol):
145 def datagramReceived(self, data, (host, port)):
147 if data[:len(YOUTHERE)] == YOUTHERE:
149 # print "Client.datagramReceived(): Recieved YOUTHERE, responding with IMHERE"
150 self.transport.write(IMHERE, (host, port))
152 if data[:len(SERVEROFFER)] == SERVEROFFER:
154 split_strings = data.split()
156 self.servers[split_strings[2]] = (host, int(split_strings[1]))
158 event = [SERVEROFFER, {'server_name': split_strings[2],
159 'server_address': self.servers[split_strings[2]]}]
160 the_engine.events.addEvent(event)
162 print "Client.datagramReceived(): Received SERVEROFFER"
164 if data[:len(YOUREIN)] == YOUREIN:
166 if (host, port) == self.requested_server:
167 self.current_server = (host, port)
168 self.requested_server = ()
170 event = [YOUREIN]
171 data = {'server': self.current_server}
172 event.append(data)
174 the_engine.events.addEvent(event)
176 print "Client.datagramReceived(): Received YOUREIN, joined server"
178 return
180 if data[:len(LIST)] == LIST:
182 print "Client.datagramReceived(): Received LIST"
184 split_strings = data.split()
186 self.members = []
188 for string in split_strings:
189 if string != LIST:
190 self.members.append(string)
192 event = [LIST]
193 data = {'names': self.members, 'server_address': (host, port)}
194 event.append(data)
196 the_engine.events.addEvent(event)
198 return
200 if data[:len(SOMEONEJOINED)] == SOMEONEJOINED:
202 if (host, port) == self.current_server:
204 print "Client.datagramReceived(): Received SOMEONEJOINED"
206 left_member = ''
208 for member in self.members:
209 if member == data[len(SOMEONEJOINED) + 1:]:
210 left_member = member
212 if left_member == '':
213 self.members.append(data[len(SOMEONEJOINED) + 1:])
215 event = [SOMEONEJOINED]
216 data = {'name': data[len(SOMEONEJOINED) + 1:]}
218 event.append(data)
220 the_engine.events.addEvent(event)
222 return
224 if data[:len(SOMEONELEFT)] == SOMEONELEFT:
226 if (host, port) == self.current_server:
228 name = data[len(SOMEONELEFT) + 1:]
230 if name in self.members:
231 print "Client.datagramReceived(): Received SOMEONELEFT"
233 self.members.remove(name)
235 event = [SOMEONELEFT]
236 data = {'name': name}
238 event.append(data)
240 the_engine.events.addEvent(event)
242 else:
243 print "Client.datagramReceived(): Received SOMEONELEFT, but", name, "not present in roster"
245 return
247 if data[:len(YOUROUT)] == YOUROUT:
249 if (host, port) == self.current_server:
251 print "Client.datagramReceived(): Recieved YOUROUT"
253 self.current_server = ()
255 event = [YOUROUT]
256 data = {}
257 event.append(data)
259 the_engine.events.addEvent(event)
261 return
263 if data[:len(LETTER)] == LETTER:
265 if (host, port) == self.current_server:
266 print "Client.datagramReceived(): Received LETTER"
268 split_strings = data.split(':')
270 message = data[data.find(':', len(LETTER) + 1) + 1:]
271 message_origin = split_strings[1]
273 event = [LETTER]
274 data = {'message': message, 'origin': message_origin}
275 event.append(data)
277 the_engine.events.addEvent(event)
279 return
281 if data[:len(IMHERE)] == IMHERE:
283 if (host, port) == self.current_server:
284 print "Client.datagramReceived(): Received IMHERE from server"
286 self.server_request = 0
288 return
290 def init(self, params):
292 self.params = params
294 self.current_server = ()
295 self.requested_server = ()
296 self.servers = {}
298 self.inited = 1
300 return
302 def serverRequest(self):
304 if self.current_server != ():
306 if self.server_request > SERVER_TIMEOUT:
307 the_engine.events.addEvent([SERVER_GONE, {}])
308 self.current_server = ()
310 else:
311 self.server_request += 1
312 self.transport.write(YOUTHERE, self.current_server)
314 return
316 def executeCommand(self, command, data):
318 reactor.callFromThread(self.executeThreadedCommand, command, data)
320 return
322 def executeThreadedCommand(self, command, data):
323 if command == SERVERKILL:
325 if self.current_server != ():
327 message = ''.join([SERVERKILL, ' '])
329 if data.has_key('password'):
330 message = ''.join([message, data['password']])
332 self.transport.write(message, self.current_server)
334 if command == SERVERREQUEST:
336 message = ''.join([SERVERREQUEST, ' ', str(self.params['message_port'])])
338 the_multicast.transport.write(message, (MULTICAST, self.params['broadcast_port']))
339 # self.transport.write(message, ('255.255.255.255', self.params['broadcast_port']))
341 if command == GETLIST:
343 message = GETLIST
345 if data.has_key('server'):
347 if self.servers.has_key(data['server']):
348 self.transport.write(message, self.servers[data['server']])
350 else:
352 if self.current_server != ():
353 self.transport.write(message, self.current_server)
355 if command == IMOUT:
357 if self.current_server != ():
359 message = IMOUT
361 self.transport.write(message, self.current_server)
363 self.current_server = ()
365 if command == LETTER:
367 if self.current_server != ():
369 message = ''.join([LETTER, ':'])
371 for dest in data['destinations']:
372 if dest in self.members:
373 message = ''.join([message, ' ' , dest])
375 message = ''.join([message, ':', data['message']])
377 self.transport.write(message, self.current_server)
379 if command == WANTIN:
381 if data.has_key('server'):
382 if self.servers.has_key(data['server']):
384 self.transport.write(''.join([WANTIN, ' ', self.params['name']]),
385 self.servers[data['server']])
386 self.current_server = ()
387 self.requested_server = self.servers[data['server']]
389 return
391 class Engine:
393 def __init__(self, config):
395 self.config = config
396 self.running = 1
398 global the_engine
399 the_engine = self
401 video_flags = OPENGL|DOUBLEBUF
403 pygame.init()
404 self.display = pygame.display.set_mode(config['window_size'], video_flags)
406 self.font = pygame.font.SysFont("default", 18)
407 self.fontBig = pygame.font.SysFont("default", 24)
408 self.fontSub = pygame.font.SysFont("default", 20)
409 self.theme = pgui.Theme(['test_theme', 'gray', 'default'])
410 # self.theme = pgui.Theme('gray')
411 # self.theme = pgui.Theme('default')
413 self.resize((config['window_size']))
415 glShadeModel(GL_SMOOTH)
416 glClearColor(self.config['background_color'][0],
417 self.config['background_color'][1],
418 self.config['background_color'][2],
419 self.config['background_color'][3])
420 glClearDepth(1.0)
421 glEnable(GL_DEPTH_TEST)
422 glDepthFunc(GL_LEQUAL)
423 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
425 pygame.display.set_caption(config['window_title'])
427 self.gui_screen = lamina.LaminaScreenSurface()
429 self.app = pgui.App(theme=self.theme)
430 self.app._screen = self.gui_screen.surf
431 self.main_container = pgui.Container(width=config['window_size'][0])
433 self.files = {}
435 self.events = EventReceiver()
437 # self.files is a map of filename to file
439 # The file has this:
440 # {parent, [children], {object_defs},
441 # {menu_defs}, {object_instances}, {menu_instances}}
443 self.zipfiles = []
445 for file in listdir(self.config['pack_dir']):
446 if (is_zipfile(os.path.join(self.config['pack_dir'], file))):
447 self.zipfiles.append(ZipFile(os.path.join(self.config['pack_dir'], file)))
449 self.running = self.addFile(self.config['init'], '')
450 self.app.init(self.main_container)
452 self.ticks = pygame.time.get_ticks()
453 self.frames = 0
455 if self.running == 0:
456 print "Engine.__init__(): Failed adding initial file"
458 self.message_boxen = []
460 def run(self):
462 global the_client
464 while self.running:
466 self.process_events()
468 self.draw()
470 pygame.display.flip()
472 return
474 def updateFPS(self):
476 self.oldticks = self.ticks
477 self.ticks = pygame.time.get_ticks()
479 self.frames += 1
481 self.fps = (self.frames * 1000) / (self.ticks - self.oldticks) / 1000
483 pygame.display.set_caption(''.join([self.config['window_title'], ' ', str(self.fps)]))
485 return
487 def process_events(self):
489 change = 0
491 for e in pygame.event.get():
492 if e.type == QUIT:
493 self.running = 0
494 print "Should be quitting..."
496 self.killGame()
498 self.app.event((e))
499 change = self.app.update(self.gui_screen.surf)
501 if (change != 0):
502 self.gui_screen.refresh(change)
504 new_event = self.convertEvent(e)
505 self.events.addEvent(new_event)
507 iterating = 1
508 while iterating:
510 if self.events.size():
511 new_event = self.events.getEvent()
512 else:
513 iterating = 0
515 if not iterating:
516 return
518 if iterating:
519 for file in self.files.keys():
521 for name in self.files[file]['object_instances'].keys():
523 self.files[file]['object_instances'][name].event(new_event[0], new_event[1])
525 return
527 def convertEvent(self, e):
529 data = {}
531 if e.type == QUIT:
532 data['none'] = ''
534 if e.type == ACTIVEEVENT:
535 data['gain'] = e.gain
536 data['state'] = e.state
538 if e.type == KEYDOWN:
539 data['unicode'] = e.unicode
540 data['key'] = e.key
541 data['mod'] = e.mod
543 if e.type == KEYUP:
544 data['key'] = e.key
545 data['mod'] = e.mod
547 if e.type == MOUSEMOTION:
548 data['pos'] = e.pos
549 data['rel'] = e.rel
550 data['buttons'] = e.buttons
552 if e.type == MOUSEBUTTONUP:
553 data['pos'] = e.pos
554 data['button'] = e.button
556 if e.type == MOUSEBUTTONDOWN:
557 data['pos'] = e.pos
558 data['button'] = e.button
560 if e.type == JOYAXISMOTION:
561 data['joy'] = e.joy
562 data['axis'] = e.axis
563 data['value'] = e.value
565 if e.type == JOYBALLMOTION:
566 data['joy'] = e.joy
567 data['ball'] = e.ball
568 data['rel'] = e.rel
570 if e.type == JOYHATMOTION:
571 data['joy'] = e.joy
572 data['hat'] = e.hat
573 data['value'] = e.value
575 if e.type == JOYBUTTONUP:
576 data['joy'] = e.joy
577 data['button'] = e.button
579 if e.type == JOYBUTTONDOWN:
580 data['joy'] = e.joy
581 data['button'] = e.button
583 if e.type == VIDEORESIZE:
584 data['size'] = e.size
585 data['w'] = e.w
586 data['h'] = e.h
588 if e.type == VIDEOEXPOSE:
589 data['none'] = ''
591 if e.type == USEREVENT:
592 data['code'] = e.code
594 type = ''
596 if e.type == QUIT: type = "QUIT"
597 if e.type == ACTIVEEVENT: type = "ACTIVEEVENT"
598 if e.type == KEYDOWN: type = "KEYDOWN"
599 if e.type == KEYUP: type = "KEYUP"
600 if e.type == MOUSEMOTION : type = "MOUSEMOTION"
601 if e.type == MOUSEBUTTONUP: type = "MOUSEBUTTONUP"
602 if e.type == MOUSEBUTTONDOWN: type = "MOUSEBUTTONDOWN"
603 if e.type == JOYAXISMOTION: type = "JOYAXISMOTION"
604 if e.type == JOYBALLMOTION: type = "JOYBALLMOTION"
605 if e.type == JOYHATMOTION: type = "JOYHATMOTION"
606 if e.type == JOYBUTTONUP: type = "JOYBUTTONUP"
607 if e.type == JOYBUTTONDOWN: type = "JOYBUTTONDOWN"
608 if e.type == VIDEORESIZE: type = "VIDEORESIZE"
609 if e.type == VIDEOEXPOSE: type = "VIDEOEXPOSE"
610 if e.type == USEREVENT: type = "USEREVENT"
612 return [type, data]
614 def draw(self):
616 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
617 glLoadIdentity()
619 # draw stuff
621 glLoadIdentity()
622 self.gui_screen.display()
624 def resize(self, (width, height)):
625 if height==0:
626 height=1
627 glViewport(0, 0, width, height)
628 glMatrixMode(GL_PROJECTION)
629 glLoadIdentity()
630 gluPerspective(45, 1.0*width/height, 0.1, 100.0)
631 glMatrixMode(GL_MODELVIEW)
632 glLoadIdentity()
634 return
636 def addFile(self, filename, parent):
638 # Because I have alot of nesting in this function,
639 # I am using 2 space formatting
641 for zipfile in self.zipfiles:
643 for file in zipfile.namelist():
645 if (file == filename):
646 dom = parseString(zipfile.read(file))
648 object_instances_d = []
649 menu_instances = []
651 if dom.childNodes[0].nodeName == 'game':
652 self.files[filename] = {
653 'object_defs': {},
654 'children': [],
655 'parent': '',
656 'object_instances': {},
657 'menu_instances': {},
658 'menu_defs': {}}
660 for node in dom.childNodes[0].childNodes:
662 if (node.nodeName == 'def'):
664 for sub_node in node.childNodes:
666 if (sub_node.nodeName == 'object'):
668 temp_object_def = {}
670 for suber_node in sub_node.childNodes:
672 if (suber_node.nodeName == 'name'):
673 if len(suber_node.childNodes):
674 temp_object_def['name'] = suber_node.childNodes[0].nodeValue
676 if (suber_node.nodeName == 'script'):
677 if len(suber_node.childNodes):
678 temp_object_def['script'] = suber_node.childNodes[0].nodeValue
680 if (suber_node.nodeName == 'tangible'):
681 if len(suber_node.childNodes):
682 temp_object_def['tangible'] = suber_node.childNodes[0].nodeValue
684 if (suber_node.nodeName == 'type'):
685 if len(suber_node.childNodes):
686 temp_object_def['type'] = suber_node.childNodes[0].nodeValue
688 self.files[filename]['object_defs'][temp_object_def['name']] = temp_object_def
689 temp_object_def = {}
691 if (sub_node.nodeName == 'menu'):
693 temp_menu_def = {}
694 temp_menu_def['elements'] = {}
696 temp_element_set = {}
698 for suber_node in sub_node.childNodes:
700 if (suber_node.nodeName == 'name'):
701 temp_menu_def['name'] = suber_node.childNodes[0].nodeValue
703 if (suber_node.nodeName == 'elements'):
705 for suberer_node in suber_node.childNodes:
707 if (suberer_node.nodeType != 3 and suberer_node.nodeType != 8):
708 if (suberer_node.hasAttribute('name')):
709 temp_element_set['name'] = suberer_node.getAttribute('name')
711 if (suberer_node.hasAttribute('x')):
712 temp_element_set['x'] = int(suberer_node.getAttribute('x'))
714 if (suberer_node.hasAttribute('y')):
715 temp_element_set['y'] = int(suberer_node.getAttribute('y'))
717 if (suberer_node.hasAttribute('width')):
718 temp_element_set['width'] = int(suberer_node.getAttribute('width'))
720 if (suberer_node.hasAttribute('height')):
721 temp_element_set['height'] = int(suberer_node.getAttribute('height'))
723 if (suberer_node.hasAttribute('parent')):
724 temp_element_set['parent'] = suberer_node.getAttribute('parent')
726 if (suberer_node.hasAttribute('target')):
727 temp_element_set['target'] = suberer_node.getAttribute('target')
729 if (suberer_node.hasAttribute('text')):
730 temp_element_set['text'] = suberer_node.getAttribute('text')
732 temp_element_set['type'] = suberer_node.nodeName
733 temp_menu_def['elements'][temp_element_set['name']] = temp_element_set
734 temp_element_set = {}
736 self.files[filename]['menu_defs'][temp_menu_def['name']] = temp_menu_def
738 temp_menu_def = {}
739 temp_element_set = {}
741 if (node.nodeName == 'instance'):
743 for sub_node in node.childNodes:
745 if (sub_node.nodeName == 'object'):
746 object_instances_d.append(sub_node.childNodes[0].nodeValue)
748 if (sub_node.nodeName == 'menu'):
749 menu_instances.append(sub_node.childNodes[0].nodeValue)
751 if (parent != ''):
752 self.files[parent]['children'].append(filename)
753 self.files[filename]['parent'] = parent
755 # create instances
757 for menuname, menu_data in self.files[filename]['menu_defs'].iteritems():
758 self.files[filename]['menu_instances'][menuname] = Menu(menu_def=menu_data)
760 for menuname in menu_instances:
761 if (self.files[filename]['menu_instances'].has_key(menuname)):
762 self.files[filename]['menu_instances'][menuname].show()
764 for file in self.files.keys():
765 if self.files[file]['menu_instances'].has_key(menuname):
766 self.files[file]['menu_instances'][menuname].show()
768 for objectname in object_instances_d:
769 self.addObject(objectname)
771 return 1
772 return 0
773 # ending 2-space formatting
775 def removeFile(self, filename):
777 if (self.files.has_key(filename)):
779 for child in self.files[filename]['children']:
780 self.removeFile(child)
782 del self.files[filename]['children']
784 parent = self.files[filename]['parent']
786 self.files[parent]['children'].pop(self.files[parent]['children'].index(filename))
788 del self.files[filename]
790 return
792 def getVisibleMenus(self):
794 menus = {}
796 for file, contents in self.files.iteritems():
797 for name, menu in contents['menu_instances'].iteritems():
798 if not menu.hidden:
799 menus[name] = menu
801 return menus
803 def hideAllMenus(self):
805 for file, contents in self.files.iteritems():
806 for name, menu in contents['menu_instances'].iteritems():
807 menu.hide()
809 return
811 def showMenu(self, menu_name):
813 for file, contents in self.files.iteritems():
814 for name, menu in contents['menu_instances'].iteritems():
815 if contents['menu_instances'].has_key(menu_name):
816 contents['menu_instances'][menu_name].show()
818 return
820 def hideMenu(self, menu_name):
822 for file, contents in self.files:
823 for name, menu in contents['menu_instances'].iteritems():
824 if contents['menu_instances'].has_key(menu_name):
825 contents['menu_instances'][menu_name].hide()
827 return
829 def setMenu(self, menu_name):
831 self.hideAllMenus()
832 self.showMenu(menu_name)
834 return
836 def addObject(self, objectname):
838 for file in self.files.keys():
839 if self.files[file]['object_defs'].has_key(objectname):
840 self.files[file]['object_instances'][objectname] = GameObject(
841 self.files[file]['object_defs'][objectname])
843 return
845 def removeObject(self, objectname):
847 for file in self.files.keys():
848 if self.files[file]['object_defs'].has_key(objectname):
849 del self.files[file]['object_instances'][objectname]
851 return
853 def addListItem(self, menuname, item, data, dvalue):
855 for file in self.files:
856 if self.files[file]['menu_instances'].has_key(menuname):
857 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
858 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
860 the_widget.add(data.encode(), value=dvalue)
861 the_widget.resize()
862 the_widget.repaint()
864 return
866 def clearListItem(self, menuname, item):
868 for file in self.files:
869 if self.files[file]['menu_instances'].has_key(menuname):
870 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
871 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
873 the_widget.clear()
874 the_widget.resize()
875 the_widget.repaint()
877 return
879 def removeListItem(self, menuname, item, value):
881 for file in self.files:
882 if self.files[file]['menu_instances'].has_key(menuname):
883 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
884 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
886 the_widget.remove(value)
887 the_widget.resize()
888 the_widget.repaint()
890 return
892 def getListValue(self, menuname, item):
894 for file in self.files:
895 if self.files[file]['menu_instances'].has_key(menuname):
897 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
898 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
900 return the_widget.value
902 return ''
904 def getEditboxValue(self, menuname, item):
906 for file in self.files:
907 if self.files[file]['menu_instances'].has_key(menuname):
909 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
910 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
912 return the_widget.value
914 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
916 return the_widget.value
918 def setEditboxValue(self, menuname, item, new_value):
920 for file in self.files:
921 if self.files[file]['menu_instances'].has_key(menuname):
923 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
924 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
926 the_widget.value = new_value
928 return
930 def showMessageBox(self, message, title, width, height):
932 # Modify width and height to your liking
933 width = 400
934 height = 150
935 the_engine.messageBox(title, message)
937 return
939 def getImage(self, filename):
941 the_buf = pygame.image.load(self.getStringIOFile(filename))
943 return the_buf
945 def getStringIOFile(self, filename):
947 for zip_file in self.zipfiles:
948 for file in zip_file.namelist():
950 if (filename == file):
952 the_string_io = StringIO.StringIO()
953 print >>the_string_io, zip_file.read(file)
954 the_string_io.seek(0)
956 return the_string_io
957 return ''
959 def getStringData(self, filename):
960 for zip_file in self.zipfiles:
961 for file in zip_file.namelist():
963 if (filename == file):
964 return zip_file.read(file)
965 return ''
967 def killThreadGame(self):
969 reactor.stop()
971 return
973 def killGame(self):
975 reactor.callFromThread(self.killThreadGame)
977 return
979 class Menu:
981 def __init__(self, menu_def):
983 self.menu_def = menu_def
984 self.widgets = {}
986 for name, element in menu_def['elements'].iteritems():
988 multiplier_x = float(the_engine.config['window_size'][0]) / 100.00
989 multiplier_y = float(the_engine.config['window_size'][1]) / 100.00
991 dx = float(element['x']) * multiplier_x
992 dy = float(element['y']) * multiplier_y
994 dwidth = float(element['width']) * multiplier_x
995 dheight = float(element['height']) * multiplier_y
997 if (element['type'] == 'button'):
998 self.widgets[name] = pgui.Button(element['text'].encode(), width=dwidth, height=dheight)
999 self.widgets[name].connect(pgui.CLICK, self.clicked, name)
1001 if (element['type'] == 'image'):
1002 self.widgets[name] = pgui.Image(the_engine.getImage(element['text']))
1004 if (element['type'] == 'label'):
1005 self.widgets[name] = pgui.Label(element['text'])
1007 if (element['type'] == 'listbox'):
1008 self.widgets[name] = pgui.List(width=dwidth, height=dheight)
1009 self.widgets[name].connect(pgui.CLICK, self.clicked, name)
1011 if (element['type'] == 'editbox'):
1012 self.widgets[name] = pgui.Input(value=element['text'], width=dwidth)
1013 self.widgets[name].connect(pgui.KEYDOWN, self.key_pressed, name)
1014 self.widgets[name].connect(pgui.KEYUP, self.key_up, name)
1016 if (self.widgets.has_key(name)):
1017 self.widgets[name].resize(width=dwidth, height=dheight)
1018 else:
1019 print "Menu.__init__(): Widget type", element['type'], " not implemented yet, skipping."
1021 self.hidden = 1
1023 def show(self):
1025 global the_engine
1027 multiplier_x = float(the_engine.config['window_size'][0]) / 100.00
1028 multiplier_y = float(the_engine.config['window_size'][1]) / 100.00
1030 if (self.hidden == 1):
1031 for name, element in self.menu_def['elements'].iteritems():
1032 dx = float(element['x']) * multiplier_x
1033 dy = float(element['y']) * multiplier_y
1035 if self.widgets.has_key(name):
1036 the_engine.main_container.add(self.widgets[name], dx, dy)
1038 self.hidden = 0
1040 return
1042 def hide(self):
1044 global the_engine
1046 if (self.hidden != 1):
1047 for name, element in self.menu_def['elements'].iteritems():
1049 if (self.widgets.has_key(name)):
1050 the_engine.main_container.remove(self.widgets[name])
1052 self.hidden = 1
1054 return
1056 def clicked(self, widget, _event):
1058 if self.menu_def['elements'].has_key(widget):
1060 if self.menu_def['elements'][widget]['target'] != '':
1061 exec(self.menu_def['elements'][widget]['target'])
1063 the_engine.events.addEvent(['WIDGET_CLICKED',
1064 {'name': widget,
1065 'menu_name': self.menu_def['name'],
1066 event: the_engine.convertEvent(_event)}])
1068 return
1070 def key_pressed(self, widget, _event):
1072 if self.menu_def['elements'].has_key(widget):
1074 new_event = the_engine.convertEvent(_event)
1076 the_engine.events.addEvent(['KEYDOWN',
1077 {'name': widget,
1078 'menu_name': self.menu_def['name'],
1079 'event': new_event}])
1081 return
1083 def key_up(self, widget, _event):
1085 if self.menu_def['elements'].has_key(widget):
1087 the_engine.events.addEvent(['KEYUP',
1088 {'name': widget,
1089 'menu_name': self.menu_def['name'],
1090 event: the_engine.convertEvent(_event)}])
1092 return
1094 class MessageBox(pgui.Dialog):
1096 def __init__(self, title, message):
1098 self.title = pgui.Label(title)
1099 self.main = pgui.Label(message)
1101 return
1103 class Camera:
1105 def __init__(self):
1106 return
1108 class GameObject:
1110 def __init__(self, dmold):
1112 self.mold = dmold
1113 global the_functions
1114 global in_script
1116 if self.mold['script'] != '':
1118 in_script = 1
1120 the_file = the_engine.getStringData(self.mold['script'])
1121 if the_file != '':
1122 exec(the_file)
1124 in_script = 0
1125 self.my_functions = the_functions
1127 the_functions = {}
1129 def event(self, event, data):
1131 if self.my_functions.has_key(event):
1133 self.my_functions[event](data)
1135 return
1137 def main():
1138 # parse command line stuff
1140 if (len(sys.argv) > 1):
1141 config = sys.argv[1]
1142 else:
1143 print "main(): No config specified, using", CONFIG
1144 config = CONFIG
1146 configuration = parse_config(config)
1148 if (configuration.has_key('error') and configuration['error']):
1149 print "main(): Error in parsing config."
1151 the_event_receiver = EventReceiver()
1153 global client_params
1154 client_params = {'broadcast_port':configuration['broadcast_port'],
1155 'broadcast_bind':configuration['broadcast_bind'],
1156 'message_port':configuration['message_port'],
1157 'name':configuration['name'],
1158 'echo_time': configuration['echo_time']}
1160 global the_engine
1161 global the_client
1163 the_engine = Engine(configuration)
1165 the_client = Client()
1166 the_client_thread = threading.Thread(target=run_net)
1168 the_client.server_request = 0
1170 the_client.init(client_params)
1172 the_client_thread.start()
1173 the_engine.run()
1175 the_engine.killGame()
1177 sys.exit()
1179 the_client_thread.join()
1181 return
1183 def run_net():
1185 global client_params
1186 global the_multicast
1188 the_multicast = Multicast()
1189 config = client_params
1191 reactor.listenMulticast(config['broadcast_bind'], the_multicast)
1192 reactor.listenUDP(config['message_port'], the_client)
1194 echo_request = task.LoopingCall(the_client.serverRequest)
1196 if client_params['echo_time'] != None:
1197 echo_request.start(client_params['echo_time'])
1198 else:
1199 print "run_net(): No ECHO_TIME specified, using default of", ECHO_TIME
1200 echo_request.start(ECHO_TIME)
1202 reactor.run(installSignalHandlers=0)
1204 return
1206 def parse_config(filename):
1207 results = {'error': 1}
1209 if (exists(filename)):
1210 dom = parse(filename)
1211 else:
1212 print "parse_config():", filename, "doesn't exist."
1213 return results
1215 results = {'window_title': None,
1216 'log': None,
1217 'name': None,
1218 'font': None,
1219 'init': None,
1220 'message_port': None,
1221 'broadcast_port': None,
1222 'broadcast_bind': None,
1223 'fullscreen': None,
1224 'background_color': None,
1225 'window_size': None,
1226 'gravity': None,
1227 'step_size': None,
1228 'pack_dir': None,
1229 'echo_time': None}
1231 if (dom.childNodes[0].nodeName == 'config'):
1232 for node in dom.childNodes[0].childNodes:
1234 if (node.nodeName == 'window_title'):
1235 results['window_title'] = node.childNodes[0].nodeValue
1237 if (node.nodeName == 'log'):
1238 results['log'] = node.childNodes[0].nodeValue
1240 if (node.nodeName == 'name'):
1241 results['name'] = node.childNodes[0].nodeValue
1243 if (node.nodeName == 'font'):
1244 results['font'] = node.childNodes[0].nodeValue
1246 if (node.nodeName == 'init'):
1247 results['init'] = node.childNodes[0].nodeValue
1249 if (node.nodeName == 'message_port'):
1250 results['message_port'] = int(node.childNodes[0].nodeValue)
1252 if (node.nodeName == 'broadcast_port'):
1253 results['broadcast_port'] = int(node.childNodes[0].nodeValue)
1255 if (node.nodeName == 'broadcast_bind'):
1256 results['broadcast_bind'] = int(node.childNodes[0].nodeValue)
1258 if (node.nodeName == 'fullscreen'):
1259 results['fullscreen'] = int(node.childNodes[0].nodeValue)
1261 if (node.nodeName == 'background_color'):
1263 string_parts = node.childNodes[0].nodeValue.split()
1264 results['background_color'] = [float(string_parts[0]), float(string_parts[1])]
1265 results['background_color'].append(float(string_parts[2]))
1266 results['background_color'].append(float(string_parts[3]))
1268 if (node.nodeName == 'window_size'):
1270 string_parts = node.childNodes[0].nodeValue.split()
1271 results['window_size'] = ((int(string_parts[0]), int(string_parts[1])))
1273 if (node.nodeName == 'gravity'):
1275 string_parts = node.childNodes[0].nodeValue.split()
1276 results['gravity'] = [float(string_parts[0]), float(string_parts[1])]
1277 results['gravity'].append(float(string_parts[2]))
1279 if (node.nodeName == 'step_size'):
1280 results['step_size'] = float(node.childNodes[0].nodeValue)
1282 if (node.nodeName == 'pack_dir'):
1283 results['pack_dir'] = node.childNodes[0].nodeValue
1285 if (node.nodeName == 'echo_time'):
1286 results['echo_time'] = int(node.childNodes[0].nodeValue)
1288 results['error'] = 0
1290 return results
1292 if __name__ == '__main__':
1293 main()