如何在PyGame中添加用于鼠标拖动的橡皮筋?

How do I add a rubber band for mouse dragging in PyGame?

我将第二个代码与第一个代码分开,我想实现与第二个代码相同的功能,即用鼠标画一条线我将第二个代码与第一个代码分开,我想实现相同的功能第二个功能是用鼠标画线

SCREEN_WIDTH = 1500
SCREEN_HEIGHT = 750
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 + 40 * i, 20)) for i in range(len(images))]
img_angles = [0 for _ in range(len(images))]

LeftButton = 0
while 1:
    for e in pygame.event.get():
        if e.type == 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 e.type == MOUSEMOTION:
            if e.buttons[LeftButton]:
                rel = e.rel
                if 0 <= current_image < len(images):
                    img_rects[current_image].x += rel[0]
                    img_rects[current_image].y += rel[1]

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

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

    for i in range(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()

如何在这段代码中添加一行代码?

def main()
    pygame.init()
    pygame.display.set_caption("Mouse Draw")
    surface = pygame.display.set_mode((800, 600))
    clock = pygame.time.Clock()
    rect = surface.get_rect()
    fps = 60

    line_surface = pygame.Surface(rect.size, pygame.SRCALPHA)
    line_surface.fill((0, 0, 0, 0))

    mouse_position = None
    display_line = None
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEMOTION:
                if mouse_position:
                    display_line = mouse_position, event.pos
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    if mouse_position:
                        pygame.draw.line(line_surface, pygame.Color("red"), mouse_position, event.pos)
                        mouse_position = None
                        display_line = None
                    else:
                        mouse_position = event.pos

        surface.fill(pygame.Color('black'))
        surface.blit(line_surface, (0, 0))

        if display_line:
            pygame.draw.line(surface, pygame.Color('lawngreen'), *display_line)

        pygame.display.update()
        clock.tick(fps)
main ()

我想将 def main 放在第一个代码中,但我并不总是看到黑屏或出现错误,如果有人能帮助我,我将不胜感激。 事实上我想加入这两个代码,但我不知道如何调整以适应第一个

如果不想点点画线,第一次点保存起始位置,第二次点点结束线。这些行必须存储到列表中。添加一个留置权列表和一个变量 line_start 并通过 None:

初始化它
lines = []
line_start = None

第一次点击开始,第二次点击结束 (MOUSEBUTTONDOWN)。将完成的行添加到行列表中:

if e.type == pygame.MOUSEBUTTONDOWN:
        # [...]

        if line_start:
            lines.append((line_start, e.pos))
            line_start = None
        else:
            line_start = e.pos

循环绘制线条。如果一条线开始短打未完成从开始位置到当前鼠标位置绘制一条线:

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

最小示例:

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 in range(len(images))]
img_angles = [0 for _ in range(len(images))]

lines = []
line_start = None

LeftButton = 0
while 1:
    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 = None
            else:
                line_start = e.pos

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

    keys = pygame.key.get_pressed()
    if 0 <= current_image < len(img_angles):
        if keys[pygame.K_RIGHT]:
            img_angles[current_image] -= 1
        if 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 in range(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()


如果要在拖动图标的同时绘制橡皮线,必须保存线条的起点。添加一个变量line_start并通过`None:

初始化
line_start = None

设置鼠标按下时的起始位置(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

设置鼠标松开时line_start = None(MOUSEBUTTONUP):

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

如果设置了line_start,从当前鼠标位置开始画一条线:

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

最小示例:

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 in range(len(images))]
img_angles = [0 for _ in range(len(images))]

line_start = None

LeftButton = 0
while 1:
    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 = None

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

    keys = pygame.key.get_pressed()
    if 0 <= current_image < len(img_angles):
        if keys[pygame.K_RIGHT]:
            img_angles[current_image] -= 1
        if 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 in range(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()


如果你想沿着拖动图标的方式绘制线条,你需要一个线条列表。每行是一个点列表:

lines = []

按下鼠标时开始一个新列表(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])                                 # <---

鼠标移动时在行列表的最后一行添加一个点(MOUSEMOTION):

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

循环画线,不唱 pygame.draw.lines:

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

如果你想要直线,你必须在移动鼠标时用新的鼠标位置替换直线的第二个点:

while 1:
    clock.tick(60)
    for e in pygame.event.get():
        # [...]

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


最小示例:

您可以通过更改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 in range(len(images))]
img_angles = [0 for _ in range(len(images))]

lines = []

# straight_lines = False 
straight_lines = True

LeftButton = 0
while 1:
    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
                if 0 <= current_image < len(images):
                    img_rects[current_image].x += rel[0]
                    img_rects[current_image].y += rel[1]
                    
                    if len(lines[-1]) < 2 or not straight_lines:
                        lines[-1].append(e.pos)
                    else:
                        lines[-1][1] = e.pos

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

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

    for line in lines:
        if len(line) > 1:
            pygame.draw.lines(screen, pygame.Color('lawngreen'), False, line)
    
    for i in range(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()