Want more features on Pastebin? Sign Up, it's FREE!
Guest

Crowd simulation in Python

By: a guest on Jul 25th, 2010  |  syntax: Python  |  size: 9.49 KB  |  views: 685  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. import pygame, sys,os
  2. from pygame.locals import *
  3. from random import random, uniform, randrange
  4. from math import sqrt, e, pi, cos, sin, atan
  5. #--------------------------------------------------------------------------
  6. Anagent class
  7. class anagent:
  8.     def __init__(self, x, y):
  9.        
  10.         #position
  11.         self.x = x
  12.         self.y = y
  13.        
  14.         self.tx = x
  15.         self.ty = y
  16.        
  17.         self.dx = 0
  18.         self.dy = 0
  19.         self.v = uniform(0.5, 2.5) #speed
  20.         self.idle = False
  21.        
  22.     def setTarget(self,x,y):
  23.         self.tx = x
  24.         self.ty = y
  25.  
  26. #--------------------------------------------------------------------------
  27. #Basic Setup
  28. pygame.init()
  29. w=400
  30. h=400
  31. window = pygame.display.set_mode((w, h))
  32. pygame.display.set_caption('Crowd Sim')
  33. screen = pygame.display.get_surface()
  34. layer1 = pygame.Surface((w,h))
  35. layer1.fill((0,0,0))
  36. layer1.set_colorkey((0,0,0))
  37.  
  38. #POT_EXTEND = 30         #how much the potential extends forwards from a person
  39. #POT_DECAY = 0.01        #how fast the potential function decays per agent
  40. POT_EXTEND = 22
  41. POT_DECAY = 0.027
  42. POT_STRENGTH = 350         #how much the agents are affected by the potential field
  43.  
  44. POT_DRAWFIELD = False    #draw the potential field?
  45.  
  46. iter = 0
  47.  
  48. PPL = 20
  49. agent = []
  50. footman = (pygame.image.load("C:/footman_1.gif"),pygame.image.load("C:/footman_2.gif"),pygame.image.load("C:/footman_3.gif"))
  51. ttt = 0
  52. #--------------------------------------------------------------------------
  53. #Defs
  54.  
  55. #handler for events
  56. def input(events):
  57.     global POT_EXTEND
  58.     global POT_DECAY
  59.     global POT_STRENGTH
  60.     global POT_DRAWFIELD
  61.     global agent
  62.     global layer1
  63.     for event in events:
  64.         if event.type == QUIT:
  65.             sys.exit(0)
  66.         elif event.type == KEYDOWN:
  67.             if event.key == K_ESCAPE:
  68.                 sys.exit(0)
  69.             elif event.key == K_i:
  70.                 POT_EXTEND += 1
  71.                 print "POT_EXTEND = " + `POT_EXTEND`
  72.             elif event.key == K_u:
  73.                 POT_EXTEND -= 1
  74.                 print "POT_EXTEND = " + `POT_EXTEND`
  75.             elif event.key == K_j:
  76.                 POT_DECAY -= 0.001
  77.                 print "POT_DECAY = " + `POT_DECAY`
  78.             elif event.key == K_k:
  79.                 POT_DECAY += 0.001
  80.                 print "POT_DECAY = " + `POT_DECAY`
  81.             elif event.key == K_m:
  82.                 POT_STRENGTH += 20
  83.                 print "POT_STRENGTH = " + `POT_STRENGTH`
  84.             elif event.key == K_n:
  85.                 POT_STRENGTH -= 20
  86.                 print "POT_STRENGTH = " + `POT_STRENGTH`
  87.             elif event.key == K_f:
  88.                 POT_DRAWFIELD = not POT_DRAWFIELD
  89.                 print "draw field toggled"
  90.             elif event.key == K_r:
  91.                 agent = []
  92.                 resetAgents()
  93.                 layer1.fill((0,0,0))
  94.                 print "Agents reset"
  95. #return total danger due to all agents from position x,y
  96. def totalDangerAt(x, y):
  97.     global agent
  98.     danger = 0
  99.     for a in agent:
  100.        danger += dangerDue(x,y,a)
  101.     return danger
  102.  
  103. #return danger to an agent a from position x,y
  104. def dangerDue(x, y, a):
  105.     global POT_EXTEND
  106.     global POT_DECAY
  107.     px2 = a.x + POT_EXTEND*a.dx
  108.     py2 = a.y + POT_EXTEND*a.dy
  109.     d1 = sqrt((a.x - x)**2 + (a.y - y)**2)
  110.     d2 = sqrt((px2 - x)**2 + (py2 - y)**2)
  111.     danger = e**(-POT_DECAY*(d1 + d2))
  112.     return danger
  113.  
  114.  
  115. #return the gradient of danger at position x,y due to agent a
  116. def gradDangerDue(x,y,a):
  117.     global POT_EXTEND
  118.     global POT_DECAY
  119.     px2 = a.x + POT_EXTEND*a.dx
  120.     py2 = a.y + POT_EXTEND*a.dy
  121.     d1 = sqrt((a.x - x)**2 + (a.y - y)**2)
  122.     d2 = sqrt((px2 - x)**2 + (py2 - y)**2)
  123.     danger = e**(-POT_DECAY*(d1 + d2))
  124.    
  125.     multiplierx = -POT_DECAY*(x - a.x)/(2*d1) - POT_DECAY*(x - px2)/(2*d2)
  126.     multipliery = -POT_DECAY*(y - a.y)/(2*d1) - POT_DECAY*(y - py2)/(2*d2)
  127.    
  128.     return (danger*multiplierx, danger*multipliery)
  129.  
  130. #return the total gradient of danger at position x,y due to all agents
  131. def gradDangerAt(x, y):
  132.     global agent
  133.     totx = 0
  134.     toty = 0
  135.     for a in agent:
  136.         if not (a.x == x and a.y == y):
  137.             res = gradDangerDue(x, y, a)
  138.             totx += res[0]
  139.             toty += res[1]
  140.     return (totx, toty)
  141.  
  142. #generate agents
  143. def resetAgents():
  144.     global agent, PPL, w, h
  145.     for i in range (0, PPL):
  146.         if i < PPL/2: #left and right walkers
  147.             newagent = anagent(w/10 + uniform(-100,100),random()*h/2 + h/4)
  148.             newagent.setTarget(w +10,newagent.y)
  149.             #newagent.setTarget(w/2,h/2)
  150.         else:
  151.             newagent = anagent(w - w/10 + uniform(-100,100),random()*h/2 + h/4)
  152.             newagent.setTarget(-10,newagent.y)
  153.             #newagent.setTarget(w/2,h/2)
  154.        
  155.         newagent.idle = False
  156.        
  157.         agent.append(newagent)
  158.  
  159. #at corners
  160. def resetAgents2():
  161.     global agent, PPL, w, h
  162.     n = PPL/4
  163.     for i in range(n):
  164.         newagent = anagent(uniform(0, 100),uniform(0, 100))
  165.         newagent.setTarget(w,h)
  166.         newagent.idle = False
  167.         agent.append(newagent)
  168.     for i in range(n):
  169.         newagent = anagent(uniform(w-100, w),uniform(0, 100))
  170.         newagent.setTarget(0,h)
  171.         newagent.idle = False
  172.         agent.append(newagent)
  173.     for i in range(n):
  174.         newagent = anagent(uniform(0, 100),uniform(h-100, h))
  175.         newagent.setTarget(w,0)
  176.         newagent.idle = False
  177.         agent.append(newagent)
  178.     for i in range(n):
  179.         newagent = anagent(uniform(w-100,w),uniform(h-100, h))
  180.         newagent.setTarget(0,0)
  181.         newagent.idle = False
  182.         agent.append(newagent)
  183.        
  184. #in circle
  185. def resetAgents3():
  186.     global agent, PPL, w, h
  187.     r = min(w, h)*0.9/2
  188.     incr = 2*pi/PPL
  189.     for i in range(PPL):
  190.         newagent = anagent(w/2 + r*cos(incr*i), h/2 + r*sin(incr*i))
  191.         newagent.setTarget(w/2 + r*cos(incr*i + pi), h/2 + r*sin(incr*i + pi))
  192.         agent.append(newagent)
  193.  
  194. #from all over the place to middle
  195. def resetAgents4():
  196.     global agent, PPL, w, h
  197.     for i in range(PPL):
  198.         newagent = anagent(uniform(-w, 2*w), uniform(-h, 2*h))
  199.         newagent.setTarget(w/2, h/2)
  200.         agent.append(newagent)
  201.        
  202. #--------------------------------------------------------------------------
  203. resetAgents3()
  204. #MAIN LOOP
  205. while True:
  206.    input(pygame.event.get())
  207.    pygame.time.delay(30)
  208.    
  209.    screen.fill((0,0,50))
  210.    
  211.    if POT_DRAWFIELD:
  212.        #calculate the danger field
  213.        for x in range(0,w,10):
  214.            for y in range(0,h,10):
  215.                
  216.                danger = 2*POT_STRENGTH*totalDangerAt(x,y)
  217.                
  218.                #print danger
  219.                dng = 0
  220.                if danger > 255:
  221.                    dng = danger - 255
  222.                    danger = 255
  223.                
  224.                if dng > 255:
  225.                    dng = 255
  226.    
  227.                pygame.draw.circle(screen, (danger,dng,0), (x,y), 7)
  228.            
  229.    #update agents
  230.    for a in agent:
  231.        dx = 0
  232.        dy = 0
  233.            
  234.        if not a.idle:
  235.            d = sqrt((a.tx - a.x)**2 + (a.ty - a.y)**2)
  236.                
  237.            if d > a.v:
  238.                dx = a.v*(a.tx - a.x)/d
  239.                dy = a.v*(a.ty - a.y)/d
  240.            else:
  241.                #a.idle = True
  242.                a.setTarget(random()*w, random()*h)
  243.                
  244.                #if random() < 0.5:
  245.                #    a.x = -30
  246.                #    a.y = random()*h/2 + h/4
  247.                #    a.setTarget(w +10,a.y)
  248.                #else:
  249.                #    a.x = w + 30
  250.                #    a.y = random()*h/2 + h/4
  251.                #    a.setTarget(-10,a.y)          
  252.            
  253.        #now calculate force due to poptential at this point.
  254.        #we do this by summing up all the gradients at this point
  255.        #of all functions that each agent generates.
  256.        gradx,grady = gradDangerAt(a.x,a.y)
  257.        gradx = -gradx*POT_STRENGTH
  258.        grady = -grady*POT_STRENGTH
  259.        #print gradx,grady
  260.        dx += gradx
  261.        dy += grady
  262.        #pygame.draw.circle(screen, (0, 255, 0) , (a.x + a.dx, a.y + a.dy), 10, 5)
  263.        #pygame.draw.circle(screen, (255, 255, 255) , (a.tx, a.ty), 5, 1)
  264.        
  265.        pygame.draw.line(screen, (255,255,0), (a.x,a.y), (a.tx, a.ty))
  266.        #pygame.draw.line(screen, (0,0,255), (a.x,a.y), (a.x+30*gradx, a.y+30*grady))
  267.            
  268.        #normalize velocity to agents speed
  269.        lengthv = sqrt(dx*dx + dy*dy)
  270.        dx = a.v*dx/lengthv
  271.        dy = a.v*dy/lengthv
  272.        
  273.        pygame.draw.line(layer1, (50,50,0), (a.x,a.y), (a.x + a.dx, a.y + a.dy))
  274.        a.x += dx
  275.        a.y += dy
  276.        a.dx = dx
  277.        a.dy = dy
  278.        
  279.        #draw agent and his direction of motion
  280.        #pygame.draw.circle(screen, (255, 255, 0) , (a.x, a.y), 17, 1)
  281.        #ang = atan(a.dy/a.dx)
  282.        #if a.dx < 0:
  283.        #    ang += pi
  284.        
  285.        #nf =pygame.transform.rotate(footman[int(ttt)],90 - ang*180/pi)
  286.        #ttt+=0.025
  287.        #if ttt > 3:
  288.        #    ttt = 0
  289.        #screen.blit(nf, (a.x - nf.get_rect().width/2, a.y - nf.get_rect().height/2))
  290.        
  291.        pygame.draw.circle(screen, (0, 255, 255) , (a.x, a.y), 10, 1)
  292.        pygame.draw.line(screen, (255,255,255), (a.x,a.y), (a.x+6*a.dx, a.y+6*a.dy))
  293.        
  294.        
  295.    #pygame.draw.line(screen, (255,255,255), (px,py), pygame.mouse.get_pos())
  296.    #pygame.draw.circle(screen, (0, 255, 0) , (px, py), 10)
  297.    #screen.blit(layer1, (0,0))
  298.    
  299.    pygame.display.flip()
  300.    #pygame.image.save(screen, "C:\pics\p" + `iter` + ".bmp")
  301.    #iter += 1
clone this paste RAW Paste Data