[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] [Pygame] Generating a map
Hi
I have looked into it and got the attached image (I do not know if you
expected that, I think not, although one can see the structure). You
were mistaken in edge_points (about line 77). Please look what I have
changed in the attached version.
~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.

"""
Terrain generator using diamond-square algorithm.
Something is not quite right here, because the points in one phase or
the other are off by one, causing them to find zero values instead of the
points they're supposed to find. I'm using a 256x256 map, which maybe should
be 255x255, but am not quite sure how it's meant to work.
"""
KLUDGE = 32 ## ( >0 makes the pattern visible despite being flawed )
import pygame
pygame.init()
import random
random.seed("Next My Generation")
size = 256
screen = pygame.display.set_mode((size,size))
screen.fill((64,0,0))
def DisplayAsImage(heightmap):
screen.fill((64,0,0))
terrain = pygame.surface.Surface((size,size))
terrain.fill((0,0,0))
for y in range(size):
for x in range(size):
h = heightmap[x][y]
terrain.set_at((x,y),(h,h,h))
screen.blit(terrain,(0,0))
pygame.image.save(terrain, 'gen_terrain3.png')
pygame.display.update()
heightmap = []
for x in range(size):
heightmap.append([])
for y in range(size):
heightmap[-1].append(0)
## heightmap[-1].append(random.randint(0,255)) ## Placebo.
for point in ((0,0),(size-1,0),(0,size-1),(size-1,size-1)):
heightmap[point[0]][point[1]] = 128
cell_size = size
half_cell_size = cell_size/2
chaos = 64
iteration = 0
while cell_size > 0:
##for n in range(1):
print "Iteration: "+str(iteration)
iteration += 1
for anchor_y in range(0,size,cell_size):
for anchor_x in range(0,size,cell_size):
## print "Anchor: "+str((anchor_x,anchor_y))
center_x = anchor_x - 1 + half_cell_size
center_y = anchor_y - 1 + half_cell_size
## The "square" phase: calculate the center point.
## print "Center: "+str((center_x, center_y))
neighbors = ((anchor_x,anchor_y),
(anchor_x+cell_size-1,anchor_y),
(anchor_x,anchor_y+cell_size-1),
(anchor_x+cell_size-1,anchor_y+cell_size-1))
try:
average_height = sum((heightmap[n[0]][n[1]] for n in neighbors))/4
except:
print neighbors
raise "Oof."
## print "Average: "+str(average_height)
h = average_height + random.randint(-chaos,chaos)+KLUDGE
h = max(min(h,255),0) ## Keep within 0-255 range.
heightmap[center_x][center_y] = h
## The "diamond" phase: calculate the edge points.
## edge_points = ((center_x,0),
## (0,center_y),
## (size-1,center_y),
## (center_x,size-1))
edge_points = ((center_x,center_y-half_cell_size),
(center_x-half_cell_size,center_y),
(center_x+half_cell_size,center_y),
(center_x,center_y+half_cell_size))
for point in edge_points:
## print "Edge point: "+str(point)
## neighbors = [(point[0],point[1]-half_cell_size),
## (point[0]-half_cell_size,point[1]),
## (point[0]+half_cell_size,point[1]),
## (point[0],point[1]+half_cell_size)]
neighbors = [[point[0],point[1]-half_cell_size],
[point[0]-half_cell_size,point[1]],
[point[0]+half_cell_size,point[1]],
[point[0],point[1]+half_cell_size]]
for n in range(4):
neighbor = neighbors[n]
if neighbor[0] < 0:
neighbors[n][0] += size
elif neighbor[0] > 255:
neighbors[n][0] -= size
if neighbor[1] < 0:
neighbors[n][1] += size
elif neighbor[1] > 255:
neighbors[n][1] -= size
## ## Kludge to keep first-round points within bounds.
## if neighbors[2][0] >= size:
## neighbors[2] = (point[0]-half_cell_size-1,point[1])
## if neighbors[3][1] >= size:
## neighbors[3] = (point[0],point[1]-half_cell_size-1)
## print " Neighbors: "+str(neighbors)
try:
average_height = sum((heightmap[n[0]][n[1]] for n in neighbors))/4
except:
print neighbors
raise "Eek!"
h = average_height + random.randint(-chaos,chaos)
h = max(min(h,255),0) ## Keep within 0-255 range.
heightmap[point[0]][point[1]] = h
cell_size /= 2
half_cell_size /= 2
chaos = max(chaos/2,1)
DisplayAsImage(heightmap)
print "Done!"
raw_input()