[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] [Pygame] Generating a map
Hello again
Out of curosity I have written my own version, I think it should look
like the attached picture.
Hope that helps. The strange thing is, that it only works with sizes
that are of the numbers (2**n)+1.
~DR0ID
Kris Schnee schrieb:
Dave LeCompte (really) wrote:
Also, there's a pretty good paper about the tricks that the "Tribal
Trouble" guys used to make their terrain here:
http://oddlabs.com/download/terrain_generation.pdf
That paper was really useful. I was able to implement a version of the
Voronoi (bubble/ridge thing) with some fiddling, and accidentally made
what appears to be a fractal by accident. It's attached as
"my_generation.py" if you want to see the messy code. The part that
was hard to figure out was what the paper described as:
height = (distance to nearest point)*(arbitrary constant 1)
The distance ranges from 0 to many thousands, so what's a good way to
convert that to a 0-255 range or the 0.0-1.0 range used in the paper?
I ended up doing it in an arbitrary way.
I see that <http://home.scarlet.be/zoetrope/voronoi/> has a Python
implementation of Voronoi code as a "Crystalize" filter for images.
I also tried to implement a diamond-square algorithm, but something's
not quite right about it. If I force the squares to be higher than
normal (adding 64 to the height values), I can see that it's
calculating all the pixels in the image, but normally most of the
image ends up black. The code for that is attached as
"my_generation3.py"; anyone know how to fix it? The problem seems to
be that I'm using a 256x256 bitmap, and the calculation of each cell's
"neighbors" is off by one pixel or something where it wraps around the
edges, so that it finds zeroed pixels instead of the
already-calculated ones.

KLUDGE = 0 ## ( >0 makes the pattern visible despite being flawed )
import pygame
pygame.init()
import random
import sys
import time
import math
random.seed("Next My Generation")#+str(time.time()))
if len(sys.argv)==2:
size = int(sys.argv[1])
else:
size = 256
print "size:", size
good_sizes = [2**n+1 for n in range(1,20)]
if size not in good_sizes:
n = math.log(size, 2)
print n
size = good_sizes[int(math.floor(n))-1]
print "WARNING: only works with sizes (2**n)+1, size changed to:", size
print "\ngood sizes are:", good_sizes
print "\n"
screen = pygame.display.set_mode((size,size))
screen.fill((64,0,0))
def DisplayAsImage(heightmap, iteration):
screen.fill((255,0,255))
terrain = pygame.surface.Surface((size,size))
terrain.fill((255,0,255))
for y in range(size):
for x in range(size):
h = heightmap[(x,y)]
if h!=-1:
terrain.set_at((x,y),(h,h,h))
elif iteration > 4:
## print "ARG:", x,y
pass
screen.blit(terrain,(0,0))
pygame.image.save(terrain, 'gen_terrain_'+str(size)+'x'+str(size)+'_iter'+str(iteration)+'.bmp')
pygame.display.update()
# generate hightmap
heightmap = {}
for x in range(size):
for y in range(size):
heightmap[(x,y)] = -1
# fill in corners
for point in ((0,0),(size-1,0),(0,size-1),(size-1,size-1)):
heightmap[point] = random.randint(0,255)
# override corners manually
##heightmap[(0,0)] = 0 #random.randint(0,255)
##heightmap[(size-1,0)] = 2 #random.randint(0,255)
##heightmap[(0,size-1)] = 4 #random.randint(0,255)
##heightmap[(size-1,size-1)] = 8 #random.randint(0,255)
cell_size = size
half_cell_size = cell_size/2
chaos = 255
iteration = 0
offset = KLUDGE
while cell_size > 1:
print "---------------->iteration:", iteration
print "cell_size", cell_size
print "half cell size", half_cell_size
for anchy in range(0, size-cell_size+1, cell_size):
for anchx in range(0, size-cell_size+1, cell_size):
posx = anchx + half_cell_size
posy = anchy + half_cell_size
neighbors = [(posx+half_cell_size, posy+half_cell_size),\
(posx-half_cell_size, posy+half_cell_size),\
(posx+half_cell_size, posy-half_cell_size),\
(posx-half_cell_size, posy-half_cell_size)]
## print anchx, anchy, posx, posy, neighbors
sum = 0
for n in neighbors:
sum += heightmap[n]
average = sum/4
average += offset
average += random.randint(-chaos, chaos)
heightmap[(posx, posy)] = max(min(average, 255), 0)
for anchy in range(0, size+1, cell_size):
for anchx in range(0, size+1, cell_size):
# print posx, posy, average, neighbors
points = [(anchx+half_cell_size, anchy),\
(anchx, anchy+half_cell_size),\
(anchx+cell_size, anchy+half_cell_size),\
(anchx+half_cell_size, anchy+cell_size)]
for point in points:
px, py = point
neighbors2 = [(px+half_cell_size, py),\
(px-half_cell_size, py),\
(px, py+half_cell_size),\
(px, py-half_cell_size)]
sum = 0
for neigh in neighbors2:
posx, posy = neigh
if posx<0:
posx %= size
if posx>size-1:
posx %= size
if posy<0:
posy %= size
if posy>size-1:
posy %= size
sum += heightmap[(posx, posy)]
sum /= 4
sum += random.randint(-chaos, chaos)
sum += offset
heightmap[(px, py)] = max(min(sum, 255), 0)
iteration += 1
cell_size /= 2
half_cell_size = cell_size/2
chaos = max(chaos/2,1)
DisplayAsImage(heightmap, iteration)
print "Done!"
pygame.event.set_blocked([pygame.MOUSEMOTION, pygame.ACTIVEEVENT])
pygame.event.clear()
pygame.event.wait()
##print heightmap[(0,0)], heightmap[(1,0)], heightmap[(2,0)]
##print heightmap[(0,1)], heightmap[(1,1)], heightmap[(2,1)]
##print heightmap[(0,2)], heightmap[(1,2)], heightmap[(2,2)]