예제 #1
0
    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()
예제 #2
0
    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)
예제 #3
0
    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()