import sys, pygame, math, random from pygame.locals import * pygame.init() #random_seed = 238572983412674123 #random.seed(random_seed) #people, houses hmap = [] for i in range(100): hmap.append(0) br, bcr = [0, 42], [ [0, 0, 100], [0, 0, 255] ] #water colour range for height map sr, scr = [42, 45], [ [255, 204, 51], [255, 225, 80] ] #sand colour range for height map gr, gcr = [45, 55], [ [0, 240, 0], [0, 200, 0] ] #grass colour range for height map tr, tcr = [55, 64], [ [0, 160, 0], [0, 100, 0] ] #tree colour range for height map rr, rcr = [64, 100], [ [150,150,150], [255, 255, 255] ] #mountain/rock/snow colour range for height map rs = [ [br, bcr], [sr, scr], [gr, gcr], [tr, tcr], [rr, rcr] ] for i in range(100): for j in range(len(rs)): r, c = rs[j][0], rs[j][1] if i >= r[0] and i < r[1]: c1, c2 = c[0], c[1] per = ( (i-r[0])/(r[1]-r[0]) ) rgb = [ c1[0] + ( (c2[0]-c1[0]) * per), c1[1] + ( (c2[1]-c1[1]) * per), c1[2] + ( (c2[2]-c1[2]) * per) ] hmap[i] = rgb width, height = 300, 300 scale = 3 maps = [1, 1] dimensions = (width*scale*maps[0], height*scale*maps[1]) screen = pygame.display.set_mode(dimensions) mapImg = pygame.Surface(dimensions) overlay = pygame.Surface(dimensions).convert_alpha() overlay.fill( (0,0,0,0) ) sky = pygame.Surface((width*scale, height*scale)).convert_alpha() sky.fill( (0,0,0,0) ) def drawScreen(): screen.blit(mapImg, (0, 0)) screen.blit(overlay, (0, 0)) screen.blit(sky, (0, 0)) pygame.display.flip() def isValid(x, y): if x >= 0 and x < width*maps[0] and y >= 0 and y < height*maps[1]: return True return False bordersOn = True border = [0, 0, 0] borderDiff = 0 def drawPixel(target, x, y, col, borders, lighting): xf, yf = x*scale, y*scale xt, yt = (x*scale)+scale, (y*scale)+scale for rx in range(xf, xt): for ry in range(yf, yt): tcol = col border = [col[0]-100, col[1]-100, col[2]-100] if bordersOn and (col[0] > 0 or col[1] > 0): if (rx == xf and borders[3]): #West (Left) tcol = border elif (rx == xt-1 and borders[1]): #East (Right) tcol = border elif (ry == yf and borders[0]): #North (Up) tcol = border elif (ry == yt-1 and borders[2]): #South (Down) tcol = border for i in range(len(tcol)): if tcol[i] > 255: tcol[i] = 255 elif tcol[i] < 0: tcol[i] = 0 target.set_at((rx, ry), tcol) def getBorders(x, y, rdiff): borders = [False, False, False, False] #North, East, South, West if isValid(x, y): h = wmap[x][y][0] col = hmap[h] for o in range(-1, 2, 2): ps = [ [x+o, y], [x, y+o] ] for i in range(len(ps)): p = ps[i] if isValid(p[0], p[1]): col2 = hmap[wmap[p[0]][p[1]][0]] diff = math.fabs(col[0]-col2[0]) + math.fabs(col[1]-col2[1]) + math.fabs(col[2]-col2[2]) if diff > rdiff and bordersOn: if p[0] < x: #West borders[3] = False elif p[0] > x: #East borders[1] = True elif p[1] < y: #North borders[0] = False elif p[1] > y: #South borders[2] = True return borders wmap = [] for x in range(width*maps[0]): tab = [] for y in range(height*maps[1]): h = random.randint(0,99) tab.append([h, 0]) wmap.append(tab) def getDist(x1, y1, x2, y2): return math.sqrt( ((x1-x2)*(x1-x2)) + ((y1-y2)*(y1-y2)) ) smooth = 3 sharp = 1 def smoothmapImg(): for x in range(width*scale): for y in range(height*scale): col = mapImg.get_at((x, y)) col = [col[0]*sharp, col[1]*sharp, col[2]*sharp] n = sharp for ox in range(-smooth, smooth+1): for oy in range(-smooth, smooth+1): if (x+ox) >= 0 and (x+ox) < width*scale and (y+oy) >= 0 and (y+oy) < height*scale: tempc = mapImg.get_at((x+ox, y+oy)) col = [col[0] + tempc[0], col[1]+tempc[1], col[2]+tempc[2] ] n = n + 1 col[0] = math.floor(col[0]/n) col[1] = math.floor(col[1]/n) col[2] = math.floor(col[2]/n) mapImg.set_at((x, y), col) def drawWorld(surface, offsetx, offsety): for x in range(width*maps[0]): for y in range(height*maps[1]): h = wmap[x][y][0] col = hmap[h] lighting = wmap[x][y][1] drawPixel(surface, x, y, col, getBorders(x, y, borderDiff), lighting) drawScreen() def drawArea(surface, fpos, tpos): for x in range(fpos[0], tpos[0]+1): for y in range(fpos[1], tpos[1]+1): h = wmap[x][y][0] col = hmap[h] lighting = wmap[x][y][1] drawPixel(surface, x, y, col, getBorders(x, y, borderDiff), lighting) drawScreen() def addHotspot(x, y, h, intensity, dist): for ox in range(-dist, dist+1): for oy in range(-dist, dist+1): if (ox*ox)+(oy*oy) <= dist*dist and isValid(x+ox, y+oy): per = 100- ((( (ox*ox) + (oy*oy) )/(dist*dist))*100) i = math.ceil( (intensity/100)*per ) wmap[x+ox][y+oy].append([h, i]) drange = [30, 70] def generateHotspot(x, y): #print("Hotspot position: ",x,",",y) pos = [x, y] h = random.randint(0, 99) intensity = random.randint(6, 13) dist = random.randint(drange[0], drange[1]) addHotspot(pos[0], pos[1], h, intensity, dist) def genHotspots(offsetx, offsety): avgdrange = (drange[0]+drange[1])/2 hotspot_amt = math.ceil( (width*height)/(math.pi*avgdrange*avgdrange) ) hotroot = math.ceil(math.sqrt(hotspot_amt)) wpart, hpart = width/hotroot, height/hotroot hotroot = hotroot*2 for x in range(0, hotroot): for y in range(0, hotroot): rx = ( (x*wpart) + wpart )/2 ry = ( (y*hpart) + hpart)/2 offset = [random.randint(0, math.floor(wpart))-(wpart/2), random.randint(0, math.floor(hpart))-(hpart/2)] generateHotspot(math.floor(rx+offset[0])+offsetx, math.floor(ry+offset[1])+offsety) print(hotspot_amt, ", ", hotroot) def getAverageHeight(x, y, sens, hotspots, circular): nlist = [] total = 0 n = 0 if isValid(x, y) and hotspots == True: if len(wmap[x][y]) > 2: for i in range(2, len(wmap[x][y])): hotspot = wmap[x][y][i] total = total + (hotspot[0]*hotspot[1]) n = n + hotspot[1] for ox in range(-sens, sens+1): for oy in range(-sens, sens+1): if isValid(x+ox, y+oy): if circular: if getDist(x, y, x+ox, y+oy) <= sens: total = total + wmap[x+ox][y+oy][0] n = n + 1 else: total = total + wmap[x+ox][y+oy][0] n = n + 1 h = 0 if n != 0: h = math.floor(total/n) if h > 99: h = 99 return h def smoothWorld(offset, amt, sens, hotspots): todo = [] for x in range(width*amt[0]): for y in range(height*amt[1]): wmap[x+offset[0]][y+offset[1]][0] = getAverageHeight(x+offset[0], y+offset[1], sens, hotspots, False) def smoothArea(offset, fpos, tpos, sens, hotspots, circ): for x in range(fpos[0], tpos[0]+1): for y in range(fpos[1], tpos[1]+1): if isValid(x, y): wmap[x+offset[0]][y+offset[1]][0] = getAverageHeight(x+offset[0], y+offset[1], sens, hotspots, circ) def getTotalAverageHeight(): total = 0 n = 0 for x in range(width): for y in range(height): total = total + wmap[x][y][0] n = n + 1 return math.floor(total/n) def createWorld(surface, offsetx, offsety): genHotspots(offsetx, offsety) #drawWorld(surface, offsetx, offsety) print("Smoothing world, pass 1") smoothWorld([offsetx, offsety], [1,1], 2, True) #drawWorld(surface, offsetx, offsety) print("Smoothing world, pass 2") smoothWorld([offsetx, offsety], [1,1], 2, False) #drawWorld(surface, offsetx, offsety) print("Smoothing world, pass 3") smoothWorld([offsetx, offsety], [1,1], 3, True) #drawWorld(surface, offsetx, offsety) print("Smoothing world, pass 4") smoothWorld([offsetx, offsety], [1,1], 4, False) #drawWorld(surface, offsetx, offsety) createWorld(mapImg, 0, 0) drawWorld(mapImg, 0, 0) #createWorld(mapImg, width, 0) #createWorld(mapImg, width, height) #createWorld(mapImg, 0, height) def joinWorlds(): print("Smoothing all maps, pass 1") smoothWorld([0,0], maps, 4, True) drawWorld(mapImg, 0, 0) print("Smoothing all maps, pass 2") smoothWorld([0,0], maps, 3, False) drawWorld(mapImg, 0, 0) #joinWorlds() print("Done!") print("Finding village locations...") villageHouses = 7 villageSize = 40 houseSize = 2 def findVillageLocations(size): locations = [] for x in range(width): for y in range(height): h = wmap[x][y][0] if h >= gr[0] and h < gr[1]: ah = getAverageHeight(x, y, size, False, True) if ah >= h-2 and ah <= h+2: canCreate = True for i in range(len(locations)): if getDist(locations[i][0], locations[i][1], x, y) < size*2: canCreate = False if canCreate: locations.append([x, y]) return locations class House: def __init__(self, village, x, y, size): self.village = village self.x = x self.y = y self.size = size def draw(self): for ox in range(-self.size, self.size+1): for oy in range(-self.size, self.size+1): if getDist(self.x, self.y, self.x+ox, self.y+oy) <= self.size: drawPixel(overlay, self.x+ox, self.y+oy, [140, 123, 55, 255], [True, True, False, False], 0) class Village: def __init__(self, loc, size, hamt, hsize): houses = [] n = 0 while len(houses) < hamt and n < 50: pos = [random.randint(loc[0]-size, loc[0]+size), random.randint(loc[1]-size, loc[1]+size)] dist = getDist(loc[0], loc[1], pos[0], pos[1]) if dist <= size and isValid(pos[0], pos[1]): canCreate = True for i in range(len(houses)): house = houses[i] if getDist(pos[0], pos[1], house.x, house.y) < hsize*2: canCreate = False ph = wmap[pos[0]][pos[1]][0] if canCreate and ph >= gr[0] and ph < gr[1]: houses.append(House(self, pos[0], pos[1], hsize)) n = n + 1 self.houses = houses self.x = loc[0] self.y = loc[1] self.size = size def draw(self): for i in range(len(self.houses)): self.houses[i].draw() #locs = findVillageLocations(villageSize) #print("Creating villages... (",len(locs),")") #villages = [] #for i in range(len(locs)): # v = Village(locs[i], villageSize, villageHouses, houseSize) # v.draw() # villages.append(v) print("Done!") drawScreen() curSens = 2 def getTilePosition(pos): return [math.floor(pos[0]/scale), math.floor(pos[1]/scale)] def raiseArea(amt, fpos, tpos, circ): centre = [(fpos[0]+tpos[0])/2, (fpos[1]+tpos[1])/2] for x in range(fpos[0], tpos[0]+1): for y in range(fpos[1], tpos[1]+1): if isValid(x, y): if (circ != 0 and getDist(x, y, centre[0], centre[1]) <= circ) or (circ == 0): wmap[x][y][0] = wmap[x][y][0] + amt if wmap[x][y][0] > 99: wmap[x][y][0] = 99 if wmap[x][y][0] < 0: wmap[x][y][0] = 0 mouseMode = 0 # 0 = smooth # 1 = raise # 2 = lower # 3 = hotspot_add # 4 = hotspot_remove mouseHotspots = False mouseCirc = True mouseArea = 2 mouseHeight = 49 mouseIntensity = 7 scrollMode = 0 # 0 = brush size # 1 = sensitivity # 2 = height # 3 = intensity mticks = pygame.time.get_ticks() kticks = pygame.time.get_ticks() while 1: for event in pygame.event.get(): if event.type == QUIT: sys.exit() if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 4: #scroll up if scrollMode == 0: mouseArea = mouseArea + 1 print("Brush size: ", mouseArea) elif scrollMode == 1: curSens = curSens + 1 print("Cursor sensitivity: ", curSens) elif scrollMode == 2: mouseHeight = mouseHeight + 1 print("Mouse height (hotspot): ", mouseHeight) elif scrollMode == 3: mouseIntensity = mouseIntensity + 1 print("Mouse intensity (hotspot): ", mouseIntensity) elif event.button == 5: #scroll down if scrollMode == 0: mouseArea = mouseArea - 1 if mouseArea < 0: mouseArea = 0 print("Brush size: ", mouseArea) elif scrollMode == 1: curSens = curSens - 1 if curSens < 0: curSens = 0 print("Cursor sensitivity: ", curSens) elif scrollMode == 2: mouseHeight = mouseHeight - 1 if mouseHeight < 0: mouseHeight = 0 print("Mouse height (hotspot): ", mouseHeight) elif scrollMode == 3: mouseIntensity = mouseIntensity - 1 if mouseIntensity < 0: mouseIntensity = 0 print("Mouse intensity (hotspot): ", mouseIntensity) if pygame.time.get_ticks() - kticks >= 100: keys = pygame.key.get_pressed() if keys[pygame.K_1]: mouseMode = 0 print("Mouse set to smooth") elif keys[pygame.K_2]: mouseMode = 1 print("Mouse set to raise") elif keys[pygame.K_3]: mouseMose = 2 print("Mouse set to lower") elif keys[pygame.K_4]: mouseMode = 3 print("Mouse mode set to hotspot! (one use)") if keys[pygame.K_q]: mouseHotspots = (mouseHotspots == False) print("Smoothing hotspots set to ", str(mouseHotspots)) if keys[pygame.K_w]: mouseCirc = (mouseCirc == False) print("Circular brush set to ", str(mouseCirc)) if keys[pygame.K_a]: scrollMode = 0 print("Scroll mode set to brush size") elif keys[pygame.K_s]: scrollMode = 1 print("Scroll mode set to sensitivity") elif keys[pygame.K_d]: scrollMode = 2 print("Scroll mode set to height (hotspot)") elif keys[pygame.K_f]: scrollMode = 3 print("Scroll mode set to intensity") if keys[pygame.K_z]: print("Smoothing world...") smoothWorld([0,0], maps, curSens, mouseHotspots) print("Drawing world...") drawWorld(mapImg, 0, 0) print("Done!") kticks = pygame.time.get_ticks() if pygame.time.get_ticks() - mticks >= 50: prsd = pygame.mouse.get_pressed() if prsd[2] or prsd[0]: if mouseMode == 0: #print("SMOOTHING_TILE") pos = getTilePosition(pygame.mouse.get_pos()) #offset, fpos, tpos, sens, hostpots, circular smoothArea([0,0], [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea], curSens, mouseHotspots, mouseCirc) #surface, fpos, tpos drawArea(mapImg, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea]) elif mouseMode == 1: pos = getTilePosition(pygame.mouse.get_pos()) circ = 0 if mouseCirc: circ = curSens raiseArea(1, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea], circ) drawArea(mapImg, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea]) elif mouseMode == 2: pos = getTilePosition(pygame.mouse.get_pos()) circ = 0 if mouseCirc: circ = curSens raiseArea(-1, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea], circ) drawArea(mapImg, [pos[0]-mouseArea, pos[1]-mouseArea], [pos[0]+mouseArea, pos[1]+mouseArea]) elif mouseMode == 3: #hotspot #addHotspot(x, y, h, intensity, dist) pos = getTilePosition(pygame.mouse.get_pos()) addHotspot(pos[0], pos[1], mouseHeight, mouseIntensity, mouseArea) mouseMode = 0 mticks = pygame.time.get_ticks()