3

I want to draw a line when mouse clicked and moving in Pygame framework, it will be a line if I move the mouse very slowly. However, if I move the mouse quickly, it's just incontinuous dots. The question is how to draw a continuous line when mouse move? Thanks in advance.

import pygame, sys
from pygame.locals import *

def main():
    pygame.init()

    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)

    mouse_position = (0, 0)
    drawing = False
    screen = pygame.display.set_mode((600, 800), 0, 32)
    screen.fill(WHITE)
    pygame.display.set_caption("ScratchBoard")

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == MOUSEMOTION:
                if (drawing):
                    mouse_position = pygame.mouse.get_pos()
                    pygame.draw.line(screen, BLACK, mouse_position, mouse_position, 1)
            elif event.type == MOUSEBUTTONUP:
                mouse_position = (0, 0)
                drawing = False
            elif event.type == MOUSEBUTTONDOWN:
                drawing = True

        pygame.display.update()

if __name__ == "__main__":
    main()
Jimmy
  • 45
  • 1
  • 7
  • It's still incontinuous after I correct the end position: elif event.type == MOUSEMOTION: if (drawing): start_position = event.pos end_position = (event.pos[0] + event.rel[0], event.pos[1] + event.rel[1]) – Jimmy May 24 '18 at 07:49

2 Answers2

2

By calling pygame.draw.line with the same argument (mouse_position) twice, you're not drawing a line, you're drawing a single pixel, because start_pos and end_pos are the same.

To get a contiguous line, you need to save the last position and draw a line between it and the next position, like this (changes are the lines with last_pos):

import pygame, sys
from pygame.locals import *

def main():
    pygame.init()

    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)

    mouse_position = (0, 0)
    drawing = False
    screen = pygame.display.set_mode((600, 800), 0, 32)
    screen.fill(WHITE)
    pygame.display.set_caption("ScratchBoard")

    last_pos = None

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == MOUSEMOTION:
                if (drawing):
                    mouse_position = pygame.mouse.get_pos()
                    if last_pos is not None:
                        pygame.draw.line(screen, BLACK, last_pos, mouse_position, 1)
                    last_pos = mouse_position
            elif event.type == MOUSEBUTTONUP:
                mouse_position = (0, 0)
                drawing = False
            elif event.type == MOUSEBUTTONDOWN:
                drawing = True

        pygame.display.update()

if __name__ == "__main__":
    main()
vgel
  • 3,225
  • 1
  • 21
  • 35
  • 1
    If you want to make _one_ continuous line, this code works good. If you want the line to break and stay broken when you release the mouse, you simply need to add `last_pos = None` under the `elif event.type == MOUSEBUTTONUP:` statement. – ZachS Apr 18 '21 at 01:53
2

vgel is right, you need to pass the previous position and the current position to pygame.draw.line. You can also calculate the previous position by subtracting the event.rel attribute of the event from the event.pos attribute.

It's also possible get rid of the drawing variable by using the event.buttons attribute. If event.buttons[0] is True then the left mouse button is being pressed.

import pygame


def main():
    pygame.init()

    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    screen = pygame.display.set_mode((600, 800), 0, 32)
    screen.fill(WHITE)
    clock = pygame.time.Clock()

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                return
            elif event.type == pygame.MOUSEMOTION:
                if event.buttons[0]:  # Left mouse button down.
                    last = (event.pos[0]-event.rel[0], event.pos[1]-event.rel[1])
                    pygame.draw.line(screen, BLACK, last, event.pos, 1)

        pygame.display.update()
        clock.tick(30)  # Limit the frame rate to 30 FPS.

if __name__ == "__main__":
    main()
skrx
  • 19,980
  • 5
  • 34
  • 48