예제 #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()
        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()