Beispiel #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(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)
Beispiel #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(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()