Skip to content Skip to sidebar Skip to footer

How Do I Add A Rubber Band For Mouse Dragging In Pygame?

I made the second code separate from the first and I wanted to implement the same functionality as the second which is to draw a line with the mouse I made the second code separate

Solution 1:

If you do not want to draw lines with a click and click, you have to save the starting position with the first click and end the line with the second click. The lines have to be stored to a list. Add a list of liens and a variable line_start and initialize it by None:

lines = []
line_start = None

Set the start with the first click and end the line with the second click (MOUSEBUTTONDOWN). Add the finished line to the list of lines:

if e.type == pygame.MOUSEBUTTONDOWN:
        # [...]if line_start:
            lines.append((line_start, e.pos))
            line_start = Noneelse:
            line_start = e.pos

Draw the lines in a loop. If a line is started bunt not finished draw a line form the start position to the current mouse position:

for line in lines:
    pygame.draw.line(screen, pygame.Color('lawngreen'), *line)
if line_start:
    pygame.draw.line(screen, pygame.Color('lawngreen'), line_start, pygame.mouse.get_pos())

Minimal example:

import pygame

pygame.init()
SCREEN_WIDTH = 1500
SCREEN_HEIGHT = 750
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()

background = pygame.image.load(r'C:\Users\ga-sa\Downloads\honeycomb.png')
background = pygame.transform.scale(BACKGROUND, (SCREEN_WIDTH, SCREEN_HEIGHT))

img1 = pygame.image.load(r"C:\Users\ga-sa\Downloads\As.png")
img2 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsXOR.png")
img3 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsNOT.png")
img4 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsAND.png")

images = [img1, img2, img3, img4]

current_image = -1
img_rects = [images[i].get_rect(topleft=(20 + 80 * i, 20)) for i inrange(len(images))]
img_angles = [0for _ inrange(len(images))]

lines = []
line_start = None

LeftButton = 0while1:
    clock.tick(60)
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            exit(0)

        if e.type == pygame.MOUSEBUTTONDOWN:
            mouse_rect = pygame.Rect(e.pos, (1, 1))
            current_image = mouse_rect.collidelist(img_rects)
            if line_start:
                lines.append((line_start, e.pos))
                line_start = Noneelse:
                line_start = e.pos

        if e.type == pygame.MOUSEMOTION:
            if e.buttons[LeftButton]:
                rel = e.rel
                if0 <= current_image < len(images):
                    img_rects[current_image].x += rel[0]
                    img_rects[current_image].y += rel[1]

    keys = pygame.key.get_pressed()
    if0 <= current_image < len(img_angles):
        if keys[pygame.K_RIGHT]:
            img_angles[current_image] -= 1if keys[pygame.K_LEFT]:
            img_angles[current_image] += 1

    screen.blit(background,(0,0))

    for line in lines:
        pygame.draw.line(screen, pygame.Color('lawngreen'), *line)
    if line_start:
        pygame.draw.line(screen, pygame.Color('lawngreen'), line_start, pygame.mouse.get_pos())

    for i inrange(len(images)):
        rotated_image = pygame.transform.rotate(images[i], img_angles[i])
        rotated_rect = rotated_image.get_rect(center = img_rects[i].center)
        screen.blit(rotated_image, rotated_rect)

    pygame.display.flip()


If you want to draw a rubber line while dragging an icon, you must save the start of the line. Add a variable line_start and initialize it by `None:

line_start = None

Set the start position when the mouse is pressed (MOUSEBUTTONDOWN):

if e.type == pygame.MOUSEBUTTONDOWN:
    mouse_rect = pygame.Rect(e.pos, (1, 1))
    current_image = mouse_rect.collidelist(img_rects)
    line_start = e.pos

Set the line_start = None when the mouse is released (MOUSEBUTTONUP):

if e.type == pygame.MOUSEBUTTONUP:
    line_start = None

If line_start is set, draw a line from the start position ot the current mouse position:

if line_start:
    pygame.draw.line(screen, pygame.Color('lawngreen'), line_start, pygame.mouse.get_pos())

Minimal example:

import pygame

pygame.init()
SCREEN_WIDTH = 1500
SCREEN_HEIGHT = 750
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()

background = pygame.image.load(r'C:\Users\ga-sa\Downloads\honeycomb.png')
background = pygame.transform.scale(BACKGROUND, (SCREEN_WIDTH, SCREEN_HEIGHT))

img1 = pygame.image.load(r"C:\Users\ga-sa\Downloads\As.png")
img2 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsXOR.png")
img3 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsNOT.png")
img4 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsAND.png")

images = [img1, img2, img3, img4]

current_image = -1
img_rects = [images[i].get_rect(topleft=(20 + 80 * i, 20)) for i inrange(len(images))]
img_angles = [0for _ inrange(len(images))]

line_start = None

LeftButton = 0while1:
    clock.tick(60)
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            exit(0)

        if e.type == pygame.MOUSEBUTTONDOWN:
            mouse_rect = pygame.Rect(e.pos, (1, 1))
            current_image = mouse_rect.collidelist(img_rects)
            line_start = e.pos

        if e.type == pygame.MOUSEBUTTONUP:
            line_start = Noneif e.type == pygame.MOUSEMOTION:
            if e.buttons[LeftButton]:
                rel = e.rel
                if0 <= current_image < len(images):
                    img_rects[current_image].x += rel[0]
                    img_rects[current_image].y += rel[1]

    keys = pygame.key.get_pressed()
    if0 <= current_image < len(img_angles):
        if keys[pygame.K_RIGHT]:
            img_angles[current_image] -= 1if keys[pygame.K_LEFT]:
            img_angles[current_image] += 1

    screen.blit(background,(0,0))

    if line_start:
        pygame.draw.line(screen, pygame.Color('lawngreen'), line_start, pygame.mouse.get_pos())

    for i inrange(len(images)):
        rotated_image = pygame.transform.rotate(images[i], img_angles[i])
        rotated_rect = rotated_image.get_rect(center = img_rects[i].center)
        screen.blit(rotated_image, rotated_rect)

    pygame.display.flip()


If you want to draw lines along the way the icons are dragged, you need a list of lines. Each line is a list of points:

lines = []

Start a new list when the mouse is pressed (MOUSEMOTION):

if e.type == pygame.MOUSEBUTTONDOWN:
    mouse_rect = pygame.Rect(e.pos, (1, 1))
    current_image = mouse_rect.collidelist(img_rects)
    lines.append([e.pos])                                 # <---

Add a point to the last line in the list of lines when the mouse is moved (MOUSEMOTION):

if e.type == pygame.MOUSEMOTION:
    if e.buttons[LeftButton]:
        rel = e.rel
        if0 <= current_image < len(images):
            img_rects[current_image].x += rel[0]
            img_rects[current_image].y += rel[1]
            lines[-1].append(e.pos)                      # <---

Draw the lines in a loop, unsing pygame.draw.lines:

for line in lines:
    iflen(line) > 1:
        pygame.draw.lines(screen, pygame.Color('lawngreen'), False, line)

If you want straight lines, you have to replace the 2nd point of the line with the new mouse position when you move the mouse:

while1:
    clock.tick(60)
    for e in pygame.event.get():
        # [...]if e.type == pygame.MOUSEMOTION:
            if e.buttons[LeftButton]:
                rel = e.rel
                if0 <= current_image < len(images):
                    img_rects[current_image].x += rel[0]
                    img_rects[current_image].y += rel[1]
                    
                    # lines[-1].append(e.pos)iflen(lines[-1]) < 2:
                        lines[-1].append(e.pos)
                    else:
                        lines[-1][1] = e.pos


Minimal example:

You can switch between the two implementations by changing the value of straight_lines.

import pygame

pygame.init()
SCREEN_WIDTH = 1500
SCREEN_HEIGHT = 750
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()

background = pygame.image.load(r'C:\Users\ga-sa\Downloads\honeycomb.png')
background = pygame.transform.scale(BACKGROUND, (SCREEN_WIDTH, SCREEN_HEIGHT))

img1 = pygame.image.load(r"C:\Users\ga-sa\Downloads\As.png")
img2 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsXOR.png")
img3 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsNOT.png")
img4 = pygame.image.load(r"C:\Users\ga-sa\Downloads\AssetsAND.png")

images = [img1, img2, img3, img4]

current_image = -1
img_rects = [images[i].get_rect(topleft=(20 + 80 * i, 20)) for i inrange(len(images))]
img_angles = [0for _ inrange(len(images))]

lines = []

# straight_lines = False 
straight_lines = True

LeftButton = 0while1:
    clock.tick(60)
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            exit(0)

        if e.type == pygame.MOUSEBUTTONDOWN:
            mouse_rect = pygame.Rect(e.pos, (1, 1))
            current_image = mouse_rect.collidelist(img_rects)
            lines.append([e.pos])

        if e.type == pygame.MOUSEMOTION:
            if e.buttons[LeftButton]:
                rel = e.rel
                if0 <= current_image < len(images):
                    img_rects[current_image].x += rel[0]
                    img_rects[current_image].y += rel[1]
                    
                    iflen(lines[-1]) < 2ornot straight_lines:
                        lines[-1].append(e.pos)
                    else:
                        lines[-1][1] = e.pos

    keys = pygame.key.get_pressed()
    if0 <= current_image < len(img_angles):
        if keys[pygame.K_RIGHT]:
            img_angles[current_image] -= 1if keys[pygame.K_LEFT]:
            img_angles[current_image] += 1

    screen.blit(background,(0,0))

    for line in lines:
        iflen(line) > 1:
            pygame.draw.lines(screen, pygame.Color('lawngreen'), False, line)
    
    for i inrange(len(images)):
        rotated_image = pygame.transform.rotate(images[i], img_angles[i])
        rotated_rect = rotated_image.get_rect(center = img_rects[i].center)
        screen.blit(rotated_image, rotated_rect)

    pygame.display.flip()

Post a Comment for "How Do I Add A Rubber Band For Mouse Dragging In Pygame?"