Some work.
[krufty_fps.git] / more_twisted.py
blobcd36d58d0e1ecdc9e6adc59db664b95ad9030d00
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 protocol_file = open('protocol.py')
26 exec(protocol_file)
27 protocol_file.close()
29 the_functions = {}
30 in_script = 0
32 import os, sys
33 from os import *
34 from os.path import *
36 import threading
37 from socket import *
38 from xml.dom.minidom import parse, parseString
39 from threading import Lock
40 from signal import *
41 from zipfile import *
43 from twisted.internet.protocol import DatagramProtocol
44 from twisted.internet import reactor
45 from twisted.internet import task
47 import pygame
48 from pygame import *
50 import pgu
51 from pgu import gui as pgui
53 import lamina
55 import OpenGL
56 import OpenGL.GL
57 from OpenGL.GL import *
58 import OpenGL.GLU
59 from OpenGL.GLU import *
61 import StringIO
63 def getBroadcast(ip):
64 global BROADCAST
65 BROADCAST = ip
67 print "getBroadcast(): Broadcast is reported to be", ip
68 return
70 reactor.resolve('<broadcast>').addCallback(getBroadcast)
72 the_event_receiver = 0
74 global the_engine
75 global the_client
77 class QueueLock:
78 def __init__(self):
80 self.items = []
81 self.items_lock = Lock()
83 def size(self):
85 return len(self.items)
87 def getItem(self):
89 self.items_lock.acquire()
90 the_item = self.items.pop(0)
91 self.items_lock.release()
93 return the_item
95 def addItem(self, new_item):
97 self.items_lock.acquire()
98 self.items.append(new_item)
99 self.items_lock.release()
101 return
103 class EventReceiver(QueueLock):
105 def getEvent(self):
106 return self.getItem()
107 def addEvent(self, event):
109 self.addItem(event)
110 return
112 class CommandLine(QueueLock):
114 def getCommand(self):
115 return self.getItem()
116 def addCommand(self, command):
117 self.addItem(command)
118 return
120 class Multicast(DatagramProtocol):
122 def startProtocol(self):
123 self.transport.joinGroup(MULTICAST)
125 def datagramReceived(self, datagram, address):
127 pass
129 class Client(DatagramProtocol):
131 def datagramReceived(self, data, (host, port)):
133 if data[:len(YOUTHERE)] == YOUTHERE:
135 # print "Client.datagramReceived(): Recieved YOUTHERE, responding with IMHERE"
136 self.transport.write(IMHERE, (host, port))
138 if data[:len(SERVEROFFER)] == SERVEROFFER:
140 split_strings = data.split()
142 self.servers[split_strings[2]] = (host, int(split_strings[1]))
144 event = [SERVEROFFER, {'server_name': split_strings[2],
145 'server_address': self.servers[split_strings[2]]}]
146 the_engine.events.addEvent(event)
148 print "Client.datagramReceived(): Received SERVEROFFER"
150 if data[:len(YOUREIN)] == YOUREIN:
152 if (host, port) == self.requested_server:
153 self.current_server = (host, port)
154 self.requested_server = ()
156 event = [YOUREIN]
157 data = {'server': self.current_server}
158 event.append(data)
160 the_engine.events.addEvent(event)
162 print "Client.datagramReceived(): Received YOUREIN, joined server"
164 return
166 if data[:len(LIST)] == LIST:
168 print "Client.datagramReceived(): Received LIST"
170 split_strings = data.split()
172 self.members = []
174 for string in split_strings:
175 if string != LIST:
176 self.members.append(string)
178 event = [LIST]
179 data = {'names': self.members, 'server_address': (host, port)}
180 event.append(data)
182 the_engine.events.addEvent(event)
184 return
186 if data[:len(SOMEONEJOINED)] == SOMEONEJOINED:
188 if (host, port) == self.current_server:
190 print "Client.datagramReceived(): Received SOMEONEJOINED"
192 left_member = ''
194 for member in self.members:
195 if member == data[len(SOMEONEJOINED) + 1:]:
196 left_member = member
198 if left_member == '':
199 self.members.append(data[len(SOMEONEJOINED) + 1:])
201 event = [SOMEONEJOINED]
202 data = {'name': data[len(SOMEONEJOINED) + 1:]}
204 event.append(data)
206 the_engine.events.addEvent(event)
208 return
210 if data[:len(SOMEONELEFT)] == SOMEONELEFT:
212 if (host, port) == self.current_server:
214 name = data[len(SOMEONELEFT) + 1:]
216 if name in self.members:
217 print "Client.datagramReceived(): Received SOMEONELEFT"
219 self.members.remove(name)
221 event = [SOMEONELEFT]
222 data = {'name': name}
224 event.append(data)
226 the_engine.events.addEvent(event)
228 else:
229 print "Client.datagramReceived(): Received SOMEONELEFT, but", name, "not present in roster"
231 return
233 if data[:len(YOUROUT)] == YOUROUT:
235 if (host, port) == self.current_server:
237 print "Client.datagramReceived(): Recieved YOUROUT"
239 self.current_server = ()
241 event = [YOUROUT]
242 data = {}
243 event.append(data)
245 the_engine.events.addEvent(event)
247 return
249 if data[:len(LETTER)] == LETTER:
251 if (host, port) == self.current_server:
252 print "Client.datagramReceived(): Received LETTER"
254 split_strings = data.split(':')
256 message = data[data.find(':', len(LETTER) + 1) + 1:]
257 message_origin = split_strings[1]
259 event = [LETTER]
260 data = {'message': message, 'origin': message_origin}
261 event.append(data)
263 the_engine.events.addEvent(event)
265 return
267 if data[:len(IMHERE)] == IMHERE:
269 if (host, port) == self.current_server:
270 print "Client.datagramReceived(): Received IMHERE from server"
272 self.server_request = 0
274 return
276 def init(self, params):
278 self.params = params
280 self.current_server = ()
281 self.requested_server = ()
282 self.servers = {}
284 self.inited = 1
286 return
288 def serverRequest(self):
290 if self.current_server != ():
292 if self.server_request > SERVER_TIMEOUT:
293 the_engine.events.addEvent([SERVER_GONE, {}])
294 self.current_server = ()
296 else:
297 self.server_request += 1
298 self.transport.write(YOUTHERE, self.current_server)
300 return
302 def executeCommand(self, command, data):
304 reactor.callFromThread(self.executeThreadedCommand, command, data)
306 return
308 def executeThreadedCommand(self, command, data):
309 if command == SERVERKILL:
311 if self.current_server != ():
313 message = ''.join([SERVERKILL, ' '])
315 if data.has_key('password'):
316 message = ''.join([message, data['password']])
318 self.transport.write(message, self.current_server)
320 if command == SERVERREQUEST:
322 message = ''.join([SERVERREQUEST, ' ', str(self.params['message_port'])])
324 the_multicast.transport.write(message, (MULTICAST, self.params['broadcast_port']))
325 # self.transport.write(message, ('255.255.255.255', self.params['broadcast_port']))
327 if command == GETLIST:
329 message = GETLIST
331 if data.has_key('server'):
333 if self.servers.has_key(data['server']):
334 self.transport.write(message, self.servers[data['server']])
336 else:
338 if self.current_server != ():
339 self.transport.write(message, self.current_server)
341 if command == IMOUT:
343 if self.current_server != ():
345 message = IMOUT
347 self.transport.write(message, self.current_server)
349 self.current_server = ()
351 if command == LETTER:
353 if self.current_server != ():
355 message = ''.join([LETTER, ':'])
357 for dest in data['destinations']:
358 if dest in self.members:
359 message = ''.join([message, ' ' , dest])
361 message = ''.join([message, ':', data['message']])
363 self.transport.write(message, self.current_server)
365 if command == WANTIN:
367 if data.has_key('server'):
368 if self.servers.has_key(data['server']):
370 self.transport.write(''.join([WANTIN, ' ', self.params['name']]),
371 self.servers[data['server']])
372 self.current_server = ()
373 self.requested_server = self.servers[data['server']]
375 return
377 class Engine:
379 def __init__(self, config):
381 self.config = config
382 self.running = 1
384 global the_engine
385 the_engine = self
387 video_flags = OPENGL|DOUBLEBUF
389 pygame.init()
390 self.display = pygame.display.set_mode(config['window_size'], video_flags)
392 self.font = pygame.font.SysFont("default", 18)
393 self.fontBig = pygame.font.SysFont("default", 24)
394 self.fontSub = pygame.font.SysFont("default", 20)
395 self.theme = pgui.Theme(['test_theme', 'gray', 'default'])
396 # self.theme = pgui.Theme('gray')
397 # self.theme = pgui.Theme('default')
399 self.resize((config['window_size']))
401 glShadeModel(GL_SMOOTH)
402 glClearColor(self.config['background_color'][0],
403 self.config['background_color'][1],
404 self.config['background_color'][2],
405 self.config['background_color'][3])
406 glClearDepth(1.0)
407 glEnable(GL_DEPTH_TEST)
408 glDepthFunc(GL_LEQUAL)
409 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
411 pygame.display.set_caption(config['window_title'])
413 self.gui_screen = lamina.LaminaScreenSurface()
415 self.app = pgui.App(theme=self.theme)
416 self.app._screen = self.gui_screen.surf
417 self.main_container = pgui.Container(width=config['window_size'][0])
419 self.files = {}
421 self.events = EventReceiver()
423 # self.files is a map of filename to file
425 # The file has this:
426 # {parent, [children], {object_defs},
427 # {menu_defs}, {object_instances}, {menu_instances}}
429 self.zipfiles = []
431 for file in listdir(self.config['pack_dir']):
432 if (is_zipfile(os.path.join(self.config['pack_dir'], file))):
433 self.zipfiles.append(ZipFile(os.path.join(self.config['pack_dir'], file)))
435 self.running = self.addFile(self.config['init'], '')
436 self.app.init(self.main_container)
438 self.ticks = pygame.time.get_ticks()
439 self.frames = 0
441 if self.running == 0:
442 print "Engine.__init__(): Failed adding initial file"
444 self.message_boxen = []
446 def run(self):
448 global the_client
450 while self.running:
452 self.process_events()
454 self.draw()
456 pygame.display.flip()
458 return
460 def updateFPS(self):
462 self.oldticks = self.ticks
463 self.ticks = pygame.time.get_ticks()
465 self.frames += 1
467 self.fps = (self.frames * 1000) / (self.ticks - self.oldticks) / 1000
469 pygame.display.set_caption(''.join([self.config['window_title'], ' ', str(self.fps)]))
471 return
473 def process_events(self):
475 change = 0
477 for e in pygame.event.get():
478 if e.type == QUIT:
479 self.running = 0
480 print "Should be quitting..."
482 self.killGame()
484 self.app.event((e))
485 change = self.app.update(self.gui_screen.surf)
487 if (change != 0):
488 self.gui_screen.refresh(change)
490 new_event = self.convertEvent(e)
491 self.events.addEvent(new_event)
493 iterating = 1
494 while iterating:
496 if self.events.size():
497 new_event = self.events.getEvent()
498 else:
499 iterating = 0
501 if not iterating:
502 return
504 if iterating:
505 for file in self.files.keys():
507 for name in self.files[file]['object_instances'].keys():
509 self.files[file]['object_instances'][name].event(new_event[0], new_event[1])
511 return
513 def convertEvent(self, e):
515 data = {}
517 if e.type == QUIT:
518 data['none'] = ''
520 if e.type == ACTIVEEVENT:
521 data['gain'] = e.gain
522 data['state'] = e.state
524 if e.type == KEYDOWN:
525 data['unicode'] = e.unicode
526 data['key'] = e.key
527 data['mod'] = e.mod
529 if e.type == KEYUP:
530 data['key'] = e.key
531 data['mod'] = e.mod
533 if e.type == MOUSEMOTION:
534 data['pos'] = e.pos
535 data['rel'] = e.rel
536 data['buttons'] = e.buttons
538 if e.type == MOUSEBUTTONUP:
539 data['pos'] = e.pos
540 data['button'] = e.button
542 if e.type == MOUSEBUTTONDOWN:
543 data['pos'] = e.pos
544 data['button'] = e.button
546 if e.type == JOYAXISMOTION:
547 data['joy'] = e.joy
548 data['axis'] = e.axis
549 data['value'] = e.value
551 if e.type == JOYBALLMOTION:
552 data['joy'] = e.joy
553 data['ball'] = e.ball
554 data['rel'] = e.rel
556 if e.type == JOYHATMOTION:
557 data['joy'] = e.joy
558 data['hat'] = e.hat
559 data['value'] = e.value
561 if e.type == JOYBUTTONUP:
562 data['joy'] = e.joy
563 data['button'] = e.button
565 if e.type == JOYBUTTONDOWN:
566 data['joy'] = e.joy
567 data['button'] = e.button
569 if e.type == VIDEORESIZE:
570 data['size'] = e.size
571 data['w'] = e.w
572 data['h'] = e.h
574 if e.type == VIDEOEXPOSE:
575 data['none'] = ''
577 if e.type == USEREVENT:
578 data['code'] = e.code
580 type = ''
582 if e.type == QUIT: type = "QUIT"
583 if e.type == ACTIVEEVENT: type = "ACTIVEEVENT"
584 if e.type == KEYDOWN: type = "KEYDOWN"
585 if e.type == KEYUP: type = "KEYUP"
586 if e.type == MOUSEMOTION : type = "MOUSEMOTION"
587 if e.type == MOUSEBUTTONUP: type = "MOUSEBUTTONUP"
588 if e.type == MOUSEBUTTONDOWN: type = "MOUSEBUTTONDOWN"
589 if e.type == JOYAXISMOTION: type = "JOYAXISMOTION"
590 if e.type == JOYBALLMOTION: type = "JOYBALLMOTION"
591 if e.type == JOYHATMOTION: type = "JOYHATMOTION"
592 if e.type == JOYBUTTONUP: type = "JOYBUTTONUP"
593 if e.type == JOYBUTTONDOWN: type = "JOYBUTTONDOWN"
594 if e.type == VIDEORESIZE: type = "VIDEORESIZE"
595 if e.type == VIDEOEXPOSE: type = "VIDEOEXPOSE"
596 if e.type == USEREVENT: type = "USEREVENT"
598 return [type, data]
600 def draw(self):
602 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
603 glLoadIdentity()
605 # draw stuff
607 glLoadIdentity()
608 self.gui_screen.display()
610 def resize(self, (width, height)):
611 if height==0:
612 height=1
613 glViewport(0, 0, width, height)
614 glMatrixMode(GL_PROJECTION)
615 glLoadIdentity()
616 gluPerspective(45, 1.0*width/height, 0.1, 100.0)
617 glMatrixMode(GL_MODELVIEW)
618 glLoadIdentity()
620 return
622 def addFile(self, filename, parent):
624 # Because I have alot of nesting in this function,
625 # I am using 2 space formatting
627 for zipfile in self.zipfiles:
629 for file in zipfile.namelist():
631 if (file == filename):
632 dom = parseString(zipfile.read(file))
634 object_instances_d = []
635 menu_instances = []
637 if dom.childNodes[0].nodeName == 'game':
638 self.files[filename] = {
639 'object_defs': {},
640 'children': [],
641 'parent': '',
642 'object_instances': {},
643 'menu_instances': {},
644 'menu_defs': {}}
646 for node in dom.childNodes[0].childNodes:
648 if (node.nodeName == 'def'):
650 for sub_node in node.childNodes:
652 if (sub_node.nodeName == 'object'):
654 temp_object_def = {}
656 for suber_node in sub_node.childNodes:
658 if (suber_node.nodeName == 'name'):
659 if len(suber_node.childNodes):
660 temp_object_def['name'] = suber_node.childNodes[0].nodeValue
662 if (suber_node.nodeName == 'script'):
663 if len(suber_node.childNodes):
664 temp_object_def['script'] = suber_node.childNodes[0].nodeValue
666 if (suber_node.nodeName == 'tangible'):
667 if len(suber_node.childNodes):
668 temp_object_def['tangible'] = suber_node.childNodes[0].nodeValue
670 if (suber_node.nodeName == 'type'):
671 if len(suber_node.childNodes):
672 temp_object_def['type'] = suber_node.childNodes[0].nodeValue
674 self.files[filename]['object_defs'][temp_object_def['name']] = temp_object_def
675 temp_object_def = {}
677 if (sub_node.nodeName == 'menu'):
679 temp_menu_def = {}
680 temp_menu_def['elements'] = {}
682 temp_element_set = {}
684 for suber_node in sub_node.childNodes:
686 if (suber_node.nodeName == 'name'):
687 temp_menu_def['name'] = suber_node.childNodes[0].nodeValue
689 if (suber_node.nodeName == 'elements'):
691 for suberer_node in suber_node.childNodes:
693 if (suberer_node.nodeType != 3 and suberer_node.nodeType != 8):
694 if (suberer_node.hasAttribute('name')):
695 temp_element_set['name'] = suberer_node.getAttribute('name')
697 if (suberer_node.hasAttribute('x')):
698 temp_element_set['x'] = int(suberer_node.getAttribute('x'))
700 if (suberer_node.hasAttribute('y')):
701 temp_element_set['y'] = int(suberer_node.getAttribute('y'))
703 if (suberer_node.hasAttribute('width')):
704 temp_element_set['width'] = int(suberer_node.getAttribute('width'))
706 if (suberer_node.hasAttribute('height')):
707 temp_element_set['height'] = int(suberer_node.getAttribute('height'))
709 if (suberer_node.hasAttribute('parent')):
710 temp_element_set['parent'] = suberer_node.getAttribute('parent')
712 if (suberer_node.hasAttribute('target')):
713 temp_element_set['target'] = suberer_node.getAttribute('target')
715 if (suberer_node.hasAttribute('text')):
716 temp_element_set['text'] = suberer_node.getAttribute('text')
718 temp_element_set['type'] = suberer_node.nodeName
719 temp_menu_def['elements'][temp_element_set['name']] = temp_element_set
720 temp_element_set = {}
722 self.files[filename]['menu_defs'][temp_menu_def['name']] = temp_menu_def
724 temp_menu_def = {}
725 temp_element_set = {}
727 if (node.nodeName == 'instance'):
729 for sub_node in node.childNodes:
731 if (sub_node.nodeName == 'object'):
732 object_instances_d.append(sub_node.childNodes[0].nodeValue)
734 if (sub_node.nodeName == 'menu'):
735 menu_instances.append(sub_node.childNodes[0].nodeValue)
737 if (parent != ''):
738 self.files[parent]['children'].append(filename)
739 self.files[filename]['parent'] = parent
741 # create instances
743 for menuname, menu_data in self.files[filename]['menu_defs'].iteritems():
744 self.files[filename]['menu_instances'][menuname] = Menu(menu_def=menu_data)
746 for menuname in menu_instances:
747 if (self.files[filename]['menu_instances'].has_key(menuname)):
748 self.files[filename]['menu_instances'][menuname].show()
750 for file in self.files.keys():
751 if self.files[file]['menu_instances'].has_key(menuname):
752 self.files[file]['menu_instances'][menuname].show()
754 for objectname in object_instances_d:
755 self.addObject(objectname)
757 return 1
758 return 0
759 # ending 2-space formatting
761 def removeFile(self, filename):
763 if (self.files.has_key(filename)):
765 for child in self.files[filename]['children']:
766 self.removeFile(child)
768 del self.files[filename]['children']
770 parent = self.files[filename]['parent']
772 self.files[parent]['children'].pop(self.files[parent]['children'].index(filename))
774 del self.files[filename]
776 return
778 def getVisibleMenus(self):
780 menus = {}
782 for file, contents in self.files.iteritems():
783 for name, menu in contents['menu_instances'].iteritems():
784 if not menu.hidden:
785 menus[name] = menu
787 return menus
789 def hideAllMenus(self):
791 for file, contents in self.files.iteritems():
792 for name, menu in contents['menu_instances'].iteritems():
793 menu.hide()
795 return
797 def showMenu(self, menu_name):
799 for file, contents in self.files.iteritems():
800 for name, menu in contents['menu_instances'].iteritems():
801 if contents['menu_instances'].has_key(menu_name):
802 contents['menu_instances'][menu_name].show()
804 return
806 def hideMenu(self, menu_name):
808 for file, contents in self.files:
809 for name, menu in contents['menu_instances'].iteritems():
810 if contents['menu_instances'].has_key(menu_name):
811 contents['menu_instances'][menu_name].hide()
813 return
815 def setMenu(self, menu_name):
817 self.hideAllMenus()
818 self.showMenu(menu_name)
820 return
822 def addObject(self, objectname):
824 for file in self.files.keys():
825 if self.files[file]['object_defs'].has_key(objectname):
826 self.files[file]['object_instances'][objectname] = GameObject(
827 self.files[file]['object_defs'][objectname])
829 return
831 def removeObject(self, objectname):
833 for file in self.files.keys():
834 if self.files[file]['object_defs'].has_key(objectname):
835 del self.files[file]['object_instances'][objectname]
837 return
839 def addListItem(self, menuname, item, data, dvalue):
841 for file in self.files:
842 if self.files[file]['menu_instances'].has_key(menuname):
843 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
844 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
846 the_widget.add(data.encode(), value=dvalue)
847 the_widget.resize()
848 the_widget.repaint()
850 return
852 def clearListItem(self, menuname, item):
854 for file in self.files:
855 if self.files[file]['menu_instances'].has_key(menuname):
856 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
857 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
859 the_widget.clear()
860 the_widget.resize()
861 the_widget.repaint()
863 return
865 def removeListItem(self, menuname, item, value):
867 for file in self.files:
868 if self.files[file]['menu_instances'].has_key(menuname):
869 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
870 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
872 the_widget.remove(value)
873 the_widget.resize()
874 the_widget.repaint()
876 return
878 def getListValue(self, menuname, item):
880 for file in self.files:
881 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 return the_widget.value
888 return ''
890 def getEditboxValue(self, menuname, item):
892 for file in self.files:
893 if self.files[file]['menu_instances'].has_key(menuname):
895 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
896 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
898 return the_widget.value
900 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
902 return the_widget.value
904 def setEditboxValue(self, menuname, item, new_value):
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 the_widget.value = new_value
914 return
916 def showMessageBox(self, message, title, width, height):
918 # Modify width and height to your liking
919 width = 400
920 height = 150
921 the_engine.messageBox(title, message)
923 return
925 def getImage(self, filename):
927 the_buf = pygame.image.load(self.getStringIOFile(filename))
929 return the_buf
931 def getStringIOFile(self, filename):
933 for zip_file in self.zipfiles:
934 for file in zip_file.namelist():
936 if (filename == file):
938 the_string_io = StringIO.StringIO()
939 print >>the_string_io, zip_file.read(file)
940 the_string_io.seek(0)
942 return the_string_io
943 return ''
945 def getStringData(self, filename):
946 for zip_file in self.zipfiles:
947 for file in zip_file.namelist():
949 if (filename == file):
950 return zip_file.read(file)
951 return ''
953 def killThreadGame(self):
955 reactor.stop()
957 return
959 def killGame(self):
961 reactor.callFromThread(self.killThreadGame)
963 return
965 class Menu:
967 def __init__(self, menu_def):
969 self.menu_def = menu_def
970 self.widgets = {}
972 for name, element in menu_def['elements'].iteritems():
974 multiplier_x = float(the_engine.config['window_size'][0]) / 100.00
975 multiplier_y = float(the_engine.config['window_size'][1]) / 100.00
977 dx = float(element['x']) * multiplier_x
978 dy = float(element['y']) * multiplier_y
980 dwidth = float(element['width']) * multiplier_x
981 dheight = float(element['height']) * multiplier_y
983 if (element['type'] == 'button'):
984 self.widgets[name] = pgui.Button(element['text'].encode(), width=dwidth, height=dheight)
985 self.widgets[name].connect(pgui.CLICK, self.clicked, name)
987 if (element['type'] == 'image'):
988 self.widgets[name] = pgui.Image(the_engine.getImage(element['text']))
990 if (element['type'] == 'label'):
991 self.widgets[name] = pgui.Label(element['text'])
993 if (element['type'] == 'listbox'):
994 self.widgets[name] = pgui.List(width=dwidth, height=dheight)
995 self.widgets[name].connect(pgui.CLICK, self.clicked, name)
997 if (element['type'] == 'editbox'):
998 self.widgets[name] = pgui.Input(value=element['text'], width=dwidth)
999 self.widgets[name].connect(pgui.KEYDOWN, self.key_pressed, name)
1000 self.widgets[name].connect(pgui.KEYUP, self.key_up, name)
1002 if (self.widgets.has_key(name)):
1003 self.widgets[name].resize(width=dwidth, height=dheight)
1004 else:
1005 print "Menu.__init__(): Widget type", element['type'], " not implemented yet, skipping."
1007 self.hidden = 1
1009 def show(self):
1011 global the_engine
1013 multiplier_x = float(the_engine.config['window_size'][0]) / 100.00
1014 multiplier_y = float(the_engine.config['window_size'][1]) / 100.00
1016 if (self.hidden == 1):
1017 for name, element in self.menu_def['elements'].iteritems():
1018 dx = float(element['x']) * multiplier_x
1019 dy = float(element['y']) * multiplier_y
1021 if self.widgets.has_key(name):
1022 the_engine.main_container.add(self.widgets[name], dx, dy)
1024 self.hidden = 0
1026 return
1028 def hide(self):
1030 global the_engine
1032 if (self.hidden != 1):
1033 for name, element in self.menu_def['elements'].iteritems():
1035 if (self.widgets.has_key(name)):
1036 the_engine.main_container.remove(self.widgets[name])
1038 self.hidden = 1
1040 return
1042 def clicked(self, widget, _event):
1044 if self.menu_def['elements'].has_key(widget):
1046 if self.menu_def['elements'][widget]['target'] != '':
1047 exec(self.menu_def['elements'][widget]['target'])
1049 the_engine.events.addEvent(['WIDGET_CLICKED',
1050 {'name': widget,
1051 'menu_name': self.menu_def['name'],
1052 event: the_engine.convertEvent(_event)}])
1054 return
1056 def key_pressed(self, widget, _event):
1058 if self.menu_def['elements'].has_key(widget):
1060 new_event = the_engine.convertEvent(_event)
1062 the_engine.events.addEvent(['KEYDOWN',
1063 {'name': widget,
1064 'menu_name': self.menu_def['name'],
1065 'event': new_event}])
1067 return
1069 def key_up(self, widget, _event):
1071 if self.menu_def['elements'].has_key(widget):
1073 the_engine.events.addEvent(['KEYUP',
1074 {'name': widget,
1075 'menu_name': self.menu_def['name'],
1076 event: the_engine.convertEvent(_event)}])
1078 return
1080 class MessageBox(pgui.Dialog):
1082 def __init__(self, title, message):
1084 self.title = pgui.Label(title)
1085 self.main = pgui.Label(message)
1087 return
1089 class Camera:
1091 def __init__(self):
1092 return
1094 class GameObject:
1096 def __init__(self, dmold):
1098 self.mold = dmold
1099 global the_functions
1100 global in_script
1102 if self.mold['script'] != '':
1104 in_script = 1
1106 the_file = the_engine.getStringData(self.mold['script'])
1107 if the_file != '':
1108 exec(the_file)
1110 in_script = 0
1111 self.my_functions = the_functions
1113 the_functions = {}
1115 def event(self, event, data):
1117 if self.my_functions.has_key(event):
1119 self.my_functions[event](data)
1121 return
1123 def main():
1124 # parse command line stuff
1126 if (len(sys.argv) > 1):
1127 config = sys.argv[1]
1128 else:
1129 print "main(): No config specified, using", CONFIG
1130 config = CONFIG
1132 configuration = parse_config(config)
1134 if (configuration.has_key('error') and configuration['error']):
1135 print "main(): Error in parsing config."
1137 the_event_receiver = EventReceiver()
1139 global client_params
1140 client_params = {'broadcast_port':configuration['broadcast_port'],
1141 'broadcast_bind':configuration['broadcast_bind'],
1142 'message_port':configuration['message_port'],
1143 'name':configuration['name'],
1144 'echo_time': configuration['echo_time']}
1146 global the_engine
1147 global the_client
1149 the_engine = Engine(configuration)
1151 the_client = Client()
1152 the_client_thread = threading.Thread(target=run_net)
1154 the_client.server_request = 0
1156 the_client.init(client_params)
1158 the_client_thread.start()
1159 the_engine.run()
1161 the_engine.killGame()
1163 sys.exit()
1165 the_client_thread.join()
1167 return
1169 def run_net():
1171 global client_params
1172 global the_multicast
1174 the_multicast = Multicast()
1175 config = client_params
1177 reactor.listenMulticast(config['broadcast_bind'], the_multicast)
1178 reactor.listenUDP(config['message_port'], the_client)
1180 echo_request = task.LoopingCall(the_client.serverRequest)
1182 if client_params['echo_time'] != None:
1183 echo_request.start(client_params['echo_time'])
1184 else:
1185 print "run_net(): No ECHO_TIME specified, using default of", ECHO_TIME
1186 echo_request.start(ECHO_TIME)
1188 reactor.run(installSignalHandlers=0)
1190 return
1192 def parse_config(filename):
1193 results = {'error': 1}
1195 if (exists(filename)):
1196 dom = parse(filename)
1197 else:
1198 print "parse_config():", filename, "doesn't exist."
1199 return results
1201 results = {'window_title': None,
1202 'log': None,
1203 'name': None,
1204 'font': None,
1205 'init': None,
1206 'message_port': None,
1207 'broadcast_port': None,
1208 'broadcast_bind': None,
1209 'fullscreen': None,
1210 'background_color': None,
1211 'window_size': None,
1212 'gravity': None,
1213 'step_size': None,
1214 'pack_dir': None,
1215 'echo_time': None}
1217 if (dom.childNodes[0].nodeName == 'config'):
1218 for node in dom.childNodes[0].childNodes:
1220 if (node.nodeName == 'window_title'):
1221 results['window_title'] = node.childNodes[0].nodeValue
1223 if (node.nodeName == 'log'):
1224 results['log'] = node.childNodes[0].nodeValue
1226 if (node.nodeName == 'name'):
1227 results['name'] = node.childNodes[0].nodeValue
1229 if (node.nodeName == 'font'):
1230 results['font'] = node.childNodes[0].nodeValue
1232 if (node.nodeName == 'init'):
1233 results['init'] = node.childNodes[0].nodeValue
1235 if (node.nodeName == 'message_port'):
1236 results['message_port'] = int(node.childNodes[0].nodeValue)
1238 if (node.nodeName == 'broadcast_port'):
1239 results['broadcast_port'] = int(node.childNodes[0].nodeValue)
1241 if (node.nodeName == 'broadcast_bind'):
1242 results['broadcast_bind'] = int(node.childNodes[0].nodeValue)
1244 if (node.nodeName == 'fullscreen'):
1245 results['fullscreen'] = int(node.childNodes[0].nodeValue)
1247 if (node.nodeName == 'background_color'):
1249 string_parts = node.childNodes[0].nodeValue.split()
1250 results['background_color'] = [float(string_parts[0]), float(string_parts[1])]
1251 results['background_color'].append(float(string_parts[2]))
1252 results['background_color'].append(float(string_parts[3]))
1254 if (node.nodeName == 'window_size'):
1256 string_parts = node.childNodes[0].nodeValue.split()
1257 results['window_size'] = ((int(string_parts[0]), int(string_parts[1])))
1259 if (node.nodeName == 'gravity'):
1261 string_parts = node.childNodes[0].nodeValue.split()
1262 results['gravity'] = [float(string_parts[0]), float(string_parts[1])]
1263 results['gravity'].append(float(string_parts[2]))
1265 if (node.nodeName == 'step_size'):
1266 results['step_size'] = float(node.childNodes[0].nodeValue)
1268 if (node.nodeName == 'pack_dir'):
1269 results['pack_dir'] = node.childNodes[0].nodeValue
1271 if (node.nodeName == 'echo_time'):
1272 results['echo_time'] = int(node.childNodes[0].nodeValue)
1274 results['error'] = 0
1276 return results
1278 if __name__ == '__main__':
1279 main()