Example #1
0
 def draw_cg(self):
     """Draw the center of gravity."""
     screen = pygame.display.get_surface()
     for b in App.current.space.bodies:
         cg = b.position + b.center_of_gravity
         p = to_pygame(cg, screen)
         pygame.draw.circle(screen, BLUE, p, 5, 1)
Example #2
0
    def DrawEverything(self,flag=0):
        ### Write Everything On The Game Window ###
        img = pygame.image.load("./assets/intel.jpg")
        x, y = 580,550
        AdjustedImagePosition = (x-50,y+50)
        screen.blit(img,to_pygame(AdjustedImagePosition,screen))

        if(flag==0 and self.DetectCrash == 0):
            (self.BotRect.x,self.BotRect.y) = self.Bot.position[0],600-self.Bot.position[1]
            self.CircleRect = pygame.draw.circle(screen, (169,169,169), (self.BotRect.x,self.BotRect.y), 20, 0)
        ## If Collision Detected Draw Green
        elif(flag==0 and self.DetectCrash >= 1):
            (self.BotRect.x,self.BotRect.y) = self.Bot.position[0],600-self.Bot.position[1]
            self.CircleRect = pygame.draw.circle(screen, (0,255,0), (self.BotRect.x,self.BotRect.y), 20, 0)
        ## If Collision Detected Draw Red
        else:
            (self.BotRect.x,self.BotRect.y) = self.Bot.position[0],600-self.Bot.position[1]
            self.CircleRect = pygame.draw.circle(screen, (255,0,0), (self.BotRect.x,self.BotRect.y), 20, 0)
        img = pygame.image.load("./assets/spherelight.png")
        offset = Vec2d(img.get_size()) / 2.
        x, y =  self.Bot.position
        y = 600.0 -y
        AdjustedImagePosition = (x,y) - offset
        screen.blit(img,AdjustedImagePosition)
        for ob in self.WallRects:
            pygame.draw.rect(screen, (169,169, 169), ob)
 def draw_everything(self,flag=0):
     
     img = pygame.image.load("./assets/intel.jpg")
     x, y = 580,550
     adjusted_img_position = (x-50,y+50)
     screen.blit(img,to_pygame(adjusted_img_position,screen))
     
     if(flag==0 and self.detect_crash == 0):
         (self.bot_rect.x,self.bot_rect.y) = self.bot.position[0],600-self.bot.position[1]
         self.circle_rect = pygame.draw.circle(screen, (169,169,169), (self.bot_rect.x,self.bot_rect.y), 20, 0)
     
     elif(flag==0 and self.detect_crash >= 1):
         
         (self.bot_rect.x,self.bot_rect.y) = self.bot.position[0],600-self.bot.position[1]
         self.circle_rect = pygame.draw.circle(screen, (0,255,0), (self.bot_rect.x,self.bot_rect.y), 20, 0)
     
     else:
         (self.bot_rect.x,self.bot_rect.y) = self.bot.position[0],600-self.bot.position[1]
         self.circle_rect = pygame.draw.circle(screen, (255,0,0), (self.bot_rect.x,self.bot_rect.y), 20, 0)
     
     img = pygame.image.load("./assets/spherelight.png")
     offset = Vec2d(img.get_size()) / 2.
     x, y =  self.bot.position
     y = 600.0 -y
     
     adjusted_img_position = (x,y) - offset
     screen.blit(img,adjusted_img_position)
     
     for ob in self.wall_rects:
         pygame.draw.rect(screen, (169,169, 169), ob)
Example #4
0
 def hitbox(self, attack, pos, radius, damage, source):
     numHit = 0
     pygame.draw.circle(self.screen, pygame.color.THECOLORS['pink'], to_pygame(pos, self.screen), radius)
     for entity in self.entities:
         if entity != source:
             if pos.get_distance(entity.position) < radius:
                 numHit += 1
                 entity.onDamaged(attack, damage)
     return numHit
Example #5
0
 def draw(self, screen, tile_id, position):
     if not tile_id:
         return  # There was nothing to be drawn
     tile_id -= 1  # we're 1-indexed in Tiled
     tiles_wide = self.img.get_width() // self.tile_width
     source_x = (tile_id % tiles_wide) * self.tile_width
     source_y = (tile_id // tiles_wide) * self.tile_height
     screen.blit(self.img, to_pygame(position, screen),
                 (source_x, source_y, self.tile_width, self.tile_height))
Example #6
0
 def draw(self, screen, tile_id, position):
     if not tile_id:
         return  # There was nothing to be drawn
     tile_id -= 1  # we're 1-indexed in Tiled
     tiles_wide = self.img.get_width() // self.tile_width
     source_x = (tile_id % tiles_wide) * self.tile_width
     source_y = (tile_id // tiles_wide) * self.tile_height
     screen.blit(self.img, to_pygame(position, screen),
                 (source_x, source_y, self.tile_width, self.tile_height))
def updateCamera(screen, game, center, space, draw_options):
    x, y = screen.get_size()
    c_x, c_y = pygame_util.to_pygame(center, game)
    dest = max(c_x - x // 2, 0), max(c_y - y // 2, 0)
    print((x, y), (c_x, c_y), dest)
    screen.fill((0, 0, 0))
    graph.drawStars(screen, center)
    game.blit(screen, dest)
    space.debug_draw(draw_options)
    screen.blit(game, (0, 0), pg.Rect(dest[0], dest[1], x, y))
Example #8
0
    def draw_polygon(self, verts, radius, outline_color, fill_color):
        ps = [ppu.to_pygame(v, self.surface) for v in verts]
        ps += [ps[0]]

        pygame.draw.polygon(self.surface, fill_color, ps)

        if radius < 1 and False:
            pygame.draw.lines(self.surface, outline_color, False, ps)
        else:
            pygame.draw.lines(self.surface, outline_color, False, ps, int(radius * 2))
Example #9
0
	def draw_build_hint(self, graph, r=8, linewidth=1):
		''' Метод для рисования подсказки на экране во время строительства.

		Подсказка разная для двух случаев (аналогичны случаям при строительстве, см. метод build в ShapeCreator):
		Если подходящие для строительства узлы не соседи друг другу, то рисуем линию между ними.
		Если подходящие для строительства узлы соседи друг другу, то рисуем круг, там где будет новый узел, и 2 линии.
		
		Аргументы:
		----------
		graph : Graph
			Объект, который даст нам доступ к фиксированным Ду, подходящим для строительства.
		r : int
			Радиус рисуемого круга.
		'''
		if len(graph.fixed_doo_for_build) == 2:
			if graph.fixed_doo_for_build[0] in graph[graph.fixed_doo_for_build[1]]:
				pg.draw.line(self, (0, 200, 0), to_pygame(graph.fixed_doo_for_build[0].body.position, self), to_pygame(self.shape_being_dragged.body.position, self), linewidth)
				pg.draw.line(self, (0, 200, 0), to_pygame(graph.fixed_doo_for_build[1].body.position, self), to_pygame(self.shape_being_dragged.body.position, self), linewidth)
				pg.draw.circle(self, (0, 200, 0), to_pygame(self.shape_being_dragged.body.position, self), r)
			else:
				pg.draw.line(self, (0, 200, 0), to_pygame(graph.fixed_doo_for_build[0].body.position, self), to_pygame(graph.fixed_doo_for_build[1].body.position, self))
  def draw(self, DEBUG):
    for s in self.soldiers: s.draw(DEBUG)

    if DEBUG:
      # DRAW CONVEX HULL
      inf_simplices, fight_simplices = self.formation.get_hulls(for_draw=True)    
      for p1, p2 in inf_simplices:
        pygame.draw.line(
          self.game.screen, (0, 0, 0), (p1[0], p2[0]), (p1[1], p2[1])
        )
      for p1, p2 in fight_simplices:
        pygame.draw.line(
          self.game.screen, (0, 0, 0), (p1[0], p2[0]), (p1[1], p2[1])
        )
        
      
      # DRAW DIRECTION
      center, direction = self.pos_direction
      p1 = to_pygame(center, self.game.screen)
      p2 = to_pygame(center + direction*30, self.game.screen)
      pygame.draw.aalines(self.game.screen, GREEN, False, [p1,p2], 10)
Example #11
0
    def draw(self, DEBUG):
        pos = to_pygame(self.body.position, self.game.screen)
        pygame.draw.circle(self.game.screen, self.col, pos, self.radius)
        if self.unit.is_selected:
            pygame.draw.circle(self.game.screen, BLACK, pos, self.radius - 1)

        if DEBUG:
            # if self.unit.is_selected:
            #   pygame.draw.circle(self.game.screen, BLACK, pos, self.radius - 1)

            # DRAW ARROW TO TARGET
            p1 = to_pygame(self.body.position, self.game.screen)
            p2 = to_pygame(self.target_position, self.game.screen)
            pygame.draw.aalines(self.game.screen, BLUE, False, [p1, p2])

            # DRAW VELOCITY
            # p1 = to_pygame(self.body.position, self.game.screen)
            # p2 = to_pygame(self.body.position + self.body.velocity.normalized() * 100, self.game.screen)
            # pygame.draw.aalines(self.game.screen, BLUE, False, [p1,p2])

            # DRAW COORDINATES
            # draw_text(f"{self.coord[0]},{self.coord[1]}", self.game.screen, self.game.font, self.body.position,
            #           np.pi)
            pass
Example #12
0
	def draw_circle(self, r=12, width=1):
		''' Метод для рисования окружности около Ду, находящегося под курсором мыши.

		Перед рисованием находим координаты центра Ду в координатной системе поверхности world.
		Так как окружность рисуем именно на этой поверхности.

		Аргументы:
		----------
		r : int
			Радиус окружности в пикселях.
		width : int
			Толщина окружности в пикселях.
		'''
		if self.free_doo_under_cursor != None:
			doo_center = to_pygame(self.free_doo_under_cursor.body.position, self)
			pg.draw.circle(self, [200,0,0], doo_center, r, width)
Example #13
0
    def draw(self, screen, camera):
        # match sprite to the physics object
        position = self.body.position - camera + SCREEN_HALF
        position = Vec2d(to_pygame(position, screen))

        # play different animations depending on what's going on
        # TODO: These are all screwed up
        flip = self.current_facing == self.left_key

        if self.health <= 0:
            self.death_sequence.draw(screen, position, flip)
            if self.death_sequence.done:
                # respawn
                self.health = self.max_health
                self.body.position = Vec2d(100, 100)
        elif self.landed and abs(self.feet.surface_velocity.x) > 1:
            # walking
            self.walk_loop.draw(screen, position, flip)
        elif self.landed:
            # idle
            self.idle_loop.draw(screen, position, flip)
        elif self.remaining_jumps > 0:
            # falling
            self.jump_loop.draw(screen, position, flip)
        elif self.remaining_jumps == 0:
            # spinning
            self.spin_loop.draw(screen, position, flip)
        else:
            # I dunno what else to do
            self.idle_loop.draw(screen, position, flip)

        # Draw health bar
        health_percent = max(float(self.health) / self.max_health, 0)
        if health_percent:
            rect = (position.x, position.y - 35, 30 * health_percent, 5)
            pygame.draw.rect(screen, (255, 0, 0, 0), rect)

        # Did we land?
        if self.landed_hard:
            self.fall_sound.play()

        # Draw our bullets
        for bullet in self.bullets:
            bullet.draw(screen, camera)
Example #14
0
    def get_hulls(self, for_draw=False):
        points = np.array(self.unit.get_soldiers_pos(False))
        if for_draw:
            for i in range(len(points)):
                points[i] = to_pygame(list(points[i]), self.unit.game.screen)
        center = points.mean(0)
        inf_hull_ = ConvexHull(points)
        inf_hull = Polygon(points[inf_hull_.vertices])

        expanded = []
        for ind1, ind2 in zip(
                inf_hull_.vertices,
                inf_hull_.vertices[1:].tolist() + [inf_hull_.vertices[0]]):
            v1 = Vec2d(list(points[ind1]))
            v2 = Vec2d(list(points[ind2]))

            p_norm = (v1 - v2).perpendicular_normal() * self.melee_range
            if (v1 + p_norm - center).length < (v1 - center).length:
                p_norm = -p_norm
            v1 = v1 + p_norm
            v2 = v2 + p_norm

            expanded.append(v1)
            expanded.append(v2)

        expanded = np.array([list(p) for p in expanded])

        hull = ConvexHull(expanded)
        fight_hull = Polygon(expanded[hull.vertices])

        if not for_draw:  # we only need polygons if we are not drawing
            return inf_hull, fight_hull

        inf_simplices = []
        for simplex in inf_hull_.simplices:
            inf_simplices.append(
                (points[simplex, 0].tolist(), points[simplex, 1].tolist()))
        fight_simplices = []
        for simplex in hull.simplices:
            fight_simplices.append(
                (expanded[simplex, 0].tolist(), expanded[simplex, 1].tolist()))
        return inf_simplices, fight_simplices
Example #15
0
    def draw(self, screen, camera):
        # match sprite to the physics object
        position = self.body.position - camera + SCREEN_HALF
        position = Vec2d(to_pygame(position, screen))

        # play different animations depending on what's going on
        # TODO: These are all screwed up
        flip = self.current_facing == self.left_key

        if self.health <= 0:
            self.death_sequence.draw(screen, position, flip)
        elif self.landed and abs(self.feet.surface_velocity.x) > 1:
            # walking
            self.walk_loop.draw(screen, position, flip)
        elif self.landed:
            # idle
            self.idle_loop.draw(screen, position, flip)
        elif self.remaining_jumps > 0:
            # falling
            self.jump_loop.draw(screen, position, flip)
        elif self.remaining_jumps == 0:
            # spinning
            self.spin_loop.draw(screen, position, flip)
        else:
            # I dunno what else to do
            self.idle_loop.draw(screen, position, flip)

        # Draw health bar
        health_percent = max(float(self.health) / self.max_health, 0)
        if health_percent:
            rect = (position.x, position.y - 35, 30 * health_percent, 5)
            pygame.draw.rect(screen, (255, 0, 0, 0), rect)

        # Did we land?
        if self.landed_hard:
            self.fall_sound.play()

        # Draw our bullets
        for bullet in self.bullets:
            bullet.draw(screen, camera)
Example #16
0
 def draw_dot(self, size, pos, color):
     p = ppu.to_pygame(pos, self.surface)
     pygame.draw.circle(self.surface, color, p, int(size), 0)
        motor_speed -= acc * dt
        motor_speed = max(motor_speed, -max_speed)
    elif keys[K_a]:
        motor_speed += acc * dt
        motor_speed = min(motor_speed, max_speed)
    else:
        sign = math.copysign(1, motor_speed)
        motor_speed += (dec * dt) * -sign
        if math.copysign(1, motor_speed) != sign:
            motor_speed = 0

    for m in motors:
        m.rate = motor_speed

    space.step(dt)
    scroll = Vec2d(screen_rect.center) - to_pygame(car.position, screen)

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

    for body, shape in sprites:
        if isinstance(shape, pymunk.Circle):
            screen_center = to_pygame(body.position, screen) + scroll
            pygame.draw.circle(screen, (0, 0, 0), screen_center, shape.radius)
            edge = to_pygame(
                body.position + Vec2d(shape.radius, 0).rotated(body.angle),
                screen) + scroll
            pygame.draw.line(screen, (255, 255, 255), screen_center, edge)
        elif isinstance(shape, pymunk.Poly):
            vertices = shape.get_vertices()
            transformed_vertices = [
                v.rotated(body.angle) + body.position for v in vertices
Example #18
0
    def draw_fat_segment(self, a, b, radius, outline_color, fill_color):
        p1 = ppu.to_pygame(a, self.surface)
        p2 = ppu.to_pygame(b, self.surface)

        r = int(max(1, radius * 2))
        pygame.draw.lines(self.surface, fill_color, False, [p1, p2], r)
Example #19
0
    def draw_segment(self, a, b, color):
        p1 = ppu.to_pygame(a, self.surface)
        p2 = ppu.to_pygame(b, self.surface)

        pygame.draw.aalines(self.surface, color, False, [p1, p2])
Example #20
0
    def draw_circle(self, pos, angle, radius, outline_color, fill_color):
        p = ppu.to_pygame(pos, self.surface)

        pygame.draw.circle(self.surface, fill_color, p, int(radius), 0)
                trajectory = np.array(game.mouse_traj)
                trajectory = trajectory + np.random.randn(len(trajectory),
                                                          2) * 0.0001
                selected_unit.set_spline_formation_trajectory(
                    start_dir, final_dir, trajectory, True)
                game.mouse_traj = []

    game.draw(DEBUG)
    for u in units:
        u.draw(DEBUG)

    # for cur_traj_form in traj_form:
    if not selected_unit is None:
        traj_form = selected_unit.traj
        for i in range(len(traj_form) - 1):
            p1 = to_pygame(traj_form[i], game.screen)
            p2 = to_pygame(traj_form[i + 1], game.screen)
            pygame.draw.aalines(game.screen, (0, 0, 0), False, [p1, p2])

    pygame.display.flip()
    game.clock.tick(game.fps)

    if game.record:
        arr = pygame.surfarray.array3d(game.screen).swapaxes(1, 0)
        game.video.append(arr.astype(np.uint8))

# %%   OLD CODE FOR TRAJECTORY SPLINE NOW IMPLEMENTED IN THE UNIT

# angle_th = 50
# SPLINE_DISTANCE_POINT = 50
Example #22
0
 def draw(self, screen, camera):
     if not self.active:
         return
     position = to_pygame(self.body.position - camera + SCREEN_HALF, screen)
     pygame.draw.circle(screen, (0, 0, 0, 0), position, self.radius)
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)
Example #24
0
 def draw(self, screen, camera):
     if not self.active:
         return
     position = to_pygame(self.body.position - camera + SCREEN_HALF, screen)
     pygame.draw.circle(screen, (0, 0, 0, 0), position, self.radius)
Example #25
0
def main():
    pygame.init()
    pygame.font.init()
    screen = pygame.display.set_mode((width, height))
    clock = pygame.time.Clock()

    tunings = (27, 2, 10)
    pid = PID(*tunings,
              output_limits=(-8000, 8000),
              proportional_on_measurement=True)
    pid.sample_time = 1 / REFRESH

    draw_options = DrawOptions(screen)
    pymunk.pygame_util.positive_y_is_up = True

    font = pygame.font.SysFont('Lucida Console', 11)

    space = pymunk.Space()
    space.gravity = 0, -100
    x = random.randint(120, 380)
    drone = Drone((x, 450), space)
    ground = Ground(space)

    setpoint = 450
    ticks = 0
    while True:
        for event in pygame.event.get():
            # print(event)
            if event.type == pygame.QUIT:
                sys.exit(0)
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    setpoint += 5
                elif event.key == pygame.K_DOWN:
                    setpoint -= 5
                elif event.key == pygame.K_ESCAPE:
                    sys.exit(0)
                elif event.key == pygame.K_1:
                    p, i, d = pid.tunings
                    pid.tunings = (p + 0.5, i, d)
                elif event.key == pygame.K_q:
                    p, i, d = pid.tunings
                    pid.tunings = (p - 0.5, i, d)
                elif event.key == pygame.K_2:
                    p, i, d = pid.tunings
                    pid.tunings = (p, i + 0.5, d)
                elif event.key == pygame.K_w:
                    p, i, d = pid.tunings
                    pid.tunings = (p, i - 0.5, d)
                elif event.key == pygame.K_3:
                    p, i, d = pid.tunings
                    pid.tunings = (p, i, d + 0.5)
                elif event.key == pygame.K_e:
                    p, i, d = pid.tunings
                    pid.tunings = (p, i, d - 0.5)
            elif event.type == pygame.MOUSEBUTTONUP:
                setpoint = 600 - event.pos[1]
                # ticks=0

        screen.fill((0, 0, 0))

        error = drone.body.position.y - setpoint
        output = pid(error)

        space.debug_draw(draw_options)

        # if drone.shape.body.position.y < setpoint:
        if True:  # output > 0:
            # drone.shape.body.apply_force_at_local_point((0, 340), (0, 0))
            drone.shape.body.apply_force_at_local_point((0, output), (0, 0))
            c = to_pygame(drone.body.position, screen)
            pygame.draw.aaline(screen, (0, 128, 255, .75), c,
                               (c[0], c[1] - output // 10))

        pygame.draw.aaline(screen, (128, 255, 128, .125),
                           to_pygame((50, setpoint), screen),
                           to_pygame((600 - 50, setpoint), screen))

        # pygame.draw.aaline(screen, (255, 255, 255, .5), to_pygame((0,0), screen), to_pygame((100,100), screen))

        textsurface = font.render(
            f"pos:{drone.body.position.y:7.1f} set:{setpoint} error:{error:7.1f} o:{output:7.1f}",
            False, WHITE)
        screen.blit(textsurface, (10, 10))
        textsurface = font.render(
            f"pid:{['{:7.1f}'.format(p) for p in pid.components]}", False,
            WHITE)
        screen.blit(textsurface, (10, 25))
        textsurface = font.render(
            f"tun:{['{:7.1f}'.format(p) for p in pid.tunings]}", False, WHITE)
        screen.blit(textsurface, (10, 40))
        textsurface = font.render(f"ticks:{ticks}", False, WHITE)
        screen.blit(textsurface, (10, 55))

        space.step(1 / REFRESH)
        pygame.display.update()
        clock.tick(REFRESH)

        pygame.display.set_caption(f"{drone.body.position.y:.1f} {setpoint}")

        ticks += 1
def draw_text(t, screen, font, pos, angle, col=YELLOW):
  pos = to_pygame(pos, screen)
  text = font.render(t, True, col)
  text = pygame.transform.rotate(text, angle)
  text_rect = text.get_rect(center=pos)
  screen.blit(text, text_rect)
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(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)