コード例 #1
0
class Environment(): #in an MVC system , this would be a controller
        ''' The environment class contains the state of the game. The server has the master version, the clients have slave versions (updated through the network) '''
        NEXT_PLAYER_ID=1
        NEXT_BUILDING_ID=1
        FPS=30
        ATTACK_DISTANCE =3
        BUILDING_DISTANCE =6
        GAME_DURATION = 10#15 seconds #15 * 60 # 15 minutes
    
        def __init__(self):
                '''State: Players,Buildings, Time, Resourse Pool'''
                self.players    = {}
                self.buildings  = {}
                self.TimeLeft = 0 
                self.TrueTimeLeft = 0  
                self.Tick = 0         
                self.scores =[0,0]     
                self.GameOver =False
                self.GameStarted =False
                self.width = 80.0
                self.height = 48.0
                self.view =None
                self.team =None
                self.actions =None
                self.IsServer = True
                self.ResourcePool = ResourcePool()
                
        #Helper Functions
        def createPlayer(self, player_id,team):
                '''add a player to the given team'''
                player = Player()
                player.team = team

                playerId = id(player)
                player.player_id = player_id
                #player.player_id = Environment.NEXT_PLAYER_ID
                #Environment.NEXT_PLAYER_ID = Environment.NEXT_PLAYER_ID + 1
        
                self.players[playerId] = player        
                return player

        def createBuilding(self, team,pos):
                '''add a building to the given team'''
                building = Building()
                building.team = team
                building.position =pos
                bid = id(building)
                building.building_id = Environment.NEXT_BUILDING_ID
                Environment.NEXT_BUILDING_ID = Environment.NEXT_BUILDING_ID + 1
                self.buildings[bid] = building
                
        
                return building

        
        def StartGame(self):
                self.Tick=0
                self.GameStarted=True
                self.GameOver = False
                self.TrueTimeLeft=Environment.GAME_DURATION
                self.TimeLeft = int(self.TrueTimeLeft)
                for playerId in self.players:
                     self.players[playerId].sides=3
                     self.players[playerId].resources=0
                     
                self.buildings.clear()

                
        def updateTime(self):
                self.Tick += 1.0/Environment.FPS
                if(self.GameStarted):
                        self.TrueTimeLeft-=1.0/Environment.FPS
                        self.TimeLeft = int(self.TrueTimeLeft)  
                        if(     self.TrueTimeLeft<=0):
                            self.GameOver =True
                            self.TrueTimeLeft =0


        def updatePositions(self):
                for playerId in self.players:
                     self.players[playerId].updatePosition( 1.0/Environment.FPS)

        def Update(self):
                
                startTime = time.time()
                self.updateTime()
                self.scores =self.calculateScores()
                self.updatePositions()
                if(self.actions<>None):
                        self.processNewState()
                self.writeStateToServer()
                self.view.paint(self.Tick)
                for event in pygame.event.get():
                        if event.type == pygame.QUIT:
                                pygame.quit()
                                #sys.exit()
                        if event.type == pygame.KEYDOWN:
                                if event.key==pygame.K_s:
                                        self.StartGame()
                #print time.time()-startTime
                                        
                        
        def processNewState(self):
            
                for action in self.actions:
                    found= False
                    for playerId in self.players:
                        if(self.players[playerId].player_id)==int(action[0]):
                            self.players[playerId].action=int(action[2])
                            pos = action[3].split(',')
                            self.players[playerId].targetPosition = Vector2D(float(pos[0]),float(pos[1]))
                            found =True
                            break

                    if(not found):
                        self.createPlayer(int(action[0]),int(action[1]))
                     

                for playerId in self.players:
                        
                        player = self.players[playerId]
                        

                        if(player.action == Player.ATTACK): #ATTACK
                                self.handleAttack(player)

                        elif(player.action == Player.BUILD): #building
                                self.handleBuild(player)

                        elif(player.action == Player.UPGRADE): #building
                                self.handleUpgrade(player)

                        elif(player.action == Player.SCAN): #building
                                self.handleScan(player)

                        elif(player.action == Player.IDLE):
                                self.handleIdle(player)
                                              
                        for b in self.buildings.itervalues():
                             if   (b.getPosition() - player.getPosition()).length < b.size and b.isTrap() and b.team<>player.team:         
                                        b.explode(player,self.Tick)   
        

        def handleAttack(self,player):
                if(player.sides>=3):
                        player.performAttack(self.Tick)  
                        for p in self.players.itervalues():
                                if (p.team != player.team) and (p.getPosition() - player.getPosition()).length < Environment.ATTACK_DISTANCE:
                                        p.hit(self.Tick)
                        for b in self.buildings.itervalues():
                                if (b.team != player.team) and (b.getPosition() - player.getPosition()).length < Environment.ATTACK_DISTANCE:
                                        b.hit(self.Tick)

        def handleBuild(self,player):
                ACTION = "BUILD"
                if((self.ResourcePool.getPosition()-player.getPosition()).length< self.ResourcePool.size):
                        ACTION ="MINE"
                else:
                        for b in self.buildings.itervalues():
                                
                                if(b.team == player.team and b.isPolyFactory() and b.resources == 5 and (b.getPosition()- player.getPosition()).length <b.size):
                                        ACTION ="MINE"
                                        break      
                if( ACTION =="MINE"):
                        player.performBuild(self.Tick)  
                        player.mine(self.Tick)
                                         
                else:
                        if(player.resources>0):
                                BUILDING =None
                                for b in self.buildings.itervalues():
                                        if   (b.getPosition() - player.getPosition()).length < b.size:
                                                BUILDING =b
                                                break
                                if BUILDING ==None :
                                        self.createBuilding(  player.team, player.getPosition())                       
                                        player.resources-=1 

                                elif BUILDING.team ==player.team:
                                        player.performBuild(self.Tick) 
                                        BUILDING.build(player,self.Tick) 
        
        def handleUpgrade(self,player):
                allowedUpgradeLoc = False
                if((self.ResourcePool.getPosition()-player.getPosition()).length< self.ResourcePool.size):
                        allowedUpgradeLoc=True
                else:
                        for b in self.buildings.itervalues():
                                if(b.team == player.team and b.isPolyFactory() and b.resources == 5 and (b.getPosition()- player.getPosition()).length <b.size): 
                                        allowedUpgradeLoc=True
                                        break
                if(allowedUpgradeLoc):
                       player.upgrade(self.Tick) 

        def handleScan(self,player):
             player.scan(self.Tick)    

        def handleIdle(self,player):

             pass  

        def start(self):
                '''controls the environment by initiating the looping calls'''
                self.TrueTimeLeft=Environment.GAME_DURATION
                self.TimeLeft = int(self.TrueTimeLeft)
                self.view.start('Server')
                if os.path.exists(SERVERDATA):
                        os.remove(SERVERDATA)
                self._renderCall = LoopingCall(self.Update)
                self._renderCall.start(1.0/Environment.FPS)

                self._readCall = LoopingCall( self.readStateFromServer)
                self._readCall.start(1.0/Environment.FPS) 
                


        def calculateScores(self):
        
                score=[0,0]
                for team in range(1,3):
                    for playerId in self.players:

                            player = self.players[playerId]

                            if player.team == team:
                                score[team-1] += player.sides
                                score[team-1] += player.resources

                    for buildingId in self.buildings:
                            building = self.buildings[buildingId]
                            if building.team == team:
                                score[team-1]  += building.sides
                                score[team-1]  += building.resources
                    score[team-1] *= 1000
                return score ;


        #FUNCTIONS FOR NETWORKING
        def writeStateToServer(self):
                string =self.Serialize()
                
                serv_db = shelve.open(SERVERDATA)
                
                try:
                        serv_db['data']= { 'time': str(time.time()), 'string': string }                      
                finally:
                        serv_db.close()
                
                for p in self.players:
                        if( len(self.players[p].animations) >10):
                                self.players[p].animations = self.players[p].animations[1:]
                                      
        def readStateFromServer(self):

                client_db = shelve.open(CLIENTDATA)
                try:
                        self.actions =[]
                        for key in client_db:
                                self.actions.append(client_db[key]['string'].split('$'))
                        
                finally:
                        client_db.close()

        def TransmitStateUDP(self):
                for c in self.clients.itervalues():
                        sock = socket.socket( socket.AF_INET,  socket.SOCK_DGRAM ) # UDP
                        sock.sendto( MESSAGE, (c[0], c[1]) )

        def ReceiveStatesUDP(self):
                for c in self.clients.itervalues():
                        sock = socket.socket( socket.AF_INET,  socket.SOCK_DGRAM ) # UDP
                        sock.sendto( MESSAGE, (c[0], c[1]) )
                        
        def cSerialize(self): #deprecated
                s=pickle.dumps(self.players)+'$'+pickle.dumps(self.buildings)+'$'+\
                pickle.dumps(self.ResourcePool)+'$'+pickle.dumps(self.scores)+'$'+str(self.TimeLeft)+'$'+str(self.Tick)+'$'+str(self.GameOver)  
                
                #print len(s),s         
                return s
        
        def Serialize(self):
                s=''
                for p in self.players.itervalues():
                        s+=str(p.player_id)+'&'
                        s+=str(p.team)+'&'
                        s+=str(p.sides)+'&'
                        s+=str(p.resources)+'&'
                        s+=str(p.partialResources)+'&'
                        s+=str(p.targetPosition.x)+'^'+str(p.targetPosition.y)+'&'
                        for a in p.animations:
                                s+=str(a[0])+'#'+str(a[1])+'#'+str(a[2])+'^'
                        s+='&'
                        s+=str(p.action)+'@'
                s+='$'
                for b in self.buildings.itervalues():
                        s+=str(b.building_id)+'&'
                        s+=str(b.team)+'&'
                        s+=str(b.sides)+'&'
                        s+=str(b.resources)+'&'
                        s+=str(b.partialResources)+'&'
                        s+=str(b.position.x)+'^'+str(b.position.y)+'&'
                        for a in b.animations:
                                s+=str(a[0])+'#'+str(a[1])+'#'+str(a[2])+'^'
                        s+='@'
                s+='$'
                
                s+=str(self.scores[0])+'^'+str(self.scores[1])+'$'
                s+=str(self.TimeLeft)+'$'
                s+=str(self.GameOver)

                return s
コード例 #2
0
class Environment(LoopingThread): #in an MVC system , this would be a controller
    ''' The environment class contains the state of the game. The server has the master version, the clients have slave versions (updated through the network) '''
    ATTACK_RADIUS = 3
    SCAN_RADIUS = 3
    FPS=30
    

    def __init__(self,player_id,team,serverIP,serverPort):
                '''State: Players,Buildings, Time, Resourse Pool'''
                LoopingThread.__init__(self)               
		
		self.players 	= {}
		self.buildings 	= {}
		self.TimeLeft = 15*60 
		self.width = 80.0
		self.height = 48.0
		self.view =None
		self.GameOver =False
		self.playerID =player_id
		
		self.player = None
		self.action = 0
		self.attemptedAction = 0
		self.lastAction = 0
		self.ActionTimeout = 1
		
		self.team =team
		self.otherTeam = 2 if self.team==1 else  1 
		self.scores =[0,0]
		self.IsServer = False
		self.ResourcePool = ResourcePool()
		self.client = UDPClient(self)
		self.serverIP =serverIP
		self.serverPort = serverPort
                self.Tick = 0
                self.Position = (0,0)
                self.lastUpdate = 0
                self.controller = None


    def createPlayer(self, player_id,team):
                '''add a player to the given team'''
                player = Player()
                player.team = team

                playerId = id(player)
                player.player_id = player_id
               
                self.players[playerId] = player
        
                return player

    def createBuilding(self, team,pos):
                '''add a building to the given team'''
                building = Building()
                building.team = team
                building.position =pos
                bid = id(building)
                building.building_id = 0
                self.buildings[bid] = building
                
        
                return building
            
    def readGestures(self):
        self.controller._handleInput()
        if(self.player<>None):
            #print self.player.action
            if(self.player.action == Player.ATTACK): #ATTACK
                                    self.handleAttack()

            elif(self.player.action == Player.BUILD): #building
                                    self.handleBuild()

            elif(self.player.action == Player.UPGRADE): #building
                                    self.handleUpgrade()

            elif(self.player.action == Player.SCAN): #building
                                    self.handleScan()

            elif(self.player.action == Player.IDLE):
                                    self.handleIdle()



    def handleAttack(self):
                if(self.player.sides>=3):
                        self.player.performAttack(self.Tick)  
                       
    def handleBuild(self):
                ACTION = "BUILD"
                if((self.ResourcePool.getPosition()-self.player.getPosition()).length< self.ResourcePool.size):
                        ACTION ="MINE"
                else:
                        for b in self.buildings.itervalues():
                                
                                if(b.team == self.player.team and b.isPolyFactory() and b.resources == 5 and (b.getPosition()- player.getPosition()).length <b.size):
                                        ACTION ="MINE"
                                        break      
                if( ACTION =="MINE"):
                        self.player.performBuild(self.Tick)  
                        
                                         
                else:
                        if(self.player.resources>0):
                                BUILDING =None
                                for b in self.buildings.itervalues():
                                        if   (b.getPosition() - self.player.getPosition()).length < b.size:
                                                BUILDING =b
                                                break
                                

                                if BUILDING.team ==self.player.team:
                                        self.player.performBuild(self.Tick) 
        
    def handleUpgrade(self):
                allowedUpgradeLoc = False
                if((self.ResourcePool.getPosition()-self.player.getPosition()).length< self.ResourcePool.size):
                        allowedUpgradeLoc=True
                else:
                        for b in self.buildings.itervalues():
                                if(b.team == self.player.team and b.isPolyFactory() and b.resources == 5 and (b.getPosition()- self.player.getPosition()).length <b.size): 
                                        allowedUpgradeLoc=True
                                        break
                if(allowedUpgradeLoc):
                       self.player.upgrade(self.Tick) 

    def handleScan(self):
             self.player.scan(self.Tick)    

    def handleIdle(self):

             pass  
      
    def updateTime(self):
		self.Tick+= 1.0/Environment.FPS
		#if( self.TimeLeft<=0):
		#    self.GameOver =True
            
    def task(self):
                
		#self.deSerialize()
		self.readGestures()
		self.updateTime()
		self.updatePositions()
		self.makeRequest()
		self.view.paint(self.Tick )
                for event in pygame.event.get():
                        if event.type == pygame.QUIT:
                                self.Exit()
                        
    def Exit(self):
        self.shutdown()
        pygame.quit()

       
    def makeRequest(self):
        #print self.action
        
        self.client.MakeRequest(self.playerID,self.team,self.action,self.Position)
        
        self.action = 0
    
    def updatePositions(self):
            for playerId in self.players:
                     
                     if self.players[playerId].player_id <> self.playerID:
                         
                         self.players[playerId].updatePosition( 1.0/Environment.FPS)
                     
    def start(self):
		'''controls the environment by initiating the looping calls'''

		self.lastUpdate =time.time()
		self.view.start('client-'+str(self.playerID))
		self.client.start(self.serverIP,int(self.serverPort),self.playerID)
		
                #if os.path.exists(CLIENTLOCALDATA.split('.')[0]+str(self.playerID)+'.'+CLIENTLOCALDATA.split('.')[1]):		
                #    os.remove(CLIENTLOCALDATA.split('.')[0]+str(self.playerID)+'.'+CLIENTLOCALDATA.split('.')[1])

		self.setInterval(1.0/Environment.FPS)
		self.run()
		#self._renderCall = LoopingCall(self.Update) 
		#self._requestCall = LoopingCall(self.makeRequest) 
		#self._renderCall.start(1.0/Environment.FPS)	
		#self._requestCall.start(1.0/Environment.FPS)	


	#FUNCTIONS FOR NETWORKING
	
    def deSerialize(self,state):
       
        try:
                
            '''
                assume the following message structure
                players$buildings$resourcepool$scores$timeleft$gameover

                    players->player1@player2@..@playern
                        player1->id&Team&sides&resources&partialResources&pos_x^pos_y&anim1^anim2^anim3&action
            '''
            if(state<>None):
                
                t = state.split('$')
                
                if(len(t)>0):
                    
                    players =  t[0].split('@') #update players
                    
                    players.remove('')
                    for p in players:
                          
                        found =False
                        pkey = 0
                        player = p.split('&')

                        pId     = int(player[0])
                        pTeam   = int (player[1])
                        pSides  = int(player[2])
                        pResources  = int(player[3])
                        pPartialResources = int(player[4])
                        pPosition = Vector2D( (float(player[5].split('^')[0]),(float(player[5].split('^')[1]))))
                        AnimationList = player[6].split('^')
                        AnimationList.remove('')
                        pAnimations=[]
                        for a in AnimationList:
                            a = a.split('#')
                            pAnimations.append( (int(a[0]),bool(a[1]),float(a[2])))
                        pAction = int(player[7])
                        
                        for ep in self.players.itervalues():
                            if ep.player_id == pId:
                                found = True
                                pkey = id(ep)
                                break
                        if found:
                            
                            self.players[pkey].sides = pSides
                            self.players[pkey].resources = pResources
                            self.players[pkey].partialResources = pPartialResources
                            
                            
                            
                            if pId == self.playerID:
                                
                                self.players[pkey].position = Vector2D(self.Position)
                                
                                self.players[pkey].action = self.action
                            else:
                                self.players[pkey].animations.extend(pAnimations)
                                self.players[pkey].targetPosition = pPosition
                                self.players[pkey].action = pAction
                        else:
                            
                            newplayer = self.createPlayer(pId,pTeam)
                            if(pId == self.playerID):
                                self.player=newplayer
                            newplayer.targetPosition=pPosition
                            newplayer.sides = pSides
                            newplayer.resources = pResources
                            newplayer.partialResources = pPartialResources
                            newplayer.animations.extend(pAnimations)
                            newplayer.action = pAction

                    '''
                    assume the following message structure
                    players$buildings$resourcepool$scores$timeleft$gameover

                        buildings->buildings@buildings@..@buildings
                            buildings->id&Team&sides&resources&partialResources&pos_x^pos_y&anim1^anim2^anim3
                    '''
                 

                if(t[1]<>''):
                    
                    buildings  =  t[1].split('@')
                    
                    self.buildings.clear()
                    for b in buildings:
                        building = b.split('&')
                        bId = int(building[0])
                        bTeam = int(building[1])
                        bSides  = int(building[2])
                        bResources  = int(building[3])
                        bPartialResources = int(building[4])
                        AnimationList = building[6].split('^')
                        
                        AnimationList.remove('')
                        bAnimations=[]
                        for a in AnimationList:
                            a = a.split('#')
                            bAnimations.append( (int(a[0]),bool(a[1]),float(a[2])))
                            
                        bPosition = Vector2D( (float(building[5].split('^')[0]),(float(building[5].split('^')[1]))))

                        newbuilding = self.createBuilding(bTeam,bPosition)
                        newbuilding.building_id = bId
                        newbuilding.sides = bSides
                        newbuilding.resources = bResources
                        newbuilding.animations.extend(bAnimations)
                if(t[2]<>''):
                    self.scores =(int(t[2].split('^')[0]),int(t[2].split('^')[1]))
                if(t[3]<>''):
                    self.TimeLeft =int(t[3])
                if(t[4]<>''): 
                    self.GameOver = not bool(t[4])
                   
              
        except:
            print "Unexpected error:", sys.exc_info()[0]