예제 #1
0
파일: view.py 프로젝트: mulaifi/game
 def paint(self):
     black = 0, 0, 0
     self.screen.fill(black)
     self.drawLevel()
     self.drawProjectiles()
     self.drawPlayers()
     self.dynamicSprites.draw(self.screen)
     self.staticSprites.draw(self.screen)
     if self.debug:  # pymunk space
         draw_space(self.screen, self.manager.space)
     pygame.display.flip()
     self.dynamicSprites.empty()
예제 #2
0
    def tick(self):
        self.screen.fill(THECOLORS['black'])
        draw_space(self.screen, self.space)
        self.space.step(1/50.0)
        pygame.display.flip()
        self.clock.tick(50)

        dead_blocks = []

        for shape in self.space.shapes:
            if shape.collision_type > 5:
               shape.collision_type -= 1
            if shape.collision_type == 5:
               dead_blocks.append(shape)
        for shape in dead_blocks:
            self.space.remove(shape)
예제 #3
0
    def tick(self):
        self.screen.fill(THECOLORS['black'])
        draw_space(self.screen, self.space)
        self.space.step(1 / 50.0)
        pygame.display.flip()
        self.clock.tick(50)

        dead_blocks = []

        for shape in self.space.shapes:
            if shape.collision_type > 5:
                shape.collision_type -= 1
            if shape.collision_type == 5:
                dead_blocks.append(shape)
        for shape in dead_blocks:
            self.space.remove(shape)
예제 #4
0
def main():
    ### PyGame init
    pygame.init()
    screen = pygame.display.set_mode((width,height)) 
    clock = pygame.time.Clock()
    running = True
    font = pygame.font.SysFont("Arial", 16)
    
    ### Physics stuff
    space = pymunk.Space()   
    space.gravity = 0,-1000
    # walls - the left-top-right walls
    static= [pymunk.Segment(space.static_body, (50, 50), (50, 550), 5)
                ,pymunk.Segment(space.static_body, (50, 550), (650, 550), 5)
                ,pymunk.Segment(space.static_body, (650, 550), (650, 50), 5)
                ,pymunk.Segment(space.static_body, (50, 50), (650, 50), 5)
                ]  
    
    b2 = pymunk.Body()
    static.append(pymunk.Circle(b2, 30))
    b2.position = 300,400
    
    for s in static:
        s.friction = 1.
        s.group = 1
    space.add(static)
    
    # "Cannon" that can fire arrows
    cannon_body = pymunk.Body(pymunk.inf, pymunk.inf)
    cannon_shape = pymunk.Circle(cannon_body, 25)
    cannon_shape.sensor = True
    cannon_body.position = 100,100
    space.add(cannon_shape)
    
    arrow_body,arrow_shape = create_arrow()
    space.add(arrow_shape)
        
    space.add_collision_handler(0, 1, post_solve=post_solve_arrow_hit)

    flying_arrows = []
    
    while running:
        for event in pygame.event.get():
            if event.type == QUIT or \
                event.type == KEYDOWN and (event.key in [K_ESCAPE, K_q]):  
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                start_time = pygame.time.get_ticks()
            elif event.type == KEYDOWN and event.key == K_p:
                pygame.image.save(screen, "arrows.png")
            elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
                end_time = pygame.time.get_ticks()
                
                diff = end_time - start_time
                power = max(min(diff, 1000), 10) * 1.5
                impulse = power * Vec2d(1,0)
                arrow_body.apply_impulse(impulse.rotated(arrow_body.angle))
                
                space.add(arrow_body)
                flying_arrows.append(arrow_body)
                
                arrow_body, arrow_shape = create_arrow()
                space.add(arrow_shape)
            
        keys = pygame.key.get_pressed()
        
        speed = 2.5
        if (keys[K_UP]):
            cannon_body.position += Vec2d(0,1) * speed
        if (keys[K_DOWN]):
            cannon_body.position += Vec2d(0,-1) * speed
        if (keys[K_LEFT]):
            cannon_body.position += Vec2d(-1,0) * speed
        if (keys[K_RIGHT]):
            cannon_body.position += Vec2d(1,0) * speed
            
        mouse_position = from_pygame( Vec2d(pygame.mouse.get_pos()), screen )
        cannon_body.angle = (mouse_position - cannon_body.position).angle
        # move the unfired arrow together with the cannon
        arrow_body.position = cannon_body.position + Vec2d(cannon_shape.radius + 40, 0).rotated(cannon_body.angle)
        arrow_body.angle = cannon_body.angle
        
        for flying_arrow in flying_arrows:
            drag_constant = 0.0002
            pointing_direction = Vec2d(1,0).rotated(flying_arrow.angle)
            flight_direction = Vec2d(flying_arrow.velocity)
            flight_speed = flight_direction.normalize_return_length()
            dot = flight_direction.dot(pointing_direction)
            drag_force_magnitude = (1-abs(dot)) * flight_speed **2 * drag_constant * flying_arrow.mass
            
            arrow_tail_position = Vec2d(-50, 0).rotated(flying_arrow.angle)
            flying_arrow.apply_impulse(drag_force_magnitude * -flight_direction, arrow_tail_position)
            
            flying_arrow.angular_velocity *= 0.9
            
        ### Clear screen
        screen.fill(pygame.color.THECOLORS["black"])
        
        ### Draw stuff
        draw_space(screen, space)
        
        # Power meter
        if pygame.mouse.get_pressed()[0]:
            current_time = pygame.time.get_ticks()
            diff = current_time - start_time
            power = max(min(diff, 1000), 10)
            h = power / 2
            pygame.draw.line(screen, pygame.color.THECOLORS["red"], (30,550), (30,550-h), 10)
                
        # Info and flip screen
        screen.blit(font.render("fps: " + str(clock.get_fps()), 1, THECOLORS["white"]), (0,0))
        screen.blit(font.render("Aim with mouse, hold LMB to powerup, release to fire", 1, THECOLORS["darkgrey"]), (5,height - 35))
        screen.blit(font.render("Press R to reset, ESC or Q to quit", 1, THECOLORS["darkgrey"]), (5,height - 20))
        
        pygame.display.flip()
        
        ### Update physics
        fps = 60
        dt = 1./fps
        space.step(dt)
        
        clock.tick(fps)
예제 #5
0
 def update_pygame(self):
     self.screen.fill(pygame.color.THECOLORS["black"])
     draw_space(self.screen, self.sim.space)
     pygame.display.flip()
예제 #6
0
def main():
    pygame.init()
    screen = pygame.display.set_mode((600,600)) 
    clock = pygame.time.Clock()
    font = pygame.font.SysFont("Arial", 16)
    
    space = pymunk.Space()
    
    ### Static
    #Static Segments
    segments = [ pymunk.Segment(space.static_body, (10, 50), (10, 500), 1)
                ,pymunk.Segment(space.static_body, (30, 50), (30, 500), 2)
                ,pymunk.Segment(space.static_body, (50, 50), (50, 500), 3)
                ,pymunk.Segment(space.static_body, (70, 50), (70, 500), 5)
                ]  
    space.add(segments)
    
    b = pymunk.Body()
    b.position = (40,530)
    b.angle = 3.14/7
    s = pymunk.Segment(b, (-30,0), (30,0), 2)
    space.add(s)
    
    # Static Circles
    b = pymunk.Body()
    b.position = (150,500)
    s = pymunk.Circle(b, 10)
    space.add(s)
    
    b = pymunk.Body()
    b.position = (150,500)
    s = pymunk.Circle(b, 10,(0,-30))
    space.add(s)
    
    b = pymunk.Body()
    b.position = (150,400)
    b.angle = 3.14/4
    s = pymunk.Circle(b, 40)
    space.add(s)
    
    # Static Polys
    b = pymunk.Body()
    b.position = (150,300)
    b.angle = 3.14/4
    s = pymunk.Poly(b, [(0, -50),(30, 50),(-30, 50)])
    space.add(s)
    
    b = pymunk.Body()
    b.position = (150,300)
    b.angle = 3.14/2
    s = pymunk.Poly(b, [(0, -50),(30, 50),(-30, 50)], (-100,0))
    space.add(s)
    
    b = pymunk.Body()
    b.position = (150,200)
    s = pymunk.Poly(b, [(0, -50),(30, 50),(-30, 50)], (0,-100))
    space.add(s)
    
    ### Dynamic
    
    #Dynamic Segments
    b = pymunk.Body(1,1)
    segments = [ pymunk.Segment(b, (210, 50), (210, 500), 1)
                ,pymunk.Segment(b, (230, 50), (230, 500), 2)
                ,pymunk.Segment(b, (250, 50), (250, 500), 3)
                ,pymunk.Segment(b, (270, 50), (270, 500), 5)
                ]  
    space.add(segments)
    
    b = pymunk.Body(1,1)
    b.position = (240,530)
    b.angle = 3.14/7
    s = pymunk.Segment(b, (-30,0), (30,0), 2)
    space.add(s)
    
    # Static Circles
    b = pymunk.Body(1,1)
    b.position = (350,500)
    s = pymunk.Circle(b, 10)
    space.add(s)
    
    b = pymunk.Body(1,1)
    b.position = (350,500)
    s = pymunk.Circle(b, 10,(0,-30))
    space.add(s)
    
    b = pymunk.Body(1,1)
    b.position = (350,400)
    b.angle = 3.14/4
    s = pymunk.Circle(b, 40)
    space.add(s)
    
    # Static Polys
    b = pymunk.Body(1,1)
    b.position = (350,300)
    b.angle = 3.14/4
    s = pymunk.Poly(b, [(0, -50),(30, 50),(-30, 50)])
    space.add(s)
    
    b = pymunk.Body(1,1)
    b.position = (350,300)
    b.angle = 3.14/2
    s = pymunk.Poly(b, [(0, -50),(30, 50),(-30, 50)], (-100,0))
    space.add(s)
    
    b = pymunk.Body(1,1)
    b.position = (350,200)
    s = pymunk.Poly(b, [(0, -50),(30, 50),(-30, 50)], (0,-100))
    space.add(s)
    
    ###Constraints
    
    # PinJoints
    a = pymunk.Body(1,1)
    a.position = (450,530)
    b = pymunk.Body(1,1)
    b.position = (550,530)
    j = pymunk.PinJoint(a,b)
    space.add(a,b,j)
    
    a = pymunk.Body(1,1)
    a.position = (450,480)
    b = pymunk.Body(1,1)
    b.position = (550,480)
    j = pymunk.PinJoint(a,b, anchr1=(0,20), anchr2=(0,-20))
    space.add(a,b,j)
    
    # SlideJoints
    a = pymunk.Body(1,1)
    a.position = (450,430)
    b = pymunk.Body(1,1)
    b.position = (550,430)
    j = pymunk.SlideJoint(a,b, anchr1=(0,20), anchr2=(0,-20), min=10,max=30)
    space.add(a,b,j)
    
    
    # TODO: more stuff here :)
    
    ### Other
    
    # Object not drawn by draw_space
    b = pymunk.Body()
    b.position = (500,250)
    s = pymunk.Circle(b, 40)
    s.ignore_draw = True
    space.add(s)
    
    # Object in custom color
    b = pymunk.Body()
    b.position = (500,200)
    s = pymunk.Circle(b, 40)
    s.color = pygame.color.THECOLORS["pink"]
    space.add(s)
    
    ### Draw it 
    screen.fill(pygame.color.THECOLORS["black"])
    
    draw_space(screen, space)
                    
    # Info
    screen.blit(font.render("Demo example of shapes drawn by pygame_util.draw_space()", 1, pygame.color.THECOLORS["darkgray"]), (5, 580))
    screen.blit(font.render("Static shapes", 1, pygame.color.THECOLORS["white"]), (50, 20))
    screen.blit(font.render("Dynamic shapes", 1, pygame.color.THECOLORS["white"]), (250, 20))
    screen.blit(font.render("Constraints", 1, pygame.color.THECOLORS["white"]), (450, 20))
    screen.blit(font.render("Other", 1, pygame.color.THECOLORS["white"]), (450, 300))
   
    pygame.display.flip()
    
    while True:
        for event in pygame.event.get():
            if event.type == QUIT or \
                event.type == KEYDOWN and (event.key in [K_ESCAPE, K_q]):  
                return 
            elif event.type == KEYDOWN and event.key == K_p:
                pygame.image.save(screen, "pygame_util_demo.png")                
                                  
        clock.tick()
def evaluate(genome, space, screen, fast_mode, start_x, start_vx, bot_startx):
    # Setup the environment
    clock = pygame.time.Clock()

    # The agents - the brain and the ball
    net = NEAT.NeuralNetwork()
    genome.BuildPhenotype(net)

    agent = NN_agent(space, net, bot_startx)
    ball = Ball(space, start_x, start_vx)

    space.add_collision_handler(collision_type_nn, collision_type_floor,
                                agent.touch_floor, None, None,
                                agent.leave_floor)
    space.add_collision_handler(collision_type_ball, collision_type_floor,
                                ball.touch_floor, None, None, ball.leave_floor)

    tstep = 0
    avg_ball_height = 0
    while tstep < max_timesteps:
        tstep += 1
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                exit()
            elif event.type == KEYDOWN and event.key == K_f:
                fast_mode = not fast_mode
            elif event.type == KEYDOWN and event.key == K_LEFT and not fast_mode:
                ball.body.velocity = (ball.body.velocity[0] - 200,
                                      ball.body.velocity[1])
            elif event.type == KEYDOWN and event.key == K_RIGHT and not fast_mode:
                ball.body.velocity = (ball.body.velocity[0] + 200,
                                      ball.body.velocity[1])
            elif event.type == KEYDOWN and event.key == K_UP and not fast_mode:
                ball.body.velocity = (ball.body.velocity[0],
                                      ball.body.velocity[1] + 200)

        ### Update physics
        dt = 1.0 / 50.0
        space.step(dt)

        # The NN interacts with the world on each 20 timesteps
        if (tstep % 20) == 0:
            agent.interact(ball)
        avg_ball_height += ball.body.position[1]

        # stopping conditions
        if not ball.in_air:
            break
        #if abs(agent.body.velocity[0]) < 50: # never stop on one place!
        #    break

        if not fast_mode:
            # draw the phenotype
            img = np.zeros((250, 250, 3), dtype=np.uint8)
            img += 10
            NEAT.DrawPhenotype(img, (0, 0, 250, 250), net)
            cv2.imshow("current best", img)
            cv2.waitKey(1)

            ## Draw stuff
            screen.fill(THECOLORS["black"])

            ### Draw stuff
            draw_space(screen, space)

            ### Flip screen
            pygame.display.flip()
            clock.tick(50)

    fitness = tstep  #+ avg_ball_height/tstep
    if ball.body.position[1] < 0:
        fitness = 0

    # remove objects from space
    space.remove(agent.shape, agent.body)
    space.remove(ball.shape, ball.body)
    #    print 'Genome ID:', genome.GetID(), 'Fitness:', tstep
    # the fitness is the number of ticks passed
    return fitness, fast_mode
예제 #8
0
def evaluate(genome, space, screen, fast_mode, start_x, start_vx, bot_startx):
    # Setup the environment
    clock = pygame.time.Clock()

    # The agents - the brain and the ball
    net = NEAT.NeuralNetwork()
    genome.BuildPhenotype(net)

    
    agent = NN_agent(space, net, bot_startx)
    ball = Ball(space, start_x, start_vx)
    
    space.add_collision_handler(collision_type_nn,   collision_type_floor, 
                                agent.touch_floor, None, None, agent.leave_floor)
    space.add_collision_handler(collision_type_ball, collision_type_floor, 
                                ball.touch_floor,  None, None, ball.leave_floor)

    tstep = 0
    avg_ball_height = 0
    while tstep < max_timesteps:
        tstep += 1
        for event in pygame.event.get():
            if event.type == QUIT:
                exit()
            elif event.type == KEYDOWN and event.key == K_ESCAPE:
                exit()
            elif event.type == KEYDOWN and event.key == K_f:
                fast_mode = not fast_mode
            elif event.type == KEYDOWN and event.key == K_LEFT and not fast_mode:
                ball.body.velocity = (ball.body.velocity[0] - 200, ball.body.velocity[1]) 
            elif event.type == KEYDOWN and event.key == K_RIGHT and not fast_mode:
                ball.body.velocity = (ball.body.velocity[0] + 200, ball.body.velocity[1]) 
            elif event.type == KEYDOWN and event.key == K_UP and not fast_mode:
                ball.body.velocity = (ball.body.velocity[0], ball.body.velocity[1] + 200) 

        ### Update physics
        dt = 1.0/50.0
        space.step(dt)
        
        # The NN interacts with the world on each 20 timesteps
        if (tstep % 20) == 0:
            agent.interact(ball)
        avg_ball_height += ball.body.position[1]
            
        # stopping conditions
        if not ball.in_air:
            break
        #if abs(agent.body.velocity[0]) < 50: # never stop on one place!
        #    break
                    
        if not fast_mode:
            # draw the phenotype
            img = np.zeros((250, 250, 3), dtype=np.uint8)
            img += 10
            NEAT.DrawPhenotype(img, (0, 0, 250, 250), net )
            cv2.imshow("current best", img)
            cv2.waitKey(1)
            
            ## Draw stuff
            screen.fill(THECOLORS["black"])
            
            ### Draw stuff
            draw_space(screen, space)
            
            ### Flip screen
            pygame.display.flip()
            clock.tick(50)
        
    fitness = tstep #+ avg_ball_height/tstep
    if ball.body.position[1] < 0:
        fitness = 0
    
    # remove objects from space
    space.remove(agent.shape, agent.body)
    space.remove(ball.shape, ball.body)
#    print 'Genome ID:', genome.GetID(), 'Fitness:', tstep
    # the fitness is the number of ticks passed
    return fitness, fast_mode
def main():
    
     
    ### PyGame init
    pygame.init()
    
    clock = pygame.time.Clock()
    running = True


    ### Physics stuff
    
    space.gravity = 0,-980
    static= [pymunk.Segment(space.static_body, (10, 50), (10, 590), 5),
        pymunk.Segment(space.static_body, (500, 200), (900,200), 5),
        pymunk.Segment(space.static_body, (500, 100), (900,100), 5),
         pymunk.Segment(space.static_body, (500, 300), (900,300), 5),
         pymunk.Segment(space.static_body, (500, 100), (450,150), 5),
         pymunk.Segment(space.static_body, (10, 590), (890, 590), 5)
                ]

    for s in static:
        s.friction = 1.
        s.group = 1
    space.add(static)
    # "Cannon" that can fire arrows
    cannon_body = pymunk.Body(10, 10)
    cannon_shape = pymunk.Circle(cannon_body, .1)
    cannon_shape.ignore_draw=True
    #~ cannon_shape.sensor = True
    cannon_body.position = 100,150
    #~ space.add(cannon_shape)

    ball_body,ball_shape = create_ball()
    pig_body,pig_shape = create_pig()
    #~ ball_shape.ignore_draw=True
    


    while running:
        start=Vec2d (100,300)
        for event in pygame.event.get():
            mp=from_pygame( (pygame.mouse.get_pos()), screen )
            if event.type == QUIT or \
                event.type == KEYDOWN and (event.key in [K_ESCAPE, K_q]):
                running = False
            elif  pygame.mouse.get_pressed()[1]:
                pig_body.position=mp
                space.add(pig_body)
                space.add(pig_shape)
                pig_body, pig_shape = create_pig()
                print len(space.shapes)
                break
            elif event.type == pygame.MOUSEMOTION and  pygame.mouse.get_pressed()[0]:
                cannon_body.position =Vec2d (mp[0],mp[1])
                print cannon_body.position
            elif event.type == pygame.MOUSEBUTTONUP and  pygame.mouse.get_pressed()[1]==False:
                diff =  -1*(Vec2d(mp)  - start)
                print("abs="+str(diff))
                cannon_body.position =start
                
                impulse = diff* 75
                ball_body.apply_impulse(impulse.rotated(ball_body.angle))

                space.add(ball_body)
                
                #~ ball_shape.ignore_draw=True
                ball_body, ball_shape = create_ball()
                space.add(ball_shape)
                
                
        mouse_position = from_pygame( Vec2d(pygame.mouse.get_pos()), screen )
        cannon_body.angle = (mouse_position - cannon_body.position).angle
        # move the unfired ball together with the cannon
        ball_body.position = cannon_body.position 
        ball_body.angle = cannon_body.angle


        ### Clear screen
        screen.fill(pygame.color.THECOLORS["white"])

        ### Draw stuff
        background = os.path.join("bgsl.png")
        background_surface = pygame.image.load(background)
        screen.blit(background_surface, (0,0)) 
        
        #~ animation_offset = 32*0
        col=[]
        pigs=[]
        for x in space.shapes:
            if x.body.mass>1:
                col.append(x)
            else:
                pigs.append(x)
        #~ print len(col)
        for x in col:
            tem=x.body.position
            tem=list(tem)
            pos=tem[0]-20,tem[1]+20
            #~ position=5
            #~ print (s)
            screen.blit(img, to_pygame(pos, screen))
        for x in pigs:
            tem=x.body.position
            tem=list(tem)
            pos=tem[0]-30,tem[1]+20
            #~ position=5
            #~ print (s)
            screen.blit(pigimg, to_pygame(pos, screen))
        draw_space(screen, space)


        pygame.display.flip()

        ### Update physics
        fps = 60
        dt = 1./fps
        space.step(dt)
        

        clock.tick(fps)
예제 #10
0
 def update_pygame(self):
     self.screen.fill( pygame.color.THECOLORS[ "black" ] )
     draw_space( self.screen, self.sim.space )
     pygame.display.flip()
예제 #11
0
def main():

    ### PyGame init
    pygame.init()
    screen = pygame.display.set_mode((width,height)) 

    clock = pygame.time.Clock()
    running = True
    font = pygame.font.SysFont("Arial", 16)
    sound = pygame.mixer.Sound("sfx.wav")
    img = pygame.image.load("xmasgirl1.png")
    
    ### Physics stuff
    space = pymunk.Space()   
    space.gravity = 0,-1000
    # box walls 
    static = [pymunk.Segment(space.static_body, (10, 50), (300, 50), 5)
                , pymunk.Segment(space.static_body, (300, 50), (325, 50), 5)
                , pymunk.Segment(space.static_body, (325, 50), (350, 50), 5)
                , pymunk.Segment(space.static_body, (350, 50), (375, 50), 5)
                , pymunk.Segment(space.static_body, (375, 50), (680, 50), 5)
                , pymunk.Segment(space.static_body, (680, 50), (680, 370), 5)
                , pymunk.Segment(space.static_body, (680, 370), (10, 370), 5)
                , pymunk.Segment(space.static_body, (10, 370), (10, 50), 5)
                ]  
    static[1].color = pygame.color.THECOLORS['red']
    static[2].color = pygame.color.THECOLORS['green']
    static[3].color = pygame.color.THECOLORS['red']
    
    # rounded shape
    rounded = [pymunk.Segment(space.static_body, (500, 50), (520, 60), 5)
                , pymunk.Segment(space.static_body, (520, 60), (540, 80), 5)
                , pymunk.Segment(space.static_body, (540, 80), (550, 100), 5)
                , pymunk.Segment(space.static_body, (550, 100), (550, 150), 5)
                ]
                
    # static platforms
    platforms = [pymunk.Segment(space.static_body, (170, 50), (270, 150), 5)
                #, pymunk.Segment(space.static_body, (270, 100), (300, 100), 5)
                , pymunk.Segment(space.static_body, (400, 150), (450, 150), 5)
                , pymunk.Segment(space.static_body, (400, 200), (450, 200), 5)
                , pymunk.Segment(space.static_body, (220, 200), (300, 200), 5)
                , pymunk.Segment(space.static_body, (50, 250), (200, 250), 5)
                , pymunk.Segment(space.static_body, (10, 370), (50, 250), 5)
                ]
    
    for s in static + platforms+rounded:
        s.friction = 1.
        s.group = 1
    space.add(static, platforms+rounded)
    
    # moving platform
    platform_path = [(650,100),(600,200),(650,300)]
    platform_path_index = 0
    platform_body = pymunk.Body(pymunk.inf, pymunk.inf)
    platform_body.position = 650,100
    s = pymunk.Segment(platform_body, (-25, 0), (25, 0), 5)
    s.friction = 1.
    s.group = 1
    s.color = pygame.color.THECOLORS["blue"]
    space.add(s)
    
    # pass through platform
    passthrough = pymunk.Segment(space.static_body, (270, 100), (320, 100), 5)
    passthrough.color = pygame.color.THECOLORS["yellow"]
    passthrough.friction = 1.
    passthrough.collision_type = 2
    passthrough.layers = passthrough.layers ^ 0b1000
    space.add(passthrough)
    
    def passthrough_handler(space, arbiter):
        if arbiter.shapes[0].body.velocity.y < 0:
            return True
        else:
            return False
            
    space.add_collision_handler(1,2, begin=passthrough_handler)
    
    
    # player
    body = pymunk.Body(5, pymunk.inf)
    body.position = 100,100
    
    
    head = pymunk.Circle(body, 10, (0,5))
    head2 = pymunk.Circle(body, 10, (0,13))
    feet = pymunk.Circle(body, 10, (0,-5))

    head.layers = head2.layers = 0b1000
    feet.collision_type = 1
    feet.ignore_draw = head.ignore_draw = head2.ignore_draw = True
    
    space.add(body, head, feet,head2)
    direction = 1
    remaining_jumps = 2
    landing = {'p':Vec2d.zero(), 'n':0}
    frame_number = 0
    
    landed_previous = False
    
    while running:
        
        grounding = {
            'normal' : Vec2d.zero(),
            'penetration' : Vec2d.zero(),
            'impulse' : Vec2d.zero(),
            'position' : Vec2d.zero(),
            'body' : None
        }
        # find out if player is standing on ground
        
                
        def f(arbiter):
            n = -arbiter.contacts[0].normal
            if n.y > grounding['normal'].y:
                grounding['normal'] = n
                grounding['penetration'] = -arbiter.contacts[0].distance
                grounding['body'] = arbiter.shapes[1].body
                grounding['impulse'] = arbiter.total_impulse
                grounding['position'] = arbiter.contacts[0].position
        body.each_arbiter(f)
            
        well_grounded = False
        if grounding['body'] != None and abs(grounding['normal'].x/grounding['normal'].y) < feet.friction:
            well_grounded = True
            remaining_jumps = 2
    
        ground_velocity = Vec2d.zero()
        if well_grounded:
            ground_velocity = grounding['body'].velocity
    
        for event in pygame.event.get():
            if event.type == QUIT or \
                event.type == KEYDOWN and (event.key in [K_ESCAPE, K_q]):  
                running = False
            elif event.type == KEYDOWN and event.key == K_p:
                pygame.image.save(screen, "platformer.png")

            elif event.type == KEYDOWN and event.key == K_d:
                feet.ignore_draw = not feet.ignore_draw
                head.ignore_draw = not head.ignore_draw
                head2.ignore_draw = not head2.ignore_draw
                
            elif event.type == KEYDOWN and event.key == K_UP:
                if well_grounded or remaining_jumps > 0:                    
                    jump_v = math.sqrt(2.0 * JUMP_HEIGHT * abs(space.gravity.y))
                    body.velocity.y = ground_velocity.y + jump_v;
                    remaining_jumps -=1
            elif event.type == KEYUP and event.key == K_UP:                
                body.velocity.y = min(body.velocity.y, JUMP_CUTOFF_VELOCITY)
                
        # Target horizontal velocity of player
        target_vx = 0
        
        if body.velocity.x > .01:
            direction = 1
        elif body.velocity.x < -.01:
            direction = -1
        
        keys = pygame.key.get_pressed()
        if (keys[K_LEFT]):
            direction = -1
            target_vx -= PLAYER_VELOCITY
        if (keys[K_RIGHT]):
            direction = 1
            target_vx += PLAYER_VELOCITY
        if (keys[K_DOWN]):
            direction = -3
            
        feet.surface_velocity = target_vx,0

        
        if grounding['body'] != None:
            feet.friction = -PLAYER_GROUND_ACCEL/space.gravity.y
            head.friciton = HEAD_FRICTION
        else:
            feet.friction,head.friction = 0,0
        
        # Air control
        if grounding['body'] == None:
            body.velocity.x = cpflerpconst(body.velocity.x, target_vx + ground_velocity.x, PLAYER_AIR_ACCEL*dt)
        
        body.velocity.y = max(body.velocity.y, -FALL_VELOCITY) # clamp upwards as well?
        
        # Move the moving platform
        destination = platform_path[platform_path_index]
        current = Vec2d(platform_body.position)
        distance = current.get_distance(destination)
        if distance < PLATFORM_SPEED:
            platform_path_index += 1
            platform_path_index = platform_path_index % len(platform_path)
            t = 1
        else:
            t = PLATFORM_SPEED / distance
        new = current.interpolate_to(destination, t)
        platform_body.position = new
        platform_body.velocity = (new - current) / dt
        
        ### Clear screen
        screen.fill(pygame.color.THECOLORS["black"])
        
        ### Helper lines
        for y in [50,100,150,200,250,300]:
            color = pygame.color.THECOLORS['darkgrey']
            pygame.draw.line(screen, color, (10,y), (680,y), 1)
        
        ### Draw stuff
        draw_space(screen, space)
        
        if feet.ignore_draw:
            direction_offset = 48+(1*direction+1)/2 * 48
            if grounding['body'] != None and abs(target_vx) > 1:
                animation_offset = 32 * (frame_number / 8 % 4)
            elif grounding['body'] is None:
                animation_offset = 32*1
            else:
                animation_offset = 32*0
            position = body.position +(-16,28)
            screen.blit(img, to_pygame(position, screen), (animation_offset, direction_offset, 32, 48))

        # Did we land?
        if abs(grounding['impulse'].y) / body.mass > 200 and not landed_previous:
            sound.play()
            landing = {'p':grounding['position'],'n':5}
            landed_previous = True
        else:
            landed_previous = False
        if landing['n'] > 0:
            pygame.draw.circle(screen, pygame.color.THECOLORS['yellow'], to_pygame(landing['p'], screen), 5)
            landing['n'] -= 1
        
        # Info and flip screen
        screen.blit(font.render("fps: " + str(clock.get_fps()), 1, THECOLORS["white"]), (0,0))
        screen.blit(font.render("Move with Left/Right, jump with Up, press again to double jump", 1, THECOLORS["darkgrey"]), (5,height - 35))
        screen.blit(font.render("Press D to toggle sprite draw, ESC or Q to quit", 1, THECOLORS["darkgrey"]), (5,height - 20))
        
       
        pygame.display.flip()
        frame_number += 1
        ### Update physics
        
        space.step(dt)
        
        clock.tick(fps)