def main_loop(self): planet = Planet(100,1,0) pygame.init() screen = pygame.display.set_mode((planet.max_row,planet.row_count), HWSURFACE) pygame.display.set_caption('Planet') background = pygame.Surface(screen.get_size()) background.fill((128,128,128)) def in_bounds(x,y): return (x > planet.row_offsets[y] and x < planet.row_offsets[y] + planet.row_lengths[y]) background.lock() for y in range(0, screen.get_height()): for x in range(0, screen.get_width()): if in_bounds(x,y): value = planet.rows[y][x - planet.row_offsets[y]] background.set_at((x,y),(value,value,value)) background.unlock() screen.blit(background, (0,0)) points = pygame.sprite.Group() for n in range(1): point = pygame.sprite.Sprite() point.image = pygame.Surface((10,10)) point.w = 10.#random.uniform(1,10) pygame.draw.circle(point.image, (255 - point.w*12,0,0), (5,5), 5) a = array([random.uniform(-1,1), random.uniform(-1,1), random.uniform(-1,1)]) point.p = a / norm(a) print point.p point.v = zeros(3) point.rect = pygame.Rect((0,0), point.image.get_size()) points.add(point) midpoints = pygame.sprite.Group() midpoint = pygame.sprite.Sprite() midpoint.image = pygame.Surface((10,10)) pygame.draw.circle(midpoint.image, (0,255,0), (5,5), 5) midpoint.rect = pygame.Rect((0,0), midpoint.image.get_size()) midpoints.add(midpoint) limit = pygame.time.Clock() done = False while not done: for event in pygame.event.get(): if event.type == QUIT: done = True elif event.type == KEYDOWN: if event.key == K_ESCAPE: done = True # join colliding points for point in points: for other in points: if point == other: continue if math.acos(dot(point.p, other.p)) < 0.1: d = other.p - point.p if (abs(math.acos(dot(d, point.v))) < math.pi /2 and abs(math.acos(dot(d, other.v))) > math.pi / 2): point.p = array(planet.vector_weighted_average( [point.p, other.p], [point.w, other.w])) v = array(planet.vector_weighted_average( [point.v, other.v], [point.w, other.w])) point.v = (norm(point.v) + norm(other.v)) * v point.w = point.w + other.w pygame.draw.circle(point.image, (255 - point.w*12,0,0), (5,5), 5) points.remove(other) # identify clusters of nearby points clusters = [] for point in points: for other in points: if point == other: continue if math.acos(dot(point.p, other.p)) < 0.5: for c in clusters: if point in c: if not other in c: c.append(other) break elif other in c: if not point in c: c.append(point) break else: clusters.append([point, other]) # repel clustered points from center of cluster midpoints.empty() seen = [] for c in clusters: cluster = pygame.sprite.Sprite() cluster.image = pygame.Surface((10,10)) pygame.draw.circle(cluster.image, (0,0,255), (5,5), 5) cluster.rect = pygame.Rect((0,0), cluster.image.get_size()) p = planet.vector_weighted_average( [point.p for point in c], [1 for point in c]) cluster.rect.topleft = planet.vector_to_xy(p, cluster.image.get_size()) midpoints.add(cluster) for point in c: if norm(point.v) < 0.05: point.v = 0.1 * planet.repel_from_point(point.p, p) / point.w if norm(point.v > 0.15): point.v = 0.15 * point.v / norm(point.v) seen.append(point) # apply velocities newpoints = [] for point in points: # move or split isolated points if not point in seen: if norm(point.v) < 0.05: u = zeros(3) u[min(range(len(a)), key=lambda i: abs(point.p[i]))] = 1 v = cross(point.p, u) v = 0.01 * planet.rotate(v / norm(v), point.p, random.uniform(0, 2*math.pi)) if point.w < 0.25: point.v = v / point.w else: point.w /= 2 point.v = v / point.w newpoint = pygame.sprite.Sprite() newpoint.image = pygame.Surface((10,10)) row = random.randint(1, planet.row_count-1) newpoint.w = point.w pygame.draw.circle(point.image, (255 - point.w*12,0,0), (5,5), 5) pygame.draw.circle(newpoint.image, (255 - newpoint.w*12,0,0), (5,5), 5) newpoint.p = point.p newpoint.v = -point.v newpoint.rect = pygame.Rect((0,0), newpoint.image.get_size()) newpoints.append(newpoint) point.p, point.v = planet.apply_velocity(point.p, point.v) if norm(point.v) < 0.01: point.v = zeros(3) else: point.v = 0.99 * point.v point.rect.topleft = planet.vector_to_xy(point.p, point.image.get_size()) points.add(newpoints) # calculate overall midpoint midpoint.p = planet.vector_weighted_average( [point.p for point in points.sprites()], [point.w for point in points.sprites()]) midpoint.rect.topleft = planet.vector_to_xy(midpoint.p, midpoint.image.get_size()) midpoints.add(midpoint) points.clear(screen, background) points.draw(screen) midpoints.clear(screen, background) midpoints.draw(screen) pygame.display.flip() limit.tick(25)
def main_loop(self): planet = Planet(100,1,0) pygame.init() screen = pygame.display.set_mode((planet.max_row,planet.row_count), HWSURFACE) pygame.display.set_caption('Planet') background = pygame.Surface(screen.get_size()) background.fill((128,128,128)) def in_bounds(x,y): return (x > planet.row_offsets[y] and x < planet.row_offsets[y] + planet.row_lengths[y]) background.lock() for y in range(0, screen.get_height()): for x in range(0, screen.get_width()): if in_bounds(x,y): value = planet.rows[y][x - planet.row_offsets[y]] background.set_at((x,y),(value,value,value)) background.unlock() screen.blit(background, (0,0)) points = pygame.sprite.Group() for n in range(20): point = pygame.sprite.Sprite() point.image = pygame.Surface((10,10)) pygame.draw.circle(point.image, (255,0,0), (5,5), 5) row = random.randint(1, planet.row_count-1) a = array([random.uniform(-1) for i in range(3)]) point.p = a / norm(a) point.theta = 0 if n == 0 else random.uniform(0, 2 * math.pi) point.v = zeros(3) point.rect = pygame.Rect((0,0), point.image.get_size()) points.add(point) midpoints = pygame.sprite.Group() midpoint = pygame.sprite.Sprite() midpoint.image = pygame.Surface((10,10)) pygame.draw.circle(midpoint.image, (0,255,0), (5,5), 5) midpoint.rect = pygame.Rect((0,0), midpoint.image.get_size()) midpoints.add(midpoint) limit = pygame.time.Clock() done = False while not done: for event in pygame.event.get(): if event.type == QUIT: done = True elif event.type == KEYDOWN: if event.key == K_ESCAPE: done = True midpoint.p = planet.vector_weighted_average( [point.p for point in points.sprites()], [1 for point in points.sprites()]) midpoint.rect.topleft = planet.vector_to_xy(midpoint.p, midpoint.image.get_size()) speed = sum([norm(p.v) for p in points]) for point in points: if not speed: point.v = 0.1 * planet.repel_from_point(point.p, midpoint.p) point.p, point.v = planet.apply_velocity(point.p, point.v) if norm(point.v) < 0.001: point.v = zeros(3) else: point.v = 0.9 * point.v point.rect.topleft = planet.vector_to_xy(point.p, point.image.get_size()) points.clear(screen, background) points.draw(screen) midpoints.clear(screen, background) midpoints.draw(screen) pygame.display.flip() limit.tick()
def main_loop(self): planet = Planet(100, 1, 0) pygame.init() screen = pygame.display.set_mode((planet.max_row, planet.row_count), HWSURFACE) pygame.display.set_caption("Planet") background = pygame.Surface(screen.get_size()) background.fill((128, 128, 128)) def in_bounds(x, y): return x > planet.row_offsets[y] and x < planet.row_offsets[y] + planet.row_lengths[y] background.lock() for y in range(0, screen.get_height()): for x in range(0, screen.get_width()): if in_bounds(x, y): value = planet.rows[y][x - planet.row_offsets[y]] background.set_at((x, y), (value, value, value)) background.unlock() screen.blit(background, (0, 0)) points = pygame.sprite.Group() for n in range(20): point = pygame.sprite.Sprite() point.image = pygame.Surface((10, 10)) row = random.randint(1, planet.row_count - 1) a = array([random.uniform(-1) for i in range(3)]) point.w = random.uniform(1, 10) pygame.draw.circle(point.image, (0, 255 - int(point.w * 16), 0), (5, 5), 5) point.p = a / norm(a) point.theta = 0 if n == 0 else random.uniform(0, 2 * math.pi) point.v = zeros(3) point.rect = pygame.Rect((0, 0), point.image.get_size()) points.add(point) midpoints = pygame.sprite.Group() midpoint = pygame.sprite.Sprite() midpoint.image = pygame.Surface((10, 10)) pygame.draw.circle(midpoint.image, (0, 0, 255), (5, 5), 5) midpoint.rect = pygame.Rect((0, 0), midpoint.image.get_size()) heatpoint = pygame.sprite.Sprite() heatpoint.image = pygame.Surface((10, 10)) pygame.draw.circle(heatpoint.image, (255, 0, 0), (5, 5), 5) heatpoint.rect = pygame.Rect((0, 0), heatpoint.image.get_size()) midpoints.add(heatpoint) midpoints.add(midpoint) limit = pygame.time.Clock() done = False while not done: for event in pygame.event.get(): if event.type == QUIT: done = True elif event.type == KEYDOWN: if event.key == K_ESCAPE: done = True midpoint.p = planet.vector_weighted_average( [point.p for point in points.sprites()], [point.w for point in points.sprites()] ) midpoint.rect.topleft = planet.vector_to_xy(midpoint.p, midpoint.image.get_size()) speed = sum([norm(p.v) for p in points]) if speed < 0.05: heatpoint.p = midpoint.p heatpoint.rect.topleft = midpoint.rect.topleft for point in points: dist = math.acos(dot(heatpoint.p, point.p)) decay = lambda dist: 0.01 * pow(dist - math.pi, 2) v = -planet.project_on_plane(heatpoint.p - point.p, point.p) point.v += decay(dist) * v / norm(v) / point.w point.p, point.v = planet.apply_velocity(point.p, point.v) point.v = 0.75 * point.v point.rect.topleft = planet.vector_to_xy(point.p, point.image.get_size()) merge = dict() for point in points: for other in points: if point == other: continue if math.acos(dot(point.p, other.p)) < 0.05: if other in merge: if not point in merge[other]: merge[other].append(point) else: merge[point] = [other] newpoints = [] seen = [] for first, merging in merge.items(): merging.append(first) print "merging", len(merging), [m.w for m in merging], "into", sum([m.w for m in merging]) for point in merging: seen.append(point) point = pygame.sprite.Sprite() point.image = pygame.Surface((10, 10)) point.w = sum([m.w for m in merging]) / len(merging) pygame.draw.circle(point.image, (0, 255 - int(point.w * 16), 0), (5, 5), 5) point.p = array(planet.vector_weighted_average([m.p for m in merging], [m.w for m in merging])) point.v = sum([m.v / m.w for m in merging]) point.rect = pygame.Rect((0, 0), point.image.get_size()) newpoints.append(point) for point in points: if point in seen: continue if point.w > 0.5 and norm(point.v) > 0.1: added = [] for i in range(2): half = pygame.sprite.Sprite() half.image = pygame.Surface((10, 10)) half.w = point.w / 2 pygame.draw.circle(half.image, (0, 255 - int(half.w * 16), 0), (5, 5), 5) half.p = point.p theta = -math.pi / 4 + i * math.pi / 2 half.v = planet.rotate(point.v, half.p, theta) / 2 half.rect = pygame.Rect((0, 0), half.image.get_size()) newpoints.append(half) added.append(half) print "splitting", point.w, "into", [a.w for a in added] seen.append(point) save = [p for p in points if not p in seen] points.empty() points.add(newpoints) points.add(save) points.clear(screen, background) points.draw(screen) midpoints.clear(screen, background) midpoints.draw(screen) pygame.display.flip() limit.tick()
def main_loop(self): planet = Planet(100,1,0) pygame.init() screen = pygame.display.set_mode((planet.max_row,planet.row_count), HWSURFACE) pygame.display.set_caption('Planet') background = pygame.Surface(screen.get_size()) background.fill((128,128,128)) def in_bounds(x,y): return (x > planet.row_offsets[y] and x < planet.row_offsets[y] + planet.row_lengths[y]) background.lock() for y in range(0, screen.get_height()): for x in range(0, screen.get_width()): if in_bounds(x,y): value = planet.rows[y][x - planet.row_offsets[y]] background.set_at((x,y),(value,value,value)) background.unlock() screen.blit(background, (0,0)) points = pygame.sprite.Group() for n in range(5): point = pygame.sprite.Sprite() point.image = pygame.Surface((10,10)) pygame.draw.circle(point.image, (255,0,0), (5,5), 5) row = random.randint(1, planet.row_count-1) a = array([random.uniform(-1) for i in range(3)]) point.p = a / norm(a) point.theta = 0 if n == 0 else random.uniform(0, 2 * math.pi) u = zeros(3) u[min(range(len(a)), key=lambda i: abs(point.p[i]))] = 1 v = cross(point.p, u) point.v = 0.01 * planet.rotate(v / norm(v), point.p, random.uniform(0, 2*math.pi)) point.rect = pygame.Rect((0,0), point.image.get_size()) points.add(point) limit = pygame.time.Clock() done = False while not done: for event in pygame.event.get(): if event.type == QUIT: done = True elif event.type == KEYDOWN: if event.key == K_ESCAPE: done = True for point in points: point.p, point.v = planet.apply_velocity(point.p, point.v) point.rect.topleft = planet.vector_to_xy(point.p, point.image.get_size()) points.clear(screen, background) points.draw(screen) pygame.display.flip() limit.tick()
def main_loop(self): planet = Planet(100,1,0) pygame.init() screen = pygame.display.set_mode((planet.max_row,planet.row_count), HWSURFACE) pygame.display.set_caption('Planet') background = pygame.Surface(screen.get_size()) background.fill((128,128,128)) def in_bounds(x,y): return (x > planet.row_offsets[y] and x < planet.row_offsets[y] + planet.row_lengths[y]) background.lock() for y in range(0, screen.get_height()): for x in range(0, screen.get_width()): if in_bounds(x,y): value = planet.rows[y][x - planet.row_offsets[y]] background.set_at((x,y),(value,value,value)) background.unlock() screen.blit(background, (0,0)) points = pygame.sprite.Group() orients = pygame.sprite.Group() shapes = pygame.sprite.Group() for n in range(3): point = pygame.sprite.Sprite() point.image = pygame.Surface((10,10)) pygame.draw.circle(point.image, (255,0,0), (5,5), 5) # random location a = array([random.uniform(-1) for i in range(3)]) point.p = a / norm(a) # best unit vector u = zeros(3) u[min(range(len(a)), key=lambda i: abs(point.p[i]))] = 1 # random velocity vector v = cross(point.p, u) point.v = 0.01 * planet.rotate(v / norm(v), point.p, random.uniform(0, 2*math.pi)) # random orienting point (o, ov) = planet.apply_velocity(point.p, 0.05 * planet.rotate(v / norm(v), point.p, random.uniform(0, 2*math.pi))) point.o = pygame.sprite.Sprite() point.o.p = o point.o.image = pygame.Surface((6,6)) pygame.draw.circle(point.o.image, (0,0,255), (3,3), 3) point.o.rect = pygame.Rect((0,0), point.o.image.get_size()) orients.add(point.o) # polygon points point.shape = [(.1,.23),(.12,.43),(.13,.52),(.25,.54), (.3,.43),(.43,.48),(.53,.31),(.48,.14), (.5,.1)] point.rect = pygame.Rect((0,0), point.image.get_size()) points.add(point) def add_shape_coords(coords, cmin, cmax, px, py): sprite = pygame.sprite.Sprite() sprite.image = pygame.Surface((cmax[0]-cmin[0],cmax[1]-cmin[1])) pygame.draw.polygon(sprite.image, (0,255,0), [(c[0]-cmin[0], c[1]-cmin[1]) for c in coords], 1) sprite.rect = pygame.Rect((px-sprite.image.get_width()/2, py-sprite.image.get_height()/2), sprite.image.get_size()) shapes.add(sprite) limit = pygame.time.Clock() done = False while not done: for event in pygame.event.get(): if event.type == QUIT: done = True elif event.type == KEYDOWN: if event.key == K_ESCAPE: done = True shapes.empty() for point in points: point.p, point.v = planet.apply_velocity(point.p, point.v) point.o.p, ov = planet.apply_velocity(point.o.p, point.v) point.rect.topleft = planet.vector_to_xy(point.p, point.image.get_size()) point.o.rect.topleft = planet.vector_to_xy(point.o.p, point.o.image.get_size()) shape = Polygon(point.shape) c = shape.centroid.coords[0] coords = [] for vertex in point.shape: # find distance from centroid d = math.sqrt(sum([(vertex[i]-c[i])*(vertex[i]-c[i]) for i in range(2)])) # find angle from local north th = math.atan2(vertex[0]-c[0],vertex[1]-c[1]) # axis of rotation separating point from orientation point u = cross(point.p, point.o.p) u = u / norm(u) # rotate point around it by d p = planet.rotate(point.p, u, d) # and then around point by -theta p = planet.rotate(p, point.p, -th) coords.append(planet.vector_to_xy(p)) cmin, cmax = ranges(coords) px,py = planet.vector_to_xy(point.p) inproj = [planet.in_projection(px+x-(cmin[0]+cmax[0])/2, py+y-(cmin[1]+cmax[1])/2) for (x,y) in coords] if all(inproj): add_shape_coords(coords, cmin, cmax, px, py) else: left = [] right = [] for c in coords: (left if c[0] < planet.max_row/2 else right).append(c) if (len(left) > 1): cmin, cmax = ranges(left) add_shape_coords(left, cmin, cmax, px, py) if (len(right) > 1): cmin, cmax = ranges(right) add_shape_coords(right, cmin, cmax, px, py) points.clear(screen, background) orients.clear(screen, background) shapes.clear(screen, background) shapes.draw(screen) points.draw(screen) orients.draw(screen) pygame.display.flip() limit.tick()