In a fit of anger, I started my own gui system.
[krufty_fps.git] / more_twisted.py
blob84fdcd2d894f242b87d30fa2c31b71584c21db58
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 # debug
48 class debug:
50 def draw(self):
51 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
52 glLoadIdentity()
54 glTranslatef(-1.5, 0.0, -6.0)
56 glBegin(GL_TRIANGLES)
57 glColor3f(1.0, 0.0, 0.0)
58 glVertex3f(0.0, 1.0, 0.0)
59 glColor3f(0.0, 1.0, 0.0)
60 glVertex3f(-1.0, -1.0, 0)
61 glColor3f(0.0, 0.0, 1.0)
62 glVertex3f(1.0, -1.0, 0)
63 glEnd()
65 glTranslatef(3.0, 0.0, 0.0)
67 glColor3f(0.5, 0.5, 1.0)
68 glBegin(GL_QUADS)
69 glVertex3f(-1.0, 1.0, 0)
70 glVertex3f(1.0, 1.0, 0)
71 glVertex3f(1.0, -1.0, 0)
72 glVertex3f(-1.0, -1.0, 0)
73 glEnd()
75 return
76 global debug_it
77 debug_it = debug()
79 # end debug
81 import os, sys
82 from os import *
83 from os.path import *
85 import threading
86 from socket import *
87 from xml.dom.minidom import parse, parseString
88 from threading import Lock
89 from signal import *
90 from zipfile import *
92 from twisted.internet.protocol import DatagramProtocol
93 from twisted.internet import reactor
94 from twisted.internet import task
96 import pygame
97 from pygame import *
99 import pgu
100 from pgu import gui as pgui
102 import lamina
104 import OpenGL
105 import OpenGL.GL
106 from OpenGL.GL import *
107 import OpenGL.GLU
108 from OpenGL.GLU import *
110 import StringIO
112 def getBroadcast(ip):
113 global BROADCAST
114 BROADCAST = ip
116 print "getBroadcast(): Broadcast is reported to be", ip
117 return
119 reactor.resolve('<broadcast>').addCallback(getBroadcast)
121 the_event_receiver = 0
123 global the_engine
124 global the_client
126 class QueueLock:
127 def __init__(self):
129 self.items = []
130 self.items_lock = Lock()
132 def size(self):
134 return len(self.items)
136 def getItem(self):
138 self.items_lock.acquire()
139 the_item = self.items.pop(0)
140 self.items_lock.release()
142 return the_item
144 def addItem(self, new_item):
146 self.items_lock.acquire()
147 self.items.append(new_item)
148 self.items_lock.release()
150 return
152 class EventReceiver(QueueLock):
154 def getEvent(self):
155 return self.getItem()
156 def addEvent(self, event):
158 self.addItem(event)
159 return
161 class CommandLine(QueueLock):
163 def getCommand(self):
164 return self.getItem()
165 def addCommand(self, command):
166 self.addItem(command)
167 return
169 class Multicast(DatagramProtocol):
171 def startProtocol(self):
172 self.transport.joinGroup(MULTICAST)
174 def datagramReceived(self, datagram, address):
176 pass
178 class Client(DatagramProtocol):
180 def datagramReceived(self, data, (host, port)):
182 if data[:len(YOUTHERE)] == YOUTHERE:
184 # print "Client.datagramReceived(): Recieved YOUTHERE, responding with IMHERE"
185 self.transport.write(IMHERE, (host, port))
187 if data[:len(SERVEROFFER)] == SERVEROFFER:
189 split_strings = data.split()
191 self.servers[split_strings[2]] = (host, int(split_strings[1]))
193 event = [SERVEROFFER, {'server_name': split_strings[2],
194 'server_address': self.servers[split_strings[2]]}]
195 the_engine.events.addEvent(event)
197 print "Client.datagramReceived(): Received SERVEROFFER"
199 if data[:len(YOUREIN)] == YOUREIN:
201 if (host, port) == self.requested_server:
202 self.current_server = (host, port)
203 self.requested_server = ()
205 event = [YOUREIN]
206 data = {'server': self.current_server}
207 event.append(data)
209 the_engine.events.addEvent(event)
211 print "Client.datagramReceived(): Received YOUREIN, joined server"
213 return
215 if data[:len(LIST)] == LIST:
217 print "Client.datagramReceived(): Received LIST"
219 split_strings = data.split()
221 self.members = []
223 for string in split_strings:
224 if string != LIST:
225 self.members.append(string)
227 event = [LIST]
228 data = {'names': self.members, 'server_address': (host, port)}
229 event.append(data)
231 the_engine.events.addEvent(event)
233 return
235 if data[:len(SOMEONEJOINED)] == SOMEONEJOINED:
237 if (host, port) == self.current_server:
239 print "Client.datagramReceived(): Received SOMEONEJOINED"
241 left_member = ''
243 for member in self.members:
244 if member == data[len(SOMEONEJOINED) + 1:]:
245 left_member = member
247 if left_member == '':
248 self.members.append(data[len(SOMEONEJOINED) + 1:])
250 event = [SOMEONEJOINED]
251 data = {'name': data[len(SOMEONEJOINED) + 1:]}
253 event.append(data)
255 the_engine.events.addEvent(event)
257 return
259 if data[:len(SOMEONELEFT)] == SOMEONELEFT:
261 if (host, port) == self.current_server:
263 name = data[len(SOMEONELEFT) + 1:]
265 if name in self.members:
266 print "Client.datagramReceived(): Received SOMEONELEFT"
268 self.members.remove(name)
270 event = [SOMEONELEFT]
271 data = {'name': name}
273 event.append(data)
275 the_engine.events.addEvent(event)
277 else:
278 print "Client.datagramReceived(): Received SOMEONELEFT, but", name, "not present in roster"
280 return
282 if data[:len(YOUROUT)] == YOUROUT:
284 if (host, port) == self.current_server:
286 print "Client.datagramReceived(): Recieved YOUROUT"
288 self.current_server = ()
290 event = [YOUROUT]
291 data = {}
292 event.append(data)
294 the_engine.events.addEvent(event)
296 return
298 if data[:len(LETTER)] == LETTER:
300 if (host, port) == self.current_server:
301 print "Client.datagramReceived(): Received LETTER"
303 split_strings = data.split(':')
305 message = data[data.find(':', len(LETTER) + 1) + 1:]
306 message_origin = split_strings[1]
308 event = [LETTER]
309 data = {'message': message, 'origin': message_origin}
310 event.append(data)
312 the_engine.events.addEvent(event)
314 return
316 if data[:len(IMHERE)] == IMHERE:
318 if (host, port) == self.current_server:
319 print "Client.datagramReceived(): Received IMHERE from server"
321 self.server_request = 0
323 return
325 def init(self, params):
327 self.params = params
329 self.current_server = ()
330 self.requested_server = ()
331 self.servers = {}
333 self.inited = 1
335 return
337 def serverRequest(self):
339 if self.current_server != ():
341 if self.server_request > SERVER_TIMEOUT:
342 the_engine.events.addEvent([SERVER_GONE, {}])
343 self.current_server = ()
345 else:
346 self.server_request += 1
347 self.transport.write(YOUTHERE, self.current_server)
349 return
351 def executeCommand(self, command, data):
353 reactor.callFromThread(self.executeThreadedCommand, command, data)
355 return
357 def executeThreadedCommand(self, command, data):
358 if command == SERVERKILL:
360 if self.current_server != ():
362 message = ''.join([SERVERKILL, ' '])
364 if data.has_key('password'):
365 message = ''.join([message, data['password']])
367 self.transport.write(message, self.current_server)
369 if command == SERVERREQUEST:
371 message = ''.join([SERVERREQUEST, ' ', str(self.params['message_port'])])
373 the_multicast.transport.write(message, (MULTICAST, self.params['broadcast_port']))
374 # self.transport.write(message, ('255.255.255.255', self.params['broadcast_port']))
376 if command == GETLIST:
378 message = GETLIST
380 if data.has_key('server'):
382 if self.servers.has_key(data['server']):
383 self.transport.write(message, self.servers[data['server']])
385 else:
387 if self.current_server != ():
388 self.transport.write(message, self.current_server)
390 if command == IMOUT:
392 if self.current_server != ():
394 message = IMOUT
396 self.transport.write(message, self.current_server)
398 self.current_server = ()
400 if command == LETTER:
402 if self.current_server != ():
404 message = ''.join([LETTER, ':'])
406 for dest in data['destinations']:
407 if dest in self.members:
408 message = ''.join([message, ' ' , dest])
410 message = ''.join([message, ':', data['message']])
412 self.transport.write(message, self.current_server)
414 if command == WANTIN:
416 if data.has_key('server'):
417 if self.servers.has_key(data['server']):
419 self.transport.write(''.join([WANTIN, ' ', self.params['name']]),
420 self.servers[data['server']])
421 self.current_server = ()
422 self.requested_server = self.servers[data['server']]
424 return
426 class Engine:
428 def __init__(self, config):
430 self.config = config
431 self.running = 1
433 global the_engine
434 the_engine = self
436 video_flags = OPENGL|DOUBLEBUF
438 pygame.init()
439 self.display = pygame.display.set_mode(config['window_size'], video_flags)
441 self.font = pygame.font.SysFont("default", 18)
442 self.fontBig = pygame.font.SysFont("default", 24)
443 self.fontSub = pygame.font.SysFont("default", 20)
444 self.theme = pgui.Theme(['test_theme', 'gray', 'default'])
445 # self.theme = pgui.Theme('gray')
446 # self.theme = pgui.Theme('default')
448 self.resize((config['window_size']))
450 glShadeModel(GL_SMOOTH)
451 glClearColor(self.config['background_color'][0],
452 self.config['background_color'][1],
453 self.config['background_color'][2],
454 self.config['background_color'][3])
455 glClearDepth(1.0)
456 glEnable(GL_DEPTH_TEST)
457 glDepthFunc(GL_LEQUAL)
458 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
460 pygame.display.set_caption(config['window_title'])
462 self.gui_screen = lamina.LaminaScreenSurface()
464 self.app = pgui.App(theme=self.theme)
465 self.app._screen = self.gui_screen.surf
466 self.main_container = pgui.Container(width=config['window_size'][0])
468 self.files = {}
470 self.events = EventReceiver()
472 # self.files is a map of filename to file
474 # The file has this:
475 # {parent, [children], {object_defs},
476 # {menu_defs}, {object_instances}, {menu_instances}}
478 self.zipfiles = []
480 for file in listdir(self.config['pack_dir']):
481 if (is_zipfile(os.path.join(self.config['pack_dir'], file))):
482 self.zipfiles.append(ZipFile(os.path.join(self.config['pack_dir'], file)))
484 self.running = self.addFile(self.config['init'], '')
485 self.app.init(self.main_container)
487 self.ticks = pygame.time.get_ticks()
488 self.frames = 0
490 if self.running == 0:
491 print "Engine.__init__(): Failed adding initial file"
493 self.message_boxen = []
495 def run(self):
497 global the_client
499 while self.running:
501 self.process_events()
503 self.draw()
505 pygame.display.flip()
507 return
509 def updateFPS(self):
511 self.oldticks = self.ticks
512 self.ticks = pygame.time.get_ticks()
514 self.frames += 1
516 self.fps = (self.frames * 1000) / (self.ticks - self.oldticks) / 1000
518 pygame.display.set_caption(''.join([self.config['window_title'], ' ', str(self.fps)]))
520 return
522 def process_events(self):
524 change = 0
526 for e in pygame.event.get():
527 if e.type == QUIT:
528 self.running = 0
529 print "Should be quitting..."
531 self.killGame()
533 self.app.event((e))
534 change = self.app.update(self.gui_screen.surf)
536 if (change != 0):
537 self.gui_screen.refresh(change)
539 new_event = self.convertEvent(e)
540 self.events.addEvent(new_event)
542 iterating = 1
543 while iterating:
545 if self.events.size():
546 new_event = self.events.getEvent()
547 else:
548 iterating = 0
550 if not iterating:
551 return
553 if iterating:
554 for file in self.files.keys():
556 for name in self.files[file]['object_instances'].keys():
558 self.files[file]['object_instances'][name].event(new_event[0], new_event[1])
560 return
562 def convertEvent(self, e):
564 data = {}
566 if e.type == QUIT:
567 data['none'] = ''
569 if e.type == ACTIVEEVENT:
570 data['gain'] = e.gain
571 data['state'] = e.state
573 if e.type == KEYDOWN:
574 data['unicode'] = e.unicode
575 data['key'] = e.key
576 data['mod'] = e.mod
578 if e.type == KEYUP:
579 data['key'] = e.key
580 data['mod'] = e.mod
582 if e.type == MOUSEMOTION:
583 data['pos'] = e.pos
584 data['rel'] = e.rel
585 data['buttons'] = e.buttons
587 if e.type == MOUSEBUTTONUP:
588 data['pos'] = e.pos
589 data['button'] = e.button
591 if e.type == MOUSEBUTTONDOWN:
592 data['pos'] = e.pos
593 data['button'] = e.button
595 if e.type == JOYAXISMOTION:
596 data['joy'] = e.joy
597 data['axis'] = e.axis
598 data['value'] = e.value
600 if e.type == JOYBALLMOTION:
601 data['joy'] = e.joy
602 data['ball'] = e.ball
603 data['rel'] = e.rel
605 if e.type == JOYHATMOTION:
606 data['joy'] = e.joy
607 data['hat'] = e.hat
608 data['value'] = e.value
610 if e.type == JOYBUTTONUP:
611 data['joy'] = e.joy
612 data['button'] = e.button
614 if e.type == JOYBUTTONDOWN:
615 data['joy'] = e.joy
616 data['button'] = e.button
618 if e.type == VIDEORESIZE:
619 data['size'] = e.size
620 data['w'] = e.w
621 data['h'] = e.h
623 if e.type == VIDEOEXPOSE:
624 data['none'] = ''
626 if e.type == USEREVENT:
627 data['code'] = e.code
629 type = ''
631 if e.type == QUIT: type = "QUIT"
632 if e.type == ACTIVEEVENT: type = "ACTIVEEVENT"
633 if e.type == KEYDOWN: type = "KEYDOWN"
634 if e.type == KEYUP: type = "KEYUP"
635 if e.type == MOUSEMOTION : type = "MOUSEMOTION"
636 if e.type == MOUSEBUTTONUP: type = "MOUSEBUTTONUP"
637 if e.type == MOUSEBUTTONDOWN: type = "MOUSEBUTTONDOWN"
638 if e.type == JOYAXISMOTION: type = "JOYAXISMOTION"
639 if e.type == JOYBALLMOTION: type = "JOYBALLMOTION"
640 if e.type == JOYHATMOTION: type = "JOYHATMOTION"
641 if e.type == JOYBUTTONUP: type = "JOYBUTTONUP"
642 if e.type == JOYBUTTONDOWN: type = "JOYBUTTONDOWN"
643 if e.type == VIDEORESIZE: type = "VIDEORESIZE"
644 if e.type == VIDEOEXPOSE: type = "VIDEOEXPOSE"
645 if e.type == USEREVENT: type = "USEREVENT"
647 return [type, data]
649 def draw(self):
651 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
652 glLoadIdentity()
654 # draw stuff
655 debug_it.draw()
657 glLoadIdentity()
658 self.gui_screen.display()
660 def resize(self, (width, height)):
661 if height==0:
662 height=1
663 glViewport(0, 0, width, height)
664 glMatrixMode(GL_PROJECTION)
665 glLoadIdentity()
666 gluPerspective(45, 1.0*width/height, 0.1, 100.0)
667 glMatrixMode(GL_MODELVIEW)
668 glLoadIdentity()
670 return
672 def addFile(self, filename, parent):
674 # Because I have alot of nesting in this function,
675 # I am using 2 space formatting
677 for zipfile in self.zipfiles:
679 for file in zipfile.namelist():
681 if (file == filename):
682 dom = parseString(zipfile.read(file))
684 object_instances_d = []
685 menu_instances = []
687 if dom.childNodes[0].nodeName == 'game':
688 self.files[filename] = {
689 'object_defs': {},
690 'children': [],
691 'parent': '',
692 'object_instances': {},
693 'menu_instances': {},
694 'menu_defs': {}}
696 for node in dom.childNodes[0].childNodes:
698 if (node.nodeName == 'def'):
700 for sub_node in node.childNodes:
702 if (sub_node.nodeName == 'object'):
704 temp_object_def = {}
706 for suber_node in sub_node.childNodes:
708 if (suber_node.nodeName == 'name'):
709 if len(suber_node.childNodes):
710 temp_object_def['name'] = suber_node.childNodes[0].nodeValue
712 if (suber_node.nodeName == 'script'):
713 if len(suber_node.childNodes):
714 temp_object_def['script'] = suber_node.childNodes[0].nodeValue
716 if (suber_node.nodeName == 'tangible'):
717 if len(suber_node.childNodes):
718 temp_object_def['tangible'] = suber_node.childNodes[0].nodeValue
720 if (suber_node.nodeName == 'type'):
721 if len(suber_node.childNodes):
722 temp_object_def['type'] = suber_node.childNodes[0].nodeValue
724 self.files[filename]['object_defs'][temp_object_def['name']] = temp_object_def
725 temp_object_def = {}
727 if (sub_node.nodeName == 'menu'):
729 temp_menu_def = {}
730 temp_menu_def['elements'] = {}
732 temp_element_set = {}
734 for suber_node in sub_node.childNodes:
736 if (suber_node.nodeName == 'name'):
737 temp_menu_def['name'] = suber_node.childNodes[0].nodeValue
739 if (suber_node.nodeName == 'elements'):
741 for suberer_node in suber_node.childNodes:
743 if (suberer_node.nodeType != 3 and suberer_node.nodeType != 8):
744 if (suberer_node.hasAttribute('name')):
745 temp_element_set['name'] = suberer_node.getAttribute('name')
747 if (suberer_node.hasAttribute('x')):
748 temp_element_set['x'] = int(suberer_node.getAttribute('x'))
750 if (suberer_node.hasAttribute('y')):
751 temp_element_set['y'] = int(suberer_node.getAttribute('y'))
753 if (suberer_node.hasAttribute('width')):
754 temp_element_set['width'] = int(suberer_node.getAttribute('width'))
756 if (suberer_node.hasAttribute('height')):
757 temp_element_set['height'] = int(suberer_node.getAttribute('height'))
759 if (suberer_node.hasAttribute('parent')):
760 temp_element_set['parent'] = suberer_node.getAttribute('parent')
762 if (suberer_node.hasAttribute('target')):
763 temp_element_set['target'] = suberer_node.getAttribute('target')
765 if (suberer_node.hasAttribute('text')):
766 temp_element_set['text'] = suberer_node.getAttribute('text')
768 temp_element_set['type'] = suberer_node.nodeName
769 temp_menu_def['elements'][temp_element_set['name']] = temp_element_set
770 temp_element_set = {}
772 self.files[filename]['menu_defs'][temp_menu_def['name']] = temp_menu_def
774 temp_menu_def = {}
775 temp_element_set = {}
777 if (node.nodeName == 'instance'):
779 for sub_node in node.childNodes:
781 if (sub_node.nodeName == 'object'):
782 object_instances_d.append(sub_node.childNodes[0].nodeValue)
784 if (sub_node.nodeName == 'menu'):
785 menu_instances.append(sub_node.childNodes[0].nodeValue)
787 if (parent != ''):
788 self.files[parent]['children'].append(filename)
789 self.files[filename]['parent'] = parent
791 # create instances
793 for menuname, menu_data in self.files[filename]['menu_defs'].iteritems():
794 self.files[filename]['menu_instances'][menuname] = Menu(menu_def=menu_data)
796 for menuname in menu_instances:
797 if (self.files[filename]['menu_instances'].has_key(menuname)):
798 self.files[filename]['menu_instances'][menuname].show()
800 for file in self.files.keys():
801 if self.files[file]['menu_instances'].has_key(menuname):
802 self.files[file]['menu_instances'][menuname].show()
804 for objectname in object_instances_d:
805 self.addObject(objectname)
807 return 1
808 return 0
809 # ending 2-space formatting
811 def removeFile(self, filename):
813 if (self.files.has_key(filename)):
815 for child in self.files[filename]['children']:
816 self.removeFile(child)
818 del self.files[filename]['children']
820 parent = self.files[filename]['parent']
822 self.files[parent]['children'].pop(self.files[parent]['children'].index(filename))
824 del self.files[filename]
826 return
828 def getVisibleMenus(self):
830 menus = {}
832 for file, contents in self.files.iteritems():
833 for name, menu in contents['menu_instances'].iteritems():
834 if not menu.hidden:
835 menus[name] = menu
837 return menus
839 def hideAllMenus(self):
841 for file, contents in self.files.iteritems():
842 for name, menu in contents['menu_instances'].iteritems():
843 menu.hide()
845 return
847 def showMenu(self, menu_name):
849 for file, contents in self.files.iteritems():
850 for name, menu in contents['menu_instances'].iteritems():
851 if contents['menu_instances'].has_key(menu_name):
852 contents['menu_instances'][menu_name].show()
854 return
856 def hideMenu(self, menu_name):
858 for file, contents in self.files:
859 for name, menu in contents['menu_instances'].iteritems():
860 if contents['menu_instances'].has_key(menu_name):
861 contents['menu_instances'][menu_name].hide()
863 return
865 def setMenu(self, menu_name):
867 self.hideAllMenus()
868 self.showMenu(menu_name)
870 return
872 def addObject(self, objectname):
874 for file in self.files.keys():
875 if self.files[file]['object_defs'].has_key(objectname):
876 self.files[file]['object_instances'][objectname] = GameObject(
877 self.files[file]['object_defs'][objectname])
879 return
881 def removeObject(self, objectname):
883 for file in self.files.keys():
884 if self.files[file]['object_defs'].has_key(objectname):
885 del self.files[file]['object_instances'][objectname]
887 return
889 def addListItem(self, menuname, item, data, dvalue):
891 for file in self.files:
892 if self.files[file]['menu_instances'].has_key(menuname):
893 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
894 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
896 the_widget.add(data.encode(), value=dvalue)
897 the_widget.resize()
898 the_widget.repaint()
900 return
902 def clearListItem(self, menuname, item):
904 for file in self.files:
905 if self.files[file]['menu_instances'].has_key(menuname):
906 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
907 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
909 the_widget.clear()
910 the_widget.resize()
911 the_widget.repaint()
913 return
915 def removeListItem(self, menuname, item, value):
917 for file in self.files:
918 if self.files[file]['menu_instances'].has_key(menuname):
919 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
920 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
922 the_widget.remove(value)
923 the_widget.resize()
924 the_widget.repaint()
926 return
928 def getListValue(self, menuname, item):
930 for file in self.files:
931 if self.files[file]['menu_instances'].has_key(menuname):
933 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
934 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
936 return the_widget.value
938 return ''
940 def getEditboxValue(self, menuname, item):
942 for file in self.files:
943 if self.files[file]['menu_instances'].has_key(menuname):
945 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
946 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
948 return the_widget.value
950 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
952 return the_widget.value
954 def setEditboxValue(self, menuname, item, new_value):
956 for file in self.files:
957 if self.files[file]['menu_instances'].has_key(menuname):
959 if self.files[file]['menu_instances'][menuname].widgets.has_key(item):
960 the_widget = self.files[file]['menu_instances'][menuname].widgets[item]
962 the_widget.value = new_value
964 return
966 def showMessageBox(self, message, title, width, height):
968 # Modify width and height to your liking
969 width = 400
970 height = 150
971 the_engine.messageBox(title, message)
973 return
975 def getImage(self, filename):
977 the_buf = pygame.image.load(self.getStringIOFile(filename))
979 return the_buf
981 def getStringIOFile(self, filename):
983 for zip_file in self.zipfiles:
984 for file in zip_file.namelist():
986 if (filename == file):
988 the_string_io = StringIO.StringIO()
989 print >>the_string_io, zip_file.read(file)
990 the_string_io.seek(0)
992 return the_string_io
993 return ''
995 def getStringData(self, filename):
996 for zip_file in self.zipfiles:
997 for file in zip_file.namelist():
999 if (filename == file):
1000 return zip_file.read(file)
1001 return ''
1003 def killThreadGame(self):
1005 reactor.stop()
1007 return
1009 def killGame(self):
1011 reactor.callFromThread(self.killThreadGame)
1013 return
1015 class Menu:
1017 def __init__(self, menu_def):
1019 self.menu_def = menu_def
1020 self.widgets = {}
1022 for name, element in menu_def['elements'].iteritems():
1024 multiplier_x = float(the_engine.config['window_size'][0]) / 100.00
1025 multiplier_y = float(the_engine.config['window_size'][1]) / 100.00
1027 dx = float(element['x']) * multiplier_x
1028 dy = float(element['y']) * multiplier_y
1030 dwidth = float(element['width']) * multiplier_x
1031 dheight = float(element['height']) * multiplier_y
1033 if (element['type'] == 'button'):
1034 self.widgets[name] = pgui.Button(element['text'].encode(), width=dwidth, height=dheight)
1035 self.widgets[name].connect(pgui.CLICK, self.clicked, name)
1037 if (element['type'] == 'image'):
1038 self.widgets[name] = pgui.Image(the_engine.getImage(element['text']))
1040 if (element['type'] == 'label'):
1041 self.widgets[name] = pgui.Label(element['text'])
1043 if (element['type'] == 'listbox'):
1044 self.widgets[name] = pgui.List(width=dwidth, height=dheight)
1045 self.widgets[name].connect(pgui.CLICK, self.clicked, name)
1047 if (element['type'] == 'editbox'):
1048 self.widgets[name] = pgui.Input(value=element['text'], width=dwidth)
1049 self.widgets[name].connect(pgui.KEYDOWN, self.key_pressed, name)
1050 self.widgets[name].connect(pgui.KEYUP, self.key_up, name)
1052 if (self.widgets.has_key(name)):
1053 self.widgets[name].resize(width=dwidth, height=dheight)
1054 else:
1055 print "Menu.__init__(): Widget type", element['type'], " not implemented yet, skipping."
1057 self.hidden = 1
1059 def show(self):
1061 global the_engine
1063 multiplier_x = float(the_engine.config['window_size'][0]) / 100.00
1064 multiplier_y = float(the_engine.config['window_size'][1]) / 100.00
1066 if (self.hidden == 1):
1067 for name, element in self.menu_def['elements'].iteritems():
1068 dx = float(element['x']) * multiplier_x
1069 dy = float(element['y']) * multiplier_y
1071 if self.widgets.has_key(name):
1072 the_engine.main_container.add(self.widgets[name], dx, dy)
1074 self.hidden = 0
1076 return
1078 def hide(self):
1080 global the_engine
1082 if (self.hidden != 1):
1083 for name, element in self.menu_def['elements'].iteritems():
1085 if (self.widgets.has_key(name)):
1086 the_engine.main_container.remove(self.widgets[name])
1088 self.hidden = 1
1090 return
1092 def clicked(self, widget, _event):
1094 if self.menu_def['elements'].has_key(widget):
1096 if self.menu_def['elements'][widget]['target'] != '':
1097 exec(self.menu_def['elements'][widget]['target'])
1099 the_engine.events.addEvent(['WIDGET_CLICKED',
1100 {'name': widget,
1101 'menu_name': self.menu_def['name'],
1102 event: the_engine.convertEvent(_event)}])
1104 return
1106 def key_pressed(self, widget, _event):
1108 if self.menu_def['elements'].has_key(widget):
1110 new_event = the_engine.convertEvent(_event)
1112 the_engine.events.addEvent(['KEYDOWN',
1113 {'name': widget,
1114 'menu_name': self.menu_def['name'],
1115 'event': new_event}])
1117 return
1119 def key_up(self, widget, _event):
1121 if self.menu_def['elements'].has_key(widget):
1123 the_engine.events.addEvent(['KEYUP',
1124 {'name': widget,
1125 'menu_name': self.menu_def['name'],
1126 event: the_engine.convertEvent(_event)}])
1128 return
1130 class MessageBox(pgui.Dialog):
1132 def __init__(self, title, message):
1134 self.title = pgui.Label(title)
1135 self.main = pgui.Label(message)
1137 return
1139 class Camera:
1141 def __init__(self):
1142 return
1144 class GameObject:
1146 def __init__(self, dmold):
1148 self.mold = dmold
1149 global the_functions
1150 global in_script
1152 if self.mold['script'] != '':
1154 in_script = 1
1156 the_file = the_engine.getStringData(self.mold['script'])
1157 if the_file != '':
1158 exec(the_file)
1160 in_script = 0
1161 self.my_functions = the_functions
1163 the_functions = {}
1165 def event(self, event, data):
1167 if self.my_functions.has_key(event):
1169 self.my_functions[event](data)
1171 return
1173 def main():
1174 # parse command line stuff
1176 if (len(sys.argv) > 1):
1177 config = sys.argv[1]
1178 else:
1179 print "main(): No config specified, using", CONFIG
1180 config = CONFIG
1182 configuration = parse_config(config)
1184 if (configuration.has_key('error') and configuration['error']):
1185 print "main(): Error in parsing config."
1187 the_event_receiver = EventReceiver()
1189 global client_params
1190 client_params = {'broadcast_port':configuration['broadcast_port'],
1191 'broadcast_bind':configuration['broadcast_bind'],
1192 'message_port':configuration['message_port'],
1193 'name':configuration['name'],
1194 'echo_time': configuration['echo_time']}
1196 global the_engine
1197 global the_client
1199 the_engine = Engine(configuration)
1201 the_client = Client()
1202 the_client_thread = threading.Thread(target=run_net)
1204 the_client.server_request = 0
1206 the_client.init(client_params)
1208 the_client_thread.start()
1209 the_engine.run()
1211 the_engine.killGame()
1213 sys.exit()
1215 the_client_thread.join()
1217 return
1219 def run_net():
1221 global client_params
1222 global the_multicast
1224 the_multicast = Multicast()
1225 config = client_params
1227 reactor.listenMulticast(config['broadcast_bind'], the_multicast)
1228 reactor.listenUDP(config['message_port'], the_client)
1230 echo_request = task.LoopingCall(the_client.serverRequest)
1232 if client_params['echo_time'] != None:
1233 echo_request.start(client_params['echo_time'])
1234 else:
1235 print "run_net(): No ECHO_TIME specified, using default of", ECHO_TIME
1236 echo_request.start(ECHO_TIME)
1238 reactor.run(installSignalHandlers=0)
1240 return
1242 def parse_config(filename):
1243 results = {'error': 1}
1245 if (exists(filename)):
1246 dom = parse(filename)
1247 else:
1248 print "parse_config():", filename, "doesn't exist."
1249 return results
1251 results = {'window_title': None,
1252 'log': None,
1253 'name': None,
1254 'font': None,
1255 'init': None,
1256 'message_port': None,
1257 'broadcast_port': None,
1258 'broadcast_bind': None,
1259 'fullscreen': None,
1260 'background_color': None,
1261 'window_size': None,
1262 'gravity': None,
1263 'step_size': None,
1264 'pack_dir': None,
1265 'echo_time': None}
1267 if (dom.childNodes[0].nodeName == 'config'):
1268 for node in dom.childNodes[0].childNodes:
1270 if (node.nodeName == 'window_title'):
1271 results['window_title'] = node.childNodes[0].nodeValue
1273 if (node.nodeName == 'log'):
1274 results['log'] = node.childNodes[0].nodeValue
1276 if (node.nodeName == 'name'):
1277 results['name'] = node.childNodes[0].nodeValue
1279 if (node.nodeName == 'font'):
1280 results['font'] = node.childNodes[0].nodeValue
1282 if (node.nodeName == 'init'):
1283 results['init'] = node.childNodes[0].nodeValue
1285 if (node.nodeName == 'message_port'):
1286 results['message_port'] = int(node.childNodes[0].nodeValue)
1288 if (node.nodeName == 'broadcast_port'):
1289 results['broadcast_port'] = int(node.childNodes[0].nodeValue)
1291 if (node.nodeName == 'broadcast_bind'):
1292 results['broadcast_bind'] = int(node.childNodes[0].nodeValue)
1294 if (node.nodeName == 'fullscreen'):
1295 results['fullscreen'] = int(node.childNodes[0].nodeValue)
1297 if (node.nodeName == 'background_color'):
1299 string_parts = node.childNodes[0].nodeValue.split()
1300 results['background_color'] = [float(string_parts[0]), float(string_parts[1])]
1301 results['background_color'].append(float(string_parts[2]))
1302 results['background_color'].append(float(string_parts[3]))
1304 if (node.nodeName == 'window_size'):
1306 string_parts = node.childNodes[0].nodeValue.split()
1307 results['window_size'] = ((int(string_parts[0]), int(string_parts[1])))
1309 if (node.nodeName == 'gravity'):
1311 string_parts = node.childNodes[0].nodeValue.split()
1312 results['gravity'] = [float(string_parts[0]), float(string_parts[1])]
1313 results['gravity'].append(float(string_parts[2]))
1315 if (node.nodeName == 'step_size'):
1316 results['step_size'] = float(node.childNodes[0].nodeValue)
1318 if (node.nodeName == 'pack_dir'):
1319 results['pack_dir'] = node.childNodes[0].nodeValue
1321 if (node.nodeName == 'echo_time'):
1322 results['echo_time'] = int(node.childNodes[0].nodeValue)
1324 results['error'] = 0
1326 return results
1328 if __name__ == '__main__':
1329 main()