Commits

Andrew Peterson committed 1384c35 Merge

Merge branch 'master' into logging

Comments (0)

Files changed (13)

+
+
+class GameClass:
+    
+    def __init__(self):
+        self.curr_state = None
+        self.running = False
+        self.known_states = {}
+
+    def initialize(self):
+        self.running = True
+
+    def update(self):
+        if self.curr_state:
+            self.curr_state.processInput()
+            self.curr_state.update()
+
+            self.curr_state.render()
+
+    def changeState(self, state_class, *args):
+        assert(state_class)
+
+        if self.curr_state:
+            # Don't switch to the same state
+            if state_class is self.curr_state.__class__:
+                return
+
+            # Leave the current state
+            self.curr_state.leave()
+
+        # look for state class in known states
+        new_state = self.known_states.get(state_class)
+        if not new_state:
+            # Instantiate class
+            new_state = state_class()
+            self.known_states[state_class] = new_state
+
+            # initialize new state
+            new_state.gc = self
+            new_state.initialize()
+
+        # officially switch to new state
+        self.curr_state = new_state
+
+        # Finally enter into the next state
+        self.curr_state.enter(*args)
+
+    def closeState(self, state_class):
+
+        # Look for state in known states
+        if state in self.known_states:
+            # shutdown and remove from list
+            state.shutdown()
+            self.known_states.remove(state)
+            return True
+        return False
+
+    def shutdown(self):
+        self.running = False
+
+        # Leave the current state we are in
+        if self.curr_state:
+            self.curr_state.leave()
+            self.curr_state = None
+
+        # Shutdown all known states
+        for state in self.known_states.itervalues():
+            state.shutdown()
+        state = {}
+
+    def getActiveState(self):
+        return self.curr_state
+        
+#end GameClass
+
+class GameState:
+
+    def __init__(self):
+        self.gc = None
+
+    def initialize(self):
+        """Called the first time the game is changed to this state
+           during the applications lifecycle."""
+
+    def enter(self):
+        """Called every time the game is switched to this state."""
+
+    def processInput(self):
+        """Called during normal update/render period for this state
+           to process it's input."""
+
+    def update(self):
+        """Called during normal update/render period for this state
+           to update it's local or game data."""
+
+    def render(self):
+        """Called during normal update/render period for this state
+           to render it's data in a specific way."""
+
+    def leave(self):
+        """Called whenever we switch from this state to another."""
+
+    def shutdown(self):
+        """Called during application shutdown."""
+
+    def changeState(self, state_class, *args):
+        """Shortcut for this state to initiate transfer to a new state."""
+        self.gc.changeState(state_class, *args)
+#end GameState
+

pyshipcommand/network.py

 from djlib.primitives import Vector
 class NetVector(pb.Copyable, pb.RemoteCopy, Vector):
 
+    @classmethod
+    def fromVector(cls, vec):
+        return NetVector(*vec.args())
+
     # serialize
     def getStateToCopy(self):
         d = self.__dict__.copy()
     
     def __init__(self, ship):
         self.id = ship.id
-        self.pos = NetVector(*ship.pos.args())
+        self.pos = NetVector.fromVector(ship.pos)
         self.speed = ship.vel.length()
         self.rotation = -int(self.degrees(self.atan2(ship.heading.y, ship.heading.x)))
         self.end_rot = None
 
         self.server_step = None
         self.universe = None
+        self.ships = None
 
 #end NetInit
 
 class NetCelestialBody(pb.Copyable, pb.RemoteCopy):
 
     def __init__(self, body):
-        self.pos = NetVector(*body.pos.args())
+        self.pos = NetVector.fromVector(body.pos)
         self.radius = body.radius
         self.type = -1
         for i, t in enumerate([celestial.Sun, celestial.Planet, celestial.Asteroid]):

pyshipcommand/players.py

         log.info('Player: "%s" has connected', self.name)
         self.remote = mind
 
-        # send ship update immediately
-        self.sendShips()
         return True
 
 
 
     @log_method(log)
     def perspective_giveMessage(self, msg):
-        log.info("%s: Receiving message:", self.name, msg)
+        log.info("%s: Receiving message: %s", self.name, str(msg))
         sm = getUtility(IManager, "Ship")
         mship = sm.getMothership(self.name)
         if sm.sendMessage(None, mship.id, 0, msg):
         if scripts:
             cinit.scripts = [NetScript(s.name, s.version, s.lastHash) for s in scripts.itervalues()]
 
+        # Send Universe
         univ = getUtility(IManager, "Universe")
         bodies = univ.getAllStatic()
         cinit.universe = [NetCelestialBody(b) for b in bodies]
+
+        # Send Ships
+        ships = self.getShips()
+        cinit.ships = [NetShip(s) for s in ships]
         
         return cinit
 
         
         self.remotePrint("Orbiting Ship[%s] @ %s" % (ship_id, target_pos))
         pos = TargetPosition(target_pos)
-        if int(target_pos.x) >= sm._INDEX_MOD:
-            t_ship = sm.getShip(int(target_pos.x))
-            if t_ship:
-                log.debug("Ship[%s] is orbiting Ship[%s]", ship_id, t_ship)
-                # XXX TODO FIXME: i am pretty sure that this should be 
-                # pos = t_ship
-                # as i am assuming the intent is to orbit the targeted ship and not
-                # the ship already selected
-                pos = ship
+        t_ship = sm.getShip(int(target_pos.x))
+        if int(target_pos.y) == 0 and t_ship:
+            # What are the odds that Y would be 0 and X also match a ship ID?
+            # Should probably changes this ;)
+            log.debug("Ship[%s] is orbiting Ship[%s]", ship_id, t_ship)
+            pos = t_ship
         target = TargetOrbit(pos, radius)
         ship.setTarget(target)
 

pyshipcommand_gui/__init__.py

 from twisted.internet._threadedselect import install as reactor_install
 reactor_install()
 
+# SYSTEM
+from os import path
+from glob import glob
+
+# ADDITIONAL LIBRARIES
 from twisted.internet import reactor, task
-from twisted.spread import pb
+import pygame
+from ocempgui.widgets import TwistedRenderer
+from djlib.game import GameClass
 
-# pyshipcommand logic
-from pyshipcommand.network import PBClient, NetVector, NetShip, NetInit, NetScript, NetCelestialBody
+# PYSHIPCOMMAND
 from cscripts import ClientScriptMgr
+from client import GUIClient
+from viewer import StarGenerator
+from states.login import LoginState
 
-# GUI libs
-import pygame
-from pygame import K_UP, K_DOWN, K_LEFT, K_RIGHT, K_RETURN, K_SLASH
-
-from ocempgui import widgets
-from ocempgui.widgets.Constants import SIG_INPUT, SIG_KEYDOWN, SIG_MOUSEDOWN, SIG_MOUSEMOVE
-from ocempgui.events import INotifyable
+# CONSTANTS
+from pyshipcommand.server import DEFAULT_PORT
+DESIRED_FPS = 30.0
+SCREEN_SIZE = (800, 600)
+DEFAULT_SERVER_STEP = 1.0
 
-from pkg_resources import resource_stream
-from os import path
-from glob import glob
+class GUIGameClass(GameClass):
 
-# pyshipcommand_gui
-import dialogs
-from viewer import ShipViewer
+    def __init__(self):
+        GameClass.__init__(self)
+
+        # Global constants
+        self.DEFAULT_SERVER = "localhost"
+        self.DEFAULT_PORT = DEFAULT_PORT
+        self.DEFAULT_USER = "admin"
+        self.COLOR_BLACK = pygame.Color(0,0,0)
+        self.STAR_COLOR = pygame.Color(255, 255, 255)
+        self.SERVER_STEP = DEFAULT_SERVER_STEP
+
+        # Itemize GameClass variables for reference
+        self.rsurf = None
+        self.uisurf = None
+        self.uirender = None
+        self.fpsClock = None
+        self.client = None
+        self.stars = None
+        self.time = 0
+        self.time_step = 0
+        self.dfont = None
 
+    def initialize(self):
 
-# CONSTANTS
-SERVER_ADDR = "localhost"
-from pyshipcommand.server import DEFAULT_PORT as SERVER_PORT
+        # Init pygame and create main rendering surface
+        pygame.init()
+        self.rsurf = pygame.display.set_mode(SCREEN_SIZE)
+        pygame.display.set_caption("pyShipCommand")
 
-DEFAULT_USER = "admin"
-DEFAULT_PASS = "password"
+        # Create UI Renderer that renders to a clone of the main surface
+        self.uirender = TwistedRenderer()
+        self.uisurf = self.rsurf.copy()
+        self.uirender.set_screen(self.uisurf)
+        self.uirender.set_color((0, 0, 0))
+        self.uirender.reactor = reactor
 
-DESIRED_FPS = 30.0
+        # Main Game Clock
+        self.fpsClock = pygame.time.Clock()
 
-# Init pygame and create main rendering surface
-pygame.init()
-g_rsurf = pygame.display.set_mode((800, 600))
-pygame.display.set_caption("pyShipCommand")
-
-# Create UI Renderer that renders to a clone of the main surface
-g_uirender = widgets.TwistedRenderer()
-g_uisurf = g_rsurf.copy()
-g_uirender.set_screen(g_uisurf)
-g_uirender.set_color((0, 0, 0))
-g_uirender.reactor = reactor
-
-fpsClock = pygame.time.Clock()
-
-ship_view = ShipViewer(g_rsurf)
-  
-# Resources
-blackColor = pygame.Color(0,0,0)              
-shipImg = resource_stream('pyshipcommand_gui', 'assets/raptor.png')
-shipImg = pygame.image.load(shipImg)
-shipImg = shipImg.convert_alpha()
-ship_view.SHIP_IMG = pygame.transform.rotozoom(shipImg, -90, 0.25)
-
-cmdImg = resource_stream('pyshipcommand_gui', 'assets/command.png')
-cmdImg = pygame.image.load(cmdImg)
-ship_view.MSHIP_IMG = cmdImg.convert_alpha()
-
-class BaseClient(PBClient):
-    def __init__(self):
-        PBClient.__init__(self)
+        # Network client
+        self.client = GUIClient(self)
 
-    def remote_print(self, msg):
-        print msg
-#end BaseClient
+        # The Starfield is used by multiple states and should be created now
+        self.stars = StarGenerator((SCREEN_SIZE[0]/2, SCREEN_SIZE[1]/2),
+                                        SCREEN_SIZE, 25)
 
-class RegisterClient(BaseClient):
+        # Load the default font
+        self.dfont = pygame.font.Font(pygame.font.get_default_font(), 12)
+        if not self.dfont:
+            print "Default Font not loaded!"
 
-    def login(self, username, password):
-        self.username = username
-        self.password = password
-        BaseClient.login(self, "register", "account")
+        # Be sure to initialize base GameClass
+        GameClass.initialize(self)
 
-    def connected(self):
-        dfr = self.server.callRemote("registerAccount", self.username, self.password)
-        dfr.addCallback(self.disconnect)
+    def update(self):
+        # Add any global/game specific updates here
+        self.fpsClock.tick()
+        self.time = pygame.time.get_ticks()
+        self.time_step = self.fpsClock.get_rawtime()/1000.0
 
-    def disconnect(self, n):
-        BaseClient.disconnect(self)
-#end RegisterClient
+        GameClass.update(self)
 
-pb.setUnjellyableForClass(NetShip, NetShip)
-pb.setUnjellyableForClass(NetInit, NetInit)
-pb.setUnjellyableForClass(NetScript, NetScript)
-pb.setUnjellyableForClass(NetCelestialBody, NetCelestialBody)
-class GUIClient(BaseClient, pb.Referenceable, INotifyable):
-    
-    def __init__(self):
-        BaseClient.__init__(self)
-        self.time = 0
-        self.cscript = ClientScriptMgr()
+    def shutdown(self):
+        GameClass.shutdown(self)
 
-        self.scrollRect = pygame.Rect(50, 50, 700, 500)
-        self.scrollDir = None
-    
-    def update(self):
-        fpsClock.tick()
-        dt = fpsClock.get_rawtime()/1000.0
-
-        # Handle map scrolling
-        if self.scrollDir:
-            ship_view.move(self.scrollDir)
-        
-        # Tick pygame event loop
-        #print dt
-        # Update the Ship Viewer
-        ship_view.update(dt)
-        
-        self.draw()
-        pygame.display.update()
-
-    def notify(self, event):
-        # Receive event notifications from ocempgui
-
-        if event.signal == SIG_KEYDOWN:
-            # Handle arrow keys
-            if event.data.key in (K_UP, K_DOWN, K_RIGHT, K_LEFT):
-                ship_view.move(event.data.key)
-            elif event.data.key in (K_RETURN, K_SLASH):
-                g_uirender.set_active_layer(self.editWnd.depth)
-                self.editWnd.set_focus()
-                if event.data.key is K_SLASH:
-                    self.editWnd.set_text('/')
-                    self.editWnd.set_caret(1)
-
-        elif event.signal == SIG_MOUSEDOWN:
-            # set keyboard focus
-            g_uirender.set_active_layer(0)
-
-            if event.data.button == 1: #Left Click
-                ship = ship_view.pickShip(event.data.pos)
-                self.shipWnd.setShip(ship)
-                self.scriptWnd.setShip(ship)
-                print str(ship)
-
-        elif event.signal == SIG_MOUSEMOVE:
-            # Set scroll direction
-            mp = event.data.pos
-            self.scrollDir = None
-            '''
-            if not self.scrollRect.collidepoint(mp):
-                if mp[0] < self.scrollRect.left:
-                    self.scrollDir = K_LEFT
-                elif mp[0] > self.scrollRect.right:
-                    self.scrollDir = K_RIGHT
-                elif mp[1] < self.scrollRect.top:
-                    self.scrollDir = K_UP
-                elif mp[1] > self.scrollRect.bottom:
-                    self.scrollDir = K_DOWN
-            '''
-
-
-    # Registered with the pyui Desktop and called during the pyui draw() processing
-    # before any windows are rendered
-    def draw(self):
-        # get render surface
-        rs = g_rsurf
-        rs.fill(blackColor)
-        
-        ship_view.draw(rs)
-        
-        # Now apply UI
-        #g_uirender.update()
-        rs.blit(g_uirender.screen, (0,0), None, pygame.BLEND_ADD)
-        
-        # Draw FPS over everything
-        ship_view.renderText(rs, (0,0), str(int(fpsClock.get_fps())))
-
-        
-    def connected(self):
-
-        # Set the local active player
-        if self.loginWnd:
-            # Destroy the login windows on successful connection
-            self.loginWnd.destroy()
-            self.loginWnd = None
-
-            # Show the rest of the UI now that we are logged in
-            g_uirender.add_widget(self.editWnd)
-            g_uirender.add_widget(self.scriptWnd)
-            g_uirender.add_widget(self.shipWnd)
-
-        dfr = self.server.callRemote("getClientInit")
-        dfr.addCallback(self.setClientInit)
-        
-    def processCmd(self, edit):
-
-        # Handle edit box
-        line = edit.text
-        edit.set_text("")
-        edit.set_dirty(1)
-        
-        # Parse the command
-        if not line or not len(line) > 0:
-            return
-
-        # Raw text should be treated as a chat message.
-        if line[0] != '/':
-            self.do_chat(line)
-            return
-
-        # Split line and remove leading '/'
-        commandParts = line[1:].split()
-        command = commandParts[0].lower()
-        args = commandParts[1:]
-
-        # Dispatch the command to the appropriate method.
-        try:
-            method = getattr(self, 'do_' + command)
-        except AttributeError, e:
-            print 'Error: no such command.'
-        else:
-            try:
-                method(*args)
-            except Exception, e:
-                    print 'Error', str(e)
-                    
-    def createDialogs(self):
-        (w,h) = g_rsurf.get_size()
-        
-        # CLI Entry
-        edit = widgets.Entry()
-        edit.topleft = (0, h-20)
-        edit.minsize = w, 20
-        edit.depth = 1
-        edit.connect_signal(SIG_INPUT, self.processCmd, edit)
-        #g_uirender.add_widget(edit)
-        self.editWnd = edit
-        
-        # Movement Widget
-        #g_uirender.add_widget(dialogs.MovementWidget(400, 0, ship_view.move))
-
-        # Script widget
-        self.scriptWnd = dialogs.ScriptWidget(w-205, 0, self.cscript, self.do_import,
-                                              self.do_upload, self.do_ship)
-        #g_uirender.add_widget(self.scriptWnd)
-        
-        # Create login dialog
-        self.loginWnd = dialogs.LoginDialog(self, RegisterClient(), w, h)
-        self.loginWnd.populateUser(DEFAULT_USER)
-        self.loginWnd.populateServer(SERVER_ADDR, SERVER_PORT)
-        g_uirender.add_widget(self.loginWnd)
-        self.loginWnd.set_focus()
-
-        # Ship Info
-        self.shipWnd = dialogs.ShipInfo(w-205, self.scriptWnd.height)
-        #g_uirender.add_widget(self.shipWnd)
-
-        # register this client to receive input notifications
-        event_mgr = g_uirender.get_managers()[0]
-        event_mgr.add_object(self, SIG_KEYDOWN, SIG_MOUSEDOWN, SIG_MOUSEMOVE)
-                    
-    def do_cl(self):
-        self.connect(SERVER_ADDR, SERVER_PORT)
-        self.login(DEFAULT_USER, DEFAULT_PASS)
-                    
-    def do_connect(self, addr = SERVER_ADDR, port = SERVER_PORT):
-        self.connect(addr, port)
-        
-    def do_login(self, user = DEFAULT_USER, password = DEFAULT_PASS):
-        self.login(user, password)
-
-    def do_help(self, command=None):
-        """help [command]: List commands, or show help on the given command"""
-        if command:
-            print (getattr(self, 'do_' + command).__doc__)
-        else:
-            commands = [cmd[3:] for cmd in dir(self) if cmd.startswith('do_')]
-            print ("Valid commands: " +" ".join(commands))
-
-    def do_exit(self):
-        self.disconnect()
+        self.client.disconnect()
         pygame.quit()
 
-    def do_info(self):
-        self.server.callRemote("info")
-
-    def do_upload(self, scriptfile):
-
-        # Sanity checks
-        if not scriptfile:
-            raise Exception("script <script_data>")
-
-        s = self.cscript.getScript(scriptfile)
-        if s:
-            print "sending script:", s.name
-            self.server.callRemote("giveScript", s.name, s.source)
-            return
-
-        print scriptfile + " not found!"
-
-
-    def do_import(self, scriptPath = None):
-
-        if not scriptPath:
-            script_dlg = dialogs.ImportScriptDialog(self.do_import, *g_rsurf.get_size())
-            g_uirender.add_widget(script_dlg)
-            script_dlg.set_focus()
-            return
-
-        # Always treat scripts as a list, even if they only specified a file.
-        scriptFiles = [scriptPath]
-        if path.isdir(scriptPath):
-            scriptFiles = glob(path.join(scriptPath,"*.py"))
-
-        for s in scriptFiles:
-            self.cscript.importScript(s)
-
-        # Update list contents, even if we could have failed
-        if len(scriptFiles) > 0:
-            self.scriptWnd.update_list()
-            #self.scriptWnd.select_script(s.name)
-            return
-
-        print "Could not import:" + scriptFiles
-
-    def do_reload(self):
-
-        self.cscript.reloadScripts()
-        self.scriptWnd.update_list()
-
-
-    def do_ship(self, cmd, *args):
-        print "do_ship", cmd, ":", args
-        if cmd == "create":
-            pos = NetVector(0.0, 0.0)
-            if len(args) == 2:
-                pos = NetVector(float(args[0]), float(args[1]))
-            print pos
-            self.server.callRemote("addShip", pos)
-        elif cmd == "move":
-            ship_id = int(args[0])
-            target_pos = NetVector(float(args[1]), float(args[2]))
-            print target_pos
-            self.server.callRemote("moveShip", ship_id, target_pos)
-        elif cmd == "orbit":
-            ship_id = int(args[0])
-            target_pos = NetVector(float(args[1]), float(args[2]))
-            radius = float(args[3])
-            self.server.callRemote("orbitShip", ship_id, target_pos, radius)
-        elif cmd == "follow":
-            ship_id = int(args[0])
-            target_id = int(args[1])
-            dist = float(args[2])
-            self.server.callRemote("followShip", ship_id, target_id, dist)
-        elif cmd == "script":
-            ship_id = int(args[0])
-            script_name = args[1]
-
-            action = "upgrade" # default to an upgrade
-            if len(args) > 2:
-                action = args[2]
-
-            self.server.callRemote("scriptShip", ship_id, script_name, action)
-
-    def do_scroll(self, *args):
-        scroll_speed = ShipViewer.SCROLL_SPEED
-        if len(args) == 1:
-            scroll_speed = int(args[0])
-        ship_view.SCROLL_SPEED = scroll_speed
-
-    def do_msg(self, *args):
-        print "do_msg, ", args
-        self.server.callRemote("giveMessage", args)
-
-    def do_home(self):
-        ship_view.centerView()
-
-    def do_chat(self, msg):
-        self.server.callRemote("giveChat", msg)
-
-    def do_players(self):
-        self.server.callRemote("getPlayers")
-        
-    def remote_updateShips(self, net_ships):
-        # Sanity check
-        if not net_ships:
-            return
-        print "Received %d ship updates!" % (len(net_ships))
-        ship_view.updateShips(net_ships)
-
-    def remote_log(self, log):
-        for l in log:
-            print l
-
-    def remote_showText(self, text):
-        ship_view.delayedText(text, 5.0)
-
-    def setClientInit(self, init_data):
-
-        # Share init data with ship view
-        ship_view.setClientInit(init_data)
-
-        # Load player scripts
-        self.cscript.setActivePlayer(init_data.player)
-        print "Scripts:", self.cscript.getScriptList()
-        self.scriptWnd.update_list()
-
-        # Cache current server scripts for player
-        self.cscript.setServerScripts(init_data.scripts)
-
-        
-#end GUIClient
+    def quit(self):
+        # tell systems to shut down
+        # normally we would just set self.running to False
+        # but our update loop is based on the Twisted Reactor
+        # Use pygame to give it the QUIT signal
+        e = pygame.event.Event(pygame.QUIT)
+        pygame.event.post(e)
+
+#end GUIGameClass
 
 def main():
 
-    client = GUIClient()
-    client.REF = client
-    
-    client.createDialogs()
+    # MAIN GAMECLASS
+    game = GUIGameClass()
     
+    #shipImg = resource_stream('pyshipcommand_gui', 'assets/raptor.png')
+    #shipImg = pygame.image.load(shipImg)
+    #shipImg = shipImg.convert_alpha()
+    #ship_view.SHIP_IMG = pygame.transform.rotozoom(shipImg, -90, 0.25)
+
+    #cmdImg = resource_stream('pyshipcommand_gui', 'assets/command.png')
+    #cmdImg = pygame.image.load(cmdImg)
+    #ship_view.MSHIP_IMG = cmdImg.convert_alpha()
+
     # Manually connect
     #client.connect(SERVER_ADDR, SERVER_PORT)
     #client.login(DEFAULT_USER, DEFAULT_PASS)
+
+    # Initialize
+    game.initialize()
+
+    # Create and switch to starting state
+    game.changeState(LoginState)
     
-    # trigger update loop
-    client.update_task = task.LoopingCall(client.update)
-    client.update_task.start(1.0/DESIRED_FPS)
-    g_uirender.start()
+    # Update loop is slightly different than normal.
+    # Instead of a running while True loop, we register
+    # an asynchronous task that runs at our desired frame rate
+    update_task = task.LoopingCall(game.update)
+    update_task.start(1.0/DESIRED_FPS)
+
+    # blocks until reactor is shutdown.
+    game.uirender.start()
 
-    client.disconnect()
+    update_task.stop()
+    game.shutdown()
 #end main
 
 if __name__ == "__main__":
Add a comment to this file

pyshipcommand_gui/assets/pyship_logo.png

Added
New image

pyshipcommand_gui/client.py

+
+# SYSTEM
+
+# ADDITIONAL LIBRARIES
+from twisted.spread import pb
+
+# LOCAL
+from states.loading import LoadingState
+from states.viewer import ViewerState
+from cscripts import ClientScriptMgr
+from pyshipcommand.network import PBClient, NetVector, NetShip, NetInit, NetScript, NetCelestialBody
+
+class BaseClient(PBClient):
+    def __init__(self):
+        PBClient.__init__(self)
+
+    def remote_print(self, msg):
+        print msg
+#end BaseClient
+
+class RegisterClient(BaseClient):
+
+    def login(self, username, password):
+        self.username = username
+        self.password = password
+        BaseClient.login(self, "register", "account")
+
+    def connected(self):
+        dfr = self.server.callRemote("registerAccount", self.username, self.password)
+        dfr.addCallback(self.disconnect)
+
+    def disconnect(self, n):
+        BaseClient.disconnect(self)
+#end RegisterClient
+
+pb.setUnjellyableForClass(NetShip, NetShip)
+pb.setUnjellyableForClass(NetInit, NetInit)
+pb.setUnjellyableForClass(NetScript, NetScript)
+pb.setUnjellyableForClass(NetCelestialBody, NetCelestialBody)
+class GUIClient(BaseClient, pb.Referenceable):
+    
+    def __init__(self, gameclass):
+        BaseClient.__init__(self)
+        self.REF = self
+        self.gc = gameclass
+
+        self.scripts = ClientScriptMgr()
+
+    def connected(self):
+        self.gc.changeState(LoadingState)
+
+    def exit(self):
+        self.gc.quit()
+
+    # SERVER COMMUNICATION
+    def info(self):
+        self.server.callRemote("info")
+
+    def giveScript(self, name, source):
+        self.server.callRemote("giveScript", name, source)
+
+    def addShip(self, pos):
+        self.server.callRemote("addShip", NetVector.fromVector(pos))
+
+    def moveShip(self, ship_id, target_pos):
+        self.server.callRemote("moveShip", ship_id, NetVector.fromVector(target_pos))
+
+    def orbitShip(self, ship_id, target_pos, radius):
+        self.server.callRemote("orbitShip", ship_id, NetVector.fromVector(target_pos), radius)
+
+    def followShip(self, ship_id, target_id, dist):
+        self.server.callRemote("followShip", ship_id, target_id, dist)
+
+    def scriptShip(self, ship_id, script_name, action):
+        self.server.callRemote("scriptShip", ship_id, script_name, action)
+
+    def giveMessage(self, msg):
+        self.server.callRemote("giveMessage", msg)
+
+    def giveChat(self, msg):
+        self.server.callRemote("giveChat", msg)
+
+    def getPlayers(self):
+        self.server.callRemote("getPlayers")
+
+    def getClientInit(self, cb):
+        dfr = self.server.callRemote("getClientInit")
+        dfr.addCallback(self.setClientInit)
+        dfr.addCallback(cb)
+
+    # CLIENT CALLBACKS
+
+    def remote_updateShips(self, net_ships):
+        # Sanity check
+        if not net_ships:
+            return
+        print "Received %d ship updates!" % (len(net_ships))
+
+        # We only use ship updates when we are in the ViewerState
+        state = self.gc.getActiveState()
+        if isinstance(state, ViewerState):
+            state.updateShips(net_ships)
+
+    def remote_log(self, log):
+        for l in log:
+            print l
+
+    def remote_showText(self, text):
+        # We only send text when in ViewerState
+        state = self.gc.getActiveState()
+        if isinstance(state, ViewerState):
+            state.delayedText(text, 5000)
+
+    def setClientInit(self, init_data):
+        # Load player scripts
+        self.scripts.setActivePlayer(init_data.player)
+        print "Scripts:", self.scripts.getScriptList()
+
+        # Cache current server scripts for player
+        self.scripts.setServerScripts(init_data.scripts)
+        return init_data
+
+#end GUIClient

pyshipcommand_gui/dialogs.py

         exitBtn.connect_signal(SIG_CLICKED, self._quit)
         self.child.add_child(6, 0, exitBtn)
         
-        # Center dialog on screen
-        self.topleft = ((screen_width-self.width)/2, (screen_height-self.height)/2)
+        # Position dialog in middle/lower half of screen
+        self.topleft = ((screen_width-self.width)/2, screen_height/2)
         
     def populateUser(self, username):
         self.userEntry.set_text(username)
 
         
     def _quit(self):
-        self.client.do_exit()
+        self.client.exit()
         
 #end LoginDialog
 
Add a comment to this file

pyshipcommand_gui/states/__init__.py

Empty file added.

pyshipcommand_gui/states/loading.py

+
+# SYSTEM
+from random import random
+
+# ADDITIONAL LIBRARIES
+import pygame
+
+# LOCAL
+from djlib.game import GameState
+from djlib.primitives import Vector
+
+from viewer import ViewerState
+
+# CONSTANTS
+MIN_LOADING = 1.0
+STAR_SPEED = 1.0
+STAR_BLUR = 5
+
+# TestState
+class LoadingState(GameState):
+
+    def __init__(self):
+        GameState.__init__(self)
+
+        # Itemize LoginState variables for reference
+
+    def initialize(self):
+        """Called the first time the game is changed to this state
+           during the applications lifecycle."""
+
+    def enter(self):
+        """Called every time the game is switched to this state."""
+        self.gc.client.getClientInit(self.setClientInit)
+
+    def processInput(self):
+        """Called during normal update/render period for this state
+           to process it's input."""
+
+    def update(self):
+        """Called during normal update/render period for this state
+           to update it's local or game data."""
+
+    def render(self):
+        """Called during normal update/render period for this state
+           to render it's data in a specific way."""
+        # get render surface
+        rs = self.gc.rsurf
+        rs.fill(self.gc.STAR_COLOR)
+
+        # Now apply UI
+        #rs.blit(self.gc.uirender.screen, (0,0), None, pygame.BLEND_ADD)
+
+        pygame.display.update()
+
+    def leave(self):
+        """Called whenever we switch from this state to another."""
+
+    def shutdown(self):
+        """Called during application shutdown."""
+
+    def setClientInit(self, client_init):
+        self.changeState(ViewerState, client_init)
+
+
+#end TestState
+

pyshipcommand_gui/states/login.py

+
+# SYSTEM
+from math import pi
+from pkg_resources import resource_stream
+
+# ADDITIONAL LIBRARIES
+import pygame
+
+# LOCAL
+from djlib.game import GameState
+from pyshipcommand_gui.dialogs import LoginDialog
+from djlib.primitives import Circle, Point, Rect
+
+#REMOVE
+from pyshipcommand_gui.client import RegisterClient
+
+# CONSTANTS
+TITLE_POS = (100, 50)
+ORBIT_RADIUS = 500
+ORBIT_SPEED = 0.04
+
+class LoginState(GameState):
+
+    def __init__(self):
+        GameState.__init__(self)
+
+        # Itemize LoginState variables for reference
+        self.titleImg = None
+        self.loginWnd = None
+        self.star_period = 0.0
+
+    def initialize(self):
+        """Called the first time the game is changed to this state
+           during the applications lifecycle."""
+        rs = resource_stream('pyshipcommand_gui', 'assets/pyship_logo.png')
+        self.titleImg = pygame.image.load(rs)
+
+        # Create Login Dialog
+        (w,h) = self.gc.rsurf.get_size()
+        self.loginWnd = LoginDialog(self.gc.client, RegisterClient(), w, h)
+        self.loginWnd.populateUser(self.gc.DEFAULT_USER)
+        self.loginWnd.populateServer(self.gc.DEFAULT_SERVER, self.gc.DEFAULT_PORT)
+
+    def enter(self):
+        """Called every time the game is switched to this state."""
+        self.gc.uirender.add_widget(self.loginWnd)
+        #self.loginWnd.resetPass()
+        self.loginWnd.set_focus()
+
+    def processInput(self):
+        """Called during normal update/render period for this state
+           to process it's input."""
+
+    def update(self):
+        """Called during normal update/render period for this state
+           to update it's local or game data."""
+        self.star_period += ORBIT_SPEED * self.gc.time_step
+        if self.star_period > (2.0*pi):
+            self.star_period = self.star_period - (2.0*pi)
+
+    def render(self):
+        """Called during normal update/render period for this state
+           to render it's data in a specific way."""
+        # get render surface
+        rs = self.gc.rsurf
+        rs.fill(self.gc.COLOR_BLACK)
+
+        # update stars
+        star_orbit = Circle(Point(0,0), ORBIT_RADIUS)
+        star_pos = star_orbit.pointOnCircle(self.star_period)
+        star_pos = Point(int(star_pos[0]), int(star_pos[1]))
+        star_view = Rect.fromPointSize(star_pos,
+                                       *self.gc.rsurf.get_size())
+        #print str(star_view)
+
+        self.gc.stars.setView(star_view)
+        self.gc.stars.draw(rs, star_view)
+
+        # Draw title image if present
+        if self.loginWnd:
+            rs.blit(self.titleImg, TITLE_POS)
+
+        # Now apply UI
+        #g_uirender.update()
+        rs.blit(self.gc.uirender.screen, (0,0), None, pygame.BLEND_ADD)
+
+        pygame.display.update()
+
+    def leave(self):
+        """Called whenever we switch from this state to another."""
+        self.gc.uirender.remove_widget(self.loginWnd)
+
+    def shutdown(self):
+        """Called during application shutdown."""
+        self.loginWnd.destroy()
+
+#end LoginState
+

pyshipcommand_gui/states/viewer.py

+
+# SYSTEM
+from pkg_resources import resource_stream
+from os import path
+from glob import glob
+
+# ADDITIONAL LIBRARIES
+import pygame
+from pygame import K_UP, K_DOWN, K_LEFT, K_RIGHT, K_RETURN, K_SLASH
+
+from ocempgui import widgets
+from ocempgui.widgets.Constants import SIG_INPUT, SIG_KEYDOWN, SIG_MOUSEDOWN, SIG_MOUSEMOVE
+from ocempgui.events import INotifyable
+
+# LOCAL
+from djlib.game import GameState
+from djlib.primitives import Vector, Rect
+from djlib.spatial import ExpandingRectTree
+from pyshipcommand_gui.viewer import ShipViewer
+import pyshipcommand_gui.dialogs as dialogs
+
+# TestState
+class ViewerState(GameState, INotifyable):
+
+    # CONSTANTS
+    SCROLL_RECT_OFFSET = 50
+    SCROLL_SPEED = 5
+    SHIP_RADIUS = 30
+
+    # ASSETS
+    SHIP_IMG = None
+    MSHIP_IMG = None
+
+    SUN_COLOR = pygame.Color(255, 255, 0)
+    PLANET_COLOR = pygame.Color(0, 128, 255)
+    ASTEROID_COLOR = pygame.Color(128, 128, 128)
+
+    SEL_COLOR = pygame.Color(0, 255, 0)
+
+    def __init__(self):
+        GameState.__init__(self)
+
+        # Itemize ViewerState members for reference
+        self.scroll_rect = None
+        self.scroll_dir = None
+
+        self.ship_view = None
+        self.sel_ship = None
+
+        self.delay_text = None
+
+        self.universe = None
+        self.view_rect = None
+        self.tree = None
+        self.view_node = None
+
+        self.script_wnd = None
+        self.ship_wnd = None
+        self.cmd_wnd = None
+
+    def initialize(self):
+        """Called the first time the game is changed to this state
+           during the applications lifecycle."""
+        (w,h) = self.gc.rsurf.get_size()
+        self.view_rect = Rect.fromSides(0, 0, w, h)
+        self.tree = ExpandingRectTree(Rect.fromSides(0, 0, w, h))
+
+        self.delay_text = []
+
+        # Resources       
+        shipImg = resource_stream('pyshipcommand_gui', 'assets/raptor.png')
+        shipImg = pygame.image.load(shipImg)
+        shipImg = shipImg.convert_alpha()
+        self.SHIP_IMG = pygame.transform.rotozoom(shipImg, -90, 0.25)
+
+        cmdImg = resource_stream('pyshipcommand_gui', 'assets/command.png')
+        cmdImg = pygame.image.load(cmdImg)
+        self.MSHIP_IMG = cmdImg.convert_alpha()
+
+        # Create ship, script, and cmd dialogs
+        self._createDialogs()
+
+    def enter(self, client_init):
+        """Called every time the game is switched to this state."""
+        self.ship_view = ShipViewer(self.gc.rsurf)
+        self.ship_view.setClientInit(client_init)
+        self.ship_view.SHIP_IMG = self.SHIP_IMG
+        self.ship_view.MSHIP_IMG = self.MSHIP_IMG
+        self.ship_view.FONT = self.gc.dfont
+
+        self.updateUniverse(client_init.universe)
+        self.centerView(client_init.start_pos)
+
+        self.scroll_dir = None
+
+        # Show dialogs
+        ui = self.gc.uirender
+        ui.add_widget(self.cmd_wnd)
+        ui.add_widget(self.script_wnd)
+        ui.add_widget(self.ship_wnd)
+
+        # Update dialogs
+        self.script_wnd.update_list()
+
+        # Register for input messages
+        event_mgr = self.gc.uirender.get_managers()[0]
+        event_mgr.add_object(self, SIG_KEYDOWN, SIG_MOUSEDOWN, SIG_MOUSEMOVE)
+
+    def notify(self, event):
+        if event.signal == SIG_KEYDOWN:
+            # Handle arrow keys
+            if event.data.key in (K_UP, K_DOWN, K_RIGHT, K_LEFT):
+                self.move(event.data.key)
+            elif event.data.key in (K_RETURN, K_SLASH):
+                self.gc.uirender.set_active_layer(self.cmd_wnd.depth)
+                self.cmd_wnd.set_focus()
+                if event.data.key is K_SLASH:
+                    self.cmd_wnd.set_text('/')
+                    self.cmd_wnd.set_caret(1)
+            
+        elif event.signal == SIG_MOUSEDOWN:
+            # set keyboard focus
+            self.gc.uirender.set_active_layer(0)
+
+            if event.data.button == 1: #Left Click
+                real_pos = Vector(*event.data.pos) + self.view_rect.pos
+                self.sel_ship = self.ship_view.pickShip(real_pos)
+                self.ship_wnd.setShip(self.sel_ship)
+                self.script_wnd.setShip(self.sel_ship)
+                print str(self.sel_ship)
+
+        elif event.signal == SIG_MOUSEMOVE:
+            # Set scroll direction
+            mp = event.data.pos
+            self.scrollDir = None
+            '''
+            if not self.scrollRect.collidepoint(mp):
+                if mp[0] < self.scrollRect.left:
+                    self.scrollDir = K_LEFT
+                elif mp[0] > self.scrollRect.right:
+                    self.scrollDir = K_RIGHT
+                elif mp[1] < self.scrollRect.top:
+                    self.scrollDir = K_UP
+                elif mp[1] > self.scrollRect.bottom:
+                    self.scrollDir = K_DOWN
+            '''
+
+    def processInput(self):
+        """Called during normal update/render period for this state
+           to process it's input."""
+
+        # Handle map scrolling
+        if self.scroll_dir:
+            self.move(self.scroll_dir)
+
+    def update(self):
+        """Called during normal update/render period for this state
+           to update it's local or game data."""
+
+        # update the ship view
+        self.ship_view.update(self.gc.time_step)
+
+        # Remove any expired delay text
+        while len(self.delay_text) > 0 and self.gc.time > self.delay_text[0][0]:
+            print "Removing Text", self.gc.time, self.delay_text[0]
+            del self.delay_text[0]
+
+    def render(self):
+        """Called during normal update/render period for this state
+           to render it's data in a specific way."""
+        # get render surface
+        rs = self.gc.rsurf
+        rs.fill(self.gc.COLOR_BLACK)
+
+        pos = -self.view_rect.pos
+
+        # Draw stars
+        self.gc.stars.draw(rs, self.view_rect)
+
+        # Draw universe
+        if self.universe:
+            uni_node = self.universe.minNode(self.view_rect)
+            if not uni_node:
+                uni_node = self.universe
+            self.ship_view.drawTree(rs, uni_node, pos)
+
+            colors = [self.SUN_COLOR, self.PLANET_COLOR, self.ASTEROID_COLOR]
+
+            for body in uni_node:
+                #ignore unknown types
+                if body.type < 0:
+                    continue
+
+                pygame.draw.circle(rs, colors[body.type], (pos+body.pos).intArgs(), body.radius)
+                #pygame.draw.circle(rs, colors[body.type], (100 * body.type,100), body.radius)
+
+        # Draw ships
+        self.ship_view.draw(rs, self.view_rect)
+
+        # draw selection
+        if self.sel_ship:
+            pygame.draw.circle(rs, self.SEL_COLOR, (pos+self.sel_ship.pos).intArgs(), self.SHIP_RADIUS, 2)
+
+        # draw delayed text
+        drawPos = Vector(20, self.view_rect.height() - 50)
+        for dText in self.delay_text[::-1]:
+            self.ship_view.renderText(rs, drawPos.intArgs(), dText[1])
+            drawPos -= Vector(0, 20)
+
+        # draw current FPS over everything
+        self.ship_view.renderText(rs, (0,0), str(int(self.gc.fpsClock.get_fps())))
+
+        # Now apply UI
+        rs.blit(self.gc.uirender.screen, (0,0), None, pygame.BLEND_ADD)
+
+        pygame.display.update()
+
+    def delayedText(self, text, delay):
+        if not isinstance(text, list):
+            text = [str(text)]
+            
+        for t in text:
+            print t
+            self.delay_text.append( (self.gc.time+delay, t) )
+        print self.delay_text
+
+    def leave(self):
+        """Called whenever we switch from this state to another."""
+        # Unregister for input messages
+        event_mgr = self.gc.uirender.get_managers()[0]
+        event_mgr.remove_object(self, SIG_KEYDOWN, SIG_MOUSEDOWN, SIG_MOUSEMOVE)
+
+        # Hide dialogs
+        ui = self.gc.uirender
+        ui.remove_widget(self.cmd_wnd)
+        ui.remove_widget(self.script_wnd)
+        ui.remove_widget(self.ship_wnd)
+
+        self.ship_view = None
+
+    def shutdown(self):
+        """Called during application shutdown."""
+        self.font = None
+        self.SHIP_IMG = None
+        self.MSHIP_IMG = None
+
+    def updateUniverse(self, net_bodies):
+
+        # for now, we only should get one universe update
+        # so overwrite any existing data
+        w, h = self.view_rect.width(), self.view_rect.height()
+        self.universe = ExpandingRectTree(Rect.fromSides(0, 0, w, h))
+        body_count = [0]*4
+        for body in net_bodies:
+            self.universe.insert(body)
+            body_count[body.type] += 1
+            #print "Body[%d] %s(%d)" % (body.type, str(body.pos), body.radius)
+
+        print "Universe contains %d Suns, %d Planets, %d Asteroids, %d Unknowns" % tuple(body_count)
+
+    def updateShips(self, net_ships):
+        self.ship_view.updateShips(net_ships)
+
+    def move(self, event):
+        vec = Vector(0, 0)
+        if event == pygame.K_UP:
+            vec = Vector(0, -self.SCROLL_SPEED)
+        elif event == pygame.K_DOWN:
+            vec = Vector(0, self.SCROLL_SPEED)
+            
+        if event == pygame.K_LEFT:
+            vec = Vector(-self.SCROLL_SPEED, 0)
+        elif event == pygame.K_RIGHT:
+            vec = Vector(self.SCROLL_SPEED, 0)
+            
+        self.view_rect.move(vec)
+        self.gc.stars.setView(self.view_rect)
+
+
+    def centerView(self, pos=None):
+
+        # Use mothership pos if no pos is specified
+        if not pos:
+            pos = self.ships[self.ship_view.mship].pos
+
+        d = pos - self.view_rect.center()
+        print "%s -> %s" % (self.view_rect.center(), pos)
+        self.view_rect.move(d)
+        print str(self.view_rect)
+        self.gc.stars.setView(self.view_rect, True)
+
+    def _createDialogs(self):
+        print "CREATING VIEWER DIALOGS!!!!"
+        (w,h) = self.gc.rsurf.get_size()
+        
+        # CLI Entry
+        edit = widgets.Entry()
+        edit.topleft = (0, h-20)
+        edit.minsize = w, 20
+        edit.depth = 1
+        edit.connect_signal(SIG_INPUT, self.processCmd, edit)
+        self.cmd_wnd = edit
+
+        # Script widget
+        self.script_wnd = dialogs.ScriptWidget(w-205, 0, self.gc.client.scripts,
+                                              self.cmd_import,
+                                              self.cmd_upload, self.cmd_ship)
+
+        # Ship Info
+        self.ship_wnd = dialogs.ShipInfo(w-205, self.script_wnd.height)
+
+    # CMD HANDLERS
+
+    def processCmd(self, edit):
+
+        # Handle edit box
+        line = edit.text
+        edit.set_text("")
+        edit.set_dirty(1)
+        
+        # Parse the command
+        if not line or not len(line) > 0:
+            return
+
+        # Raw text should be treated as a chat message.
+        if line[0] != '/':
+            self.cmd_chat(line)
+            return
+
+        # Split line and remove leading '/'
+        commandParts = line[1:].split()
+        command = commandParts[0].lower()
+        args = commandParts[1:]
+
+        # Dispatch the command to the appropriate method.
+        try:
+            method = getattr(self, 'cmd_' + command)
+        except AttributeError, e:
+            print 'Error: no such command.'
+        else:
+            try:
+                method(*args)
+            except Exception, e:
+                    print 'Error', str(e)
+
+    def cmd_help(self, command=None):
+        """help [command]: List commands, or show help on the given command"""
+        if command:
+            print (getattr(self, 'cmd_' + command).__doc__)
+        else:
+            commands = [cmd[3:] for cmd in dir(self) if cmd.startswith('cmd_')]
+            print ("Valid commands: " +" ".join(commands))
+
+    def cmd_exit(self):
+        self.gc.quit()
+
+    def cmd_info(self):
+        self.gc.client.info()
+
+    def cmd_upload(self, scriptfile):
+
+        # Sanity checks
+        if not scriptfile:
+            raise Exception("script <script_data>")
+
+        s = self.gc.client.scripts.getScript(scriptfile)
+        if s:
+            print "sending script:", s.name
+            self.gc.client.giveScript(s.name, s.source)
+            return
+
+        print scriptfile + " not found!"
+
+
+    def cmd_import(self, scriptPath = None):
+
+        if not scriptPath:
+            script_dlg = dialogs.ImportScriptDialog(self.cmd_import, *self.gc.rsurf.get_size())
+            self.gc.uirender.add_widget(script_dlg)
+            script_dlg.set_focus()
+            return
+
+        # Always treat scripts as a list, even if they only specified a file.
+        scriptFiles = [scriptPath]
+        if path.isdir(scriptPath):
+            scriptFiles = glob(path.join(scriptPath,"*.py"))
+
+        for s in scriptFiles:
+            self.gc.client.scripts.importScript(s)
+
+        # Update list contents, even if we could have failed
+        if len(scriptFiles) > 0:
+            self.script_wnd.update_list()
+            #self.script_wnd.select_script(s.name)
+            return
+
+        print "Could not import:" + scriptFiles
+
+    def cmd_reload(self):
+
+        self.gc.client.scripts.reloadScripts()
+        self.script_wnd.update_list()
+
+
+    def cmd_ship(self, cmd, *args):
+        print "cmd_ship", cmd, ":", args
+        if cmd == "create":
+            pos = Vector(0.0, 0.0)
+            if len(args) == 2:
+                pos = Vector(float(args[0]), float(args[1]))
+            print pos
+            self.gc.client.addShip(pos)
+        elif cmd == "move":
+            ship_id = int(args[0])
+            target_pos = Vector(float(args[1]), float(args[2]))
+            print target_pos
+            self.gc.client.moveShip(ship_id, target_pos)
+        elif cmd == "orbit":
+            ship_id = int(args[0])
+            target_pos = Vector(float(args[1]), float(args[2]))
+            radius = float(args[3])
+            self.gc.client.orbitShip(ship_id, target_pos, radius)
+        elif cmd == "follow":
+            ship_id = int(args[0])
+            target_id = int(args[1])
+            dist = float(args[2])
+            self.gc.client.followShip(ship_id, target_id, dist)
+        elif cmd == "script":
+            ship_id = int(args[0])
+            script_name = args[1]
+
+            action = "upgrade" # default to an upgrade
+            if len(args) > 2:
+                action = args[2]
+
+            self.gc.client.scriptShip(ship_id, script_name, action)
+
+    def cmd_scroll(self, *args):
+        scroll_speed = ShipViewer.SCROLL_SPEED
+        if len(args) == 1:
+            scroll_speed = int(args[0])
+        ship_view.SCROLL_SPEED = scroll_speed
+
+    def cmd_msg(self, *args):
+        print "cmd_msg, ", args
+        self.gc.client.giveMessage(args)
+
+    def cmd_home(self):
+        ship_view.centerView()
+
+    def cmd_chat(self, msg):
+        self.gc.client.giveChat(msg)
+
+    def cmd_players(self):
+        self.gc.client.getPlayers()
+        
+
+#end TestState
+

pyshipcommand_gui/viewer.py

 class ShipViewer:
     
     # CONSTANTS
-    DEFAULT_SERVER_STEP = 1.0
-    SCROLL_SPEED = 5
     SHIP_RADIUS = 30
     
     # ASSETS
     SHIP_IMG = None
     MSHIP_IMG = None
-    STAR_COLOR = pygame.Color(255, 255, 255)
-
-    SUN_COLOR = pygame.Color(255, 255, 0)
-    PLANET_COLOR = pygame.Color(0, 128, 255)
-    ASTEROID_COLOR = pygame.Color(128, 128, 128)
+    FONT = None
 
     FONT_COLOR = pygame.Color(0, 255, 0)
-    SEL_COLOR = pygame.Color(0, 255, 0)
-
+    TREE_COLOR = pygame.Color(128, 128, 128)
 
     def __init__(self, rs):
         self.ships = {}
         self.mship = None
         self.destroyed_ships = []
-        self.time = 0
-        self.lerpTime = 0
-        self.serverStep = self.DEFAULT_SERVER_STEP
+        
+        self.lerp_time = 0
+        self.server_step = 0
         self.player_id = 0
 
-        self.delayText = []
-        self.sel_ship = None
-
-        self.universe = None
-
         (w,h) = rs.get_size()
-        self.view_rect = Rect.fromSides(0, 0, w, h)
-        self.starGen = StarGenerator((w/2, h/2), (w, h), 25)
 
         #ExpandingRectTree.MAX_DATA = 2
         self.tree = ExpandingRectTree(Rect.fromSides(0, 0, w, h))
         self.view_node = None
 
-        self.font = pygame.font.Font(pygame.font.get_default_font(), 12)
-        if not self.font:
-            print "Default Font not loaded!"
-
     def setClientInit(self, init_data):
 
         print "ClientInit Received with Player ID %d" % (self.player_id)
         print "View Position: %s" % (str(init_data.start_pos))
 
         self.player_id = init_data.player_id
-        self.mship = init_data.mship_id
         self.setServerStep(init_data.server_step)
 
-        self.updateUniverse(init_data.universe)
-
-        self.centerView(init_data.start_pos)
-
+        self.updateShips(init_data.ships)
+        self.mship = self.ships[init_data.mship_id]
+        
         
     def updateShips(self, net_ships):
 
                 self.tree.insert(nship)
                 
         # reset interpolation time
-        self.lerpTime = 0.0
-
-    def updateUniverse(self, net_bodies):
-
-        # for now, we only should get one universe update
-        # so overwrite any existing data
-        w, h = self.view_rect.width(), self.view_rect.height()
-        self.universe = ExpandingRectTree(Rect.fromSides(0, 0, w, h))
-        body_count = [0]*4
-        for body in net_bodies:
-            self.universe.insert(body)
-            body_count[body.type] += 1
-            #print "Body[%d] %s(%d)" % (body.type, str(body.pos), body.radius)
+        self.lerp_time = 0.0
 
-        print "Universe contains %d Suns, %d Planets, %d Asteroids, %d Unknowns" % tuple(body_count)
-            
     def update(self, dt):
-        self.time += dt
         # Interpolate ship positions between server updates
-        self.lerpTime += dt
-        int_time = self.lerpTime/self.serverStep
+        self.lerp_time += dt
+        int_time = self.lerp_time/self.server_step
         for ship in self.ships.itervalues():
             ship.interpolate(int_time)
-
-        # Remove any expired delay text
-        while len(self.delayText) > 0 and self.time > self.delayText[0][0]:
-            del self.delayText[0]
-        
-            
-    def draw(self, rs):
-        pos = -self.view_rect.pos
-
-        star_pos = None
-        for sector in self.starGen.sectors:
-            for star in sector.stars:
-                star_pos = pos + star.pos
-                pygame.draw.circle(rs, self.STAR_COLOR, star_pos.intArgs(), star.radius)
+   
+    def draw(self, rs, view_rect = None):
+        pos = -view_rect.pos
 
         # Debug render of spatial tree
-        new_node = self.tree.minNode(self.view_rect)
+        new_node = self.tree.minNode(view_rect)
         if not new_node:
             new_node = self.tree
         if new_node != self.view_node:
             print "New view node has %d ships." % (new_node.count())
             self.view_node = new_node
-        self.drawTree(rs, self.view_node)
-
-        # Draw universe
-        if self.universe:
-            uni_node = self.universe.minNode(self.view_rect)
-            if not uni_node:
-                uni_node = self.universe
-            self.drawTree(rs, uni_node)
-
-            colors = [self.SUN_COLOR, self.PLANET_COLOR, self.ASTEROID_COLOR]
-
-            for body in uni_node:
-                #ignore unknown types
-                if body.type < 0:
-                    continue
-
-                pygame.draw.circle(rs, colors[body.type], (pos+body.pos).intArgs(), body.radius)
-                #pygame.draw.circle(rs, colors[body.type], (100 * body.type,100), body.radius)
+        self.drawTree(rs, self.view_node, pos)
 
         # Draw Ships
         offset = None
                     wep_color = pygame.Color(255, 0, 0, int(ship.weapon_a*255))
                     pygame.draw.line(rs, wep_color, (pos+ship.pos).intArgs(), (pos+target_ship.pos).intArgs(), 2)
 
-        # draw selection
-        if self.sel_ship:
-            pygame.draw.circle(rs, self.SEL_COLOR, (pos+self.sel_ship.pos).intArgs(), self.SHIP_RADIUS, 2)
-
-        # draw delayed text
-        drawPos = Vector(20, self.view_rect.height() - 50)
-        for dText in self.delayText[::-1]:
-            self.renderText(rs, drawPos.intArgs(), dText[1])
-            drawPos -= Vector(0, 20)
-
-
-    def drawTree(self, rs, node):
-        true_pos = node.rect.pos - self.view_rect.pos
+    def drawTree(self, rs, node, pos):
+        true_pos = pos + node.rect.pos
         rect = pygame.Rect(true_pos.intArgs(), node.rect.size.intArgs())
-        pygame.draw.rect(rs, self.STAR_COLOR, rect, 2)
+        pygame.draw.rect(rs, self.TREE_COLOR, rect, 2)
         self.renderText(rs, true_pos.intArgs(), str(len(node.data) if node.data else 0))
         if node.children:
             for child in node.children:
-                self.drawTree(rs, child)
+                self.drawTree(rs, child, pos)
 
     def renderText(self, rs, pos, text, centered = False):
-        surf = self.font.render(text, False, self.FONT_COLOR)
+        surf = self.FONT.render(text, False, self.FONT_COLOR)
         if centered:
             pos = (pos[0]-surf.get_width()/2, pos[1]-surf.get_height()/2)
         rs.blit(surf, pos)
 
-    def delayedText(self, text, delay):
-        if not isinstance(text, list):
-            text = [str(text)]
-            
-        for t in text:
-            print t
-            self.delayText.append( (self.time+delay, t) )
-        print self.delayText
-            
     def setServerStep(self, dt):
         print "Server time step set to %f seconds" % (dt)
-        self.serverStep = dt
-        
-            
-    def move(self, event):
-        vec = Vector(0, 0)
-        if event == pygame.K_UP:
-            vec = Vector(0, -self.SCROLL_SPEED)
-        elif event == pygame.K_DOWN:
-            vec = Vector(0, self.SCROLL_SPEED)
-            
-        if event == pygame.K_LEFT:
-            vec = Vector(-self.SCROLL_SPEED, 0)
-        elif event == pygame.K_RIGHT:
-            vec = Vector(self.SCROLL_SPEED, 0)
-            
-        self.view_rect.move(vec)
-        self.starGen.setView(self.view_rect)
-
-    def centerView(self, pos=None):
+        self.server_step = dt
 
-        # Use mothership pos if no pos is specified
-        if not pos:
-            pos = self.ships[self.mship].pos
-
-        d = pos - self.view_rect.center()
-        print "%s -> %s" % (self.view_rect.center(), pos)
-        self.view_rect.move(d)
-        print str(self.view_rect)
-        self.starGen.setView(self.view_rect, True)
-
-    def pickShip(self, mouse_pos):
-        real_pos = Vector(*mouse_pos) + self.view_rect.pos
+    def pickShip(self, real_pos):
+        
 
         # Compare mouse pos against all visible ships
         close_ship = None
                 close_dist = dist
 
         # pick closest ship within click range
-        self.sel_ship = close_ship
-        return self.sel_ship
+        return close_ship
 
 #end ShipViewer
 
 import random
 class StarGenerator:
 
-	STARS_MAX_SIZE = 3
+    STAR_COLOR = pygame.Color(255, 255, 255)
+    STARS_MAX_SIZE = 3
 
-	from djlib.primitives import Circle as Star
+    from djlib.primitives import Circle as Star
 
-	def __init__(self, sector_size, screen_size, star_freq):
+    def __init__(self, sector_size, screen_size, star_freq):
             self.sector_size = sector_size
             self.star_freq = star_freq
 
             for y in xrange(self.repeat[1]):
                 for x in xrange(self.repeat[0]):
                     self.sectors.append(self._generateSector(star_pos + Vector(x*sector_size[0], y*sector_size[1])))
-	
-	def setView(self, view_rect, full_gen = False):
+    
+    def setView(self, view_rect, full_gen = False):
             if self.star_bounds.contains(view_rect):
                 return
 
             # Delete any sectors that are no longer visible
             self.sectors = [sector for sector in self.sectors if self.star_bounds.contains(sector.pos)]
             print "Deleted %d sectors" % (sect_count - len(self.sectors))
-		
-	def _generateSector(self, sector_pos):
+
+    def draw(self, rs, view_rect = None):
+        pos = Vector(0,0)
+        if view_rect:
+            pos = view_rect.pos
+
+        star_pos = None
+        for sector in self.sectors:
+            for star in sector.stars:
+                star_pos = star.pos - pos
+                pygame.draw.circle(rs, self.STAR_COLOR, star_pos.intArgs(), star.radius)
+        
+    def _generateSector(self, sector_pos):
             
             # seed random with the sector_pos so starts will always look the same in that sector
             state = random.getstate()
             for i in xrange(self.star_freq):
                 vec = Vector(random.randint(sector_pos[0], sector_pos[0]+self.sector_size[0]), 
                              random.randint(sector_pos[1], sector_pos[1]+self.sector_size[1]))
-                stars.append(self.Star(vec, random.randint(1, self.STARS_MAX_SIZE)))		
+                stars.append(self.Star(vec, random.randint(1, self.STARS_MAX_SIZE)))        
             
             # restore random state
             random.setstate(state)
                                        'ship_cmd.py',
                                        'tracker.py'],
                     'pyshipcommand_gui':['assets/command.png',
-                                         'assets/raptor.png'],
+                                         'assets/raptor.png',
+                                         'assets/title_logo.png'],
                    },
 
     # files not in the module/packge dir that are needed, eg art assets,README files, init scripts
     # setup_requires = ['hgdistver'],
 
     # optinal packages needed to install/run this app
-    install_requires = ['Twisted==12.0.0',
+    install_requires = ['Twisted>=12.0.0',
                         'zope.interface==3.8.0',
                         'zope.event==3.5.2',
                         'zope.component==3.12.1',
     cmdclass = {'test': PyTest},
     
     # Extra locations to look for dependincies if not found apart from PyPi
-    dependency_links = ['https://sf.net/projects/ocemp/files/ocempgui/0.2.9/',],
+    dependency_links = ['https://sourceforge.net/projects/ocemp/files/ocempgui/0.2.9/OcempGUI-0.2.9.tar.gz#egg=OcempGUI-0.2.9',],
 )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.