Advertisement
billysback

Map generator (python, pygame)

Apr 30th, 2014
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.49 KB | None | 0 0
  1. import sys, pygame, math, random
  2.  
  3. from pygame.locals import *
  4. pygame.init()
  5.  
  6. random_seed = 238572983412674123
  7. random.seed(random_seed)
  8.  
  9. #people, houses
  10.  
  11.  
  12. hmap = []
  13. for i in range(100):
  14.     hmap.append(0)
  15.  
  16. br, bcr = [0, 42], [ [0, 0, 100], [0, 0, 255] ] #water colour range for height map
  17. sr, scr = [42, 45], [ [255, 204, 51], [255, 225, 80] ] #sand colour range for height map
  18. gr, gcr = [45, 55], [ [0, 240, 0], [0, 200, 0] ] #grass colour range for height map
  19. tr, tcr = [55, 64], [ [0, 160, 0], [0, 100, 0] ] #tree colour range for height map
  20. rr, rcr = [64, 100], [ [150,150,150], [255, 255, 255] ] #mountain/rock/snow colour range for height map
  21.  
  22. rs = [ [br, bcr], [sr, scr], [gr, gcr], [tr, tcr], [rr, rcr] ]
  23.  
  24. for i in range(100):
  25.     for j in range(len(rs)):
  26.         r, c = rs[j][0], rs[j][1]
  27.         if i >= r[0] and i < r[1]:
  28.             c1, c2 = c[0], c[1]
  29.             per = ( (i-r[0])/(r[1]-r[0]) )
  30.             rgb = [ c1[0] + ( (c2[0]-c1[0]) * per),
  31.                     c1[1] + ( (c2[1]-c1[1]) * per),
  32.                     c1[2] + ( (c2[2]-c1[2]) * per) ]
  33.             hmap[i] = rgb
  34.            
  35. width, height = 300, 300
  36. scale = 3
  37.  
  38. screen = pygame.display.set_mode((width*scale, height*scale))
  39.  
  40. mapImg = pygame.Surface((width*scale, height*scale))
  41. overlay = pygame.Surface((width*scale, height*scale)).convert_alpha()
  42. overlay.fill( (0,0,0,0) )
  43.  
  44. sky = pygame.Surface((width*scale, height*scale)).convert_alpha()
  45. sky.fill( (0,0,0,0) )
  46.  
  47. def drawScreen():
  48.     screen.blit(mapImg, (0, 0))
  49.     screen.blit(overlay, (0, 0))
  50.     screen.blit(sky, (0, 0))
  51.     pygame.display.flip()
  52.  
  53. def isValid(x, y):
  54.     if x >= 0 and x < width and y >= 0 and y < height:
  55.         return True
  56.     return False
  57.  
  58. bordersOn = True
  59. border = [0, 0, 0]
  60. borderDiff = 0
  61. def drawPixel(target, x, y, col, borders, lighting):
  62.     xf, yf = x*scale, y*scale
  63.     xt, yt = (x*scale)+scale, (y*scale)+scale
  64.    
  65.     for rx in range(xf, xt):
  66.         for ry in range(yf, yt):
  67.             tcol = col
  68.  
  69.             if bordersOn and (col[0] > 0 or col[1] > 0):
  70.                 if (rx == xf and borders[3]): #West (Left)
  71.                     tcol = border
  72.                 elif (rx == xt-1 and borders[1]): #East (Right)
  73.                     tcol = border
  74.                 elif (ry == yf and borders[0]): #North (Up)
  75.                     tcol = border
  76.                 elif (ry == yt-1 and borders[2]): #South (Down)
  77.                     tcol = border
  78.  
  79.             for i in range(len(tcol)):
  80.                 if tcol[i] > 255:
  81.                     tcol[i] = 255
  82.                 elif tcol[i] < 0:
  83.                     tcol[i] = 0
  84.                    
  85.             target.set_at((rx, ry), tcol)
  86.  
  87. def getBorders(x, y, rdiff):
  88.     borders = [False, False, False, False] #North, East, South, West
  89.     if isValid(x, y):
  90.         h = wmap[x][y][0]
  91.         col = hmap[h]
  92.  
  93.         for o in range(-1, 2, 2):
  94.             ps = [ [x+o, y], [x, y+o] ]
  95.             for i in range(len(ps)):
  96.                 p = ps[i]
  97.  
  98.                 if isValid(p[0], p[1]):
  99.                    
  100.                     col2 = hmap[wmap[p[0]][p[1]][0]]
  101.                     diff = math.fabs(col[0]-col2[0]) + math.fabs(col[1]-col2[1]) + math.fabs(col[2]-col2[2])
  102.                     if diff > rdiff and bordersOn:
  103.                         if p[0] < x: #West
  104.                             borders[3] = False
  105.                         elif p[0] > x: #East
  106.                             borders[1] = True
  107.                         elif p[1] < y: #North
  108.                             borders[0] = False
  109.                         elif p[1] > y: #South
  110.                             borders[2] = True
  111.     return borders
  112.  
  113. wmap = []
  114.  
  115. for x in range(width):
  116.     tab = []
  117.     for y in range(height):
  118.         h = random.randint(0,99)
  119.        
  120.         tab.append([h, 0])
  121.     wmap.append(tab)
  122.  
  123. def getDist(x1, y1, x2, y2):
  124.     return math.sqrt( ((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)) )
  125.  
  126. smooth = 3
  127. sharp = 1
  128. def smoothmapImg():
  129.     for x in range(width*scale):
  130.         for y in range(height*scale):
  131.             col = mapImg.get_at((x, y))
  132.             col = [col[0]*sharp, col[1]*sharp, col[2]*sharp]
  133.             n = sharp
  134.             for ox in range(-smooth, smooth+1):
  135.                 for oy in range(-smooth, smooth+1):
  136.                     if (x+ox) >= 0 and (x+ox) < width*scale and (y+oy) >= 0 and (y+oy) < height*scale:
  137.                         tempc = mapImg.get_at((x+ox, y+oy))
  138.                         col = [col[0] + tempc[0], col[1]+tempc[1], col[2]+tempc[2] ]
  139.                         n = n + 1
  140.             col[0] = math.floor(col[0]/n)
  141.             col[1] = math.floor(col[1]/n)
  142.             col[2] = math.floor(col[2]/n)
  143.             mapImg.set_at((x, y), col)
  144.                
  145.  
  146. def drawWorld():
  147.     for x in range(width):
  148.         for y in range(height):
  149.             h = wmap[x][y][0]
  150.             col = hmap[h]
  151.  
  152.             lighting = wmap[x][y][1]
  153.            
  154.             drawPixel(mapImg, x, y, col, getBorders(x, y, borderDiff), lighting)
  155.     drawScreen()
  156.  
  157.  
  158. def addHotspot(x, y, h, intensity, dist):
  159.     for ox in range(-dist, dist+1):
  160.         for oy in range(-dist, dist+1):
  161.             if (ox*ox)+(oy*oy) <= dist*dist and isValid(x+ox, y+oy):
  162.                 per = 100- ((( (ox*ox) + (oy*oy) )/(dist*dist))*100)
  163.                 i = math.ceil( (intensity/100)*per )
  164.                 wmap[x+ox][y+oy].append([h, i])
  165.  
  166. drange = [30, 70]
  167. def generateHotspot(x, y):
  168.     pos = [x, y]
  169.     h = random.randint(0, 99)
  170.     intensity = random.randint(6, 13)
  171.     dist = random.randint(drange[0], drange[1])
  172.     addHotspot(pos[0], pos[1], h, intensity, dist)
  173.  
  174. def genHotspots():
  175.     avgdrange = (drange[0]+drange[1])/2
  176.     hotspot_amt = math.ceil( (width*height)/(math.pi*avgdrange*avgdrange) )
  177.     hotroot = math.ceil(math.sqrt(hotspot_amt))
  178.     wpart, hpart = width/hotroot, height/hotroot
  179.     hotroot = hotroot*2
  180.     for x in range(0, hotroot):
  181.        
  182.         for y in range(0, hotroot):
  183.             rx = ( (x*wpart) + wpart )/2
  184.             ry = ( (y*hpart) + hpart)/2
  185.             offset = [random.randint(0, math.floor(wpart))-(wpart/2), random.randint(0, math.floor(hpart))-(hpart/2)]
  186.             generateHotspot(math.floor(rx+offset[0]), math.floor(ry+offset[1]))
  187.            
  188.     print(hotspot_amt, ", ", hotroot)
  189.  
  190.  
  191. def getAverageHeight(x, y, sens, hotspots, circular):
  192.     nlist = []
  193.     total = 0
  194.     n = 0
  195.     if isValid(x, y) and hotspots == True:
  196.         if len(wmap[x][y]) > 2:
  197.             for i in range(2, len(wmap[x][y])):
  198.                 hotspot = wmap[x][y][i]
  199.                 total = total + (hotspot[0]*hotspot[1])
  200.                 n = n + hotspot[1]
  201.     for ox in range(-sens, sens+1):
  202.         for oy in range(-sens, sens+1):
  203.             if isValid(x+ox, y+oy):
  204.                 if circular:
  205.                     if getDist(x, y, x+ox, y+oy) <= sens:
  206.                         total = total + wmap[x+ox][y+oy][0]
  207.                         n = n + 1
  208.                 else:
  209.                     total = total + wmap[x+ox][y+oy][0]
  210.                     n = n + 1
  211.     h = math.floor(total/n)
  212.     if h > 99:
  213.         h = 99
  214.     return h
  215.  
  216.    
  217.  
  218. def smoothWorld(sens, hotspots):
  219.     todo = []
  220.     for x in range(width):
  221.         for y in range(height):
  222.             wmap[x][y][0] = getAverageHeight(x, y, sens, hotspots, False)
  223.  
  224.  
  225. def getTotalAverageHeight():
  226.     total = 0
  227.     n = 0
  228.     for x in range(width):
  229.         for y in range(height):
  230.             total = total + wmap[x][y][0]
  231.             n = n + 1
  232.    
  233.     return math.floor(total/n)
  234.  
  235. def createWorld():
  236.     genHotspots()
  237.     drawWorld()
  238.  
  239.     print("Smoothing world, pass 1")
  240.     smoothWorld(2, True)
  241.     drawWorld()
  242.  
  243.     print("Smoothing world, pass 2")
  244.     smoothWorld(3, False)
  245.     drawWorld()
  246.  
  247.     print("Smoothing world, pass 3")
  248.     smoothWorld(3, True)
  249.     drawWorld()
  250.  
  251.     print("Smoothing world, pass 4")
  252.     smoothWorld(3, False)
  253.     drawWorld()
  254.  
  255. createWorld()
  256.  
  257. print("Done!")
  258. print("Finding village locations...")
  259.  
  260. villageHouses = 7
  261. villageSize = 40
  262. houseSize = 2
  263. def findVillageLocations(size):
  264.     locations = []
  265.     for x in range(width):
  266.         for y in range(height):
  267.             h = wmap[x][y][0]
  268.             if h >= gr[0] and h < gr[1]:
  269.                 ah = getAverageHeight(x, y, size, False, True)
  270.                 if ah >= h-2 and ah <= h+2:
  271.                     canCreate = True
  272.                     for i in range(len(locations)):
  273.                         if getDist(locations[i][0], locations[i][1], x, y) < size*2:
  274.                             canCreate = False
  275.                     if canCreate:
  276.                         locations.append([x, y])
  277.     return locations
  278.  
  279. class House:
  280.     def __init__(self, village, x, y, size):
  281.         self.village = village
  282.         self.x = x
  283.         self.y = y
  284.         self.size = size
  285.  
  286.     def draw(self):
  287.         for ox in range(-self.size, self.size+1):
  288.             for oy in range(-self.size, self.size+1):
  289.                 if getDist(self.x, self.y, self.x+ox, self.y+oy) <= self.size:
  290.                     drawPixel(overlay, self.x+ox, self.y+oy, [140, 123, 55, 255], [True, True, False, False], 0)
  291.  
  292. class Village:
  293.     def __init__(self, loc, size, hamt, hsize):
  294.         houses = []
  295.         n = 0
  296.         while len(houses) < hamt and n < 50:
  297.             pos = [random.randint(loc[0]-size, loc[0]+size), random.randint(loc[1]-size, loc[1]+size)]
  298.             dist = getDist(loc[0], loc[1], pos[0], pos[1])
  299.             if dist <= size and isValid(pos[0], pos[1]):
  300.                 canCreate = True
  301.                 for i in range(len(houses)):
  302.                     house = houses[i]
  303.                     if getDist(pos[0], pos[1], house.x, house.y) < hsize*2:
  304.                         canCreate = False
  305.                 ph = wmap[pos[0]][pos[1]][0]
  306.                 if canCreate and ph >= gr[0] and ph < gr[1]:
  307.                     houses.append(House(self, pos[0], pos[1], hsize))
  308.             n = n + 1
  309.         self.houses = houses
  310.         self.x = loc[0]
  311.         self.y = loc[1]
  312.         self.size = size
  313.  
  314.     def draw(self):
  315.         for i in range(len(self.houses)):
  316.             self.houses[i].draw()
  317.                                  
  318.  
  319.  
  320. #locs = findVillageLocations(villageSize)
  321.  
  322. #print("Creating villages... (",len(locs),")")
  323. #villages = []
  324. #for i in range(len(locs)):
  325. #    v = Village(locs[i], villageSize, villageHouses, houseSize)
  326. #    v.draw()
  327. #    villages.append(v)
  328.  
  329. print("Done!")
  330. drawScreen()
  331.  
  332. while 1:
  333.     for event in pygame.event.get():
  334.         if event.type == QUIT:
  335.             sys.exit()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement