Как создать клонирование MS Paint с помощью Python и pygame
Как я вижу, есть два способа обработки событий мыши для рисования изображения.
Во-первых, чтобы обнаружить, когда мышь перемещается и рисует линию, где находится мышь, показано здесь. Однако проблема заключается в том, что при большом размере кисти между каждыми "прямыми", которые не являются прямыми, появляется много пробелов, так как он использует размер штриха линии для создания толстых линий.
Другой способ - нарисовать круги, когда мышь перемещается, как показано здесь. Проблема заключается в том, что между каждым кружком появляются промежутки, если мышь движется быстрее, чем компьютер обнаруживает ввод мыши.
Вот скриншот с моими проблемами с обоими:
![http://imgur.com/32DXN.jpg]()
Каков наилучший способ реализации кисти, такой как MS Paint, с прилично большим размером кисти без пробелов в штрихе линии или без пробелов между каждым кругом?
Ответы
Ответ 1
Почему бы не сделать оба?
Нарисуйте круг на каждой конечной точке и линию между ними.
РЕДАКТИРОВАТЬ rofl, просто не мог остановиться.
Собственно, вы не хотите использовать pygame.draw.line
, потому что он обманывает. Он заполняет строку или столбец шириной 1 пиксель (в зависимости от угла атаки) пикселей. Если вы переходите на грубо перпендикулярный угол, 0 градусов или 90 градусов, это не проблема, но в 45 секунд вы заметите какой-то эффект строки bean.
Единственное решение - нарисовать круг на каждом расстоянии. Здесь...
import pygame, random
screen = pygame.display.set_mode((800,600))
draw_on = False
last_pos = (0, 0)
color = (255, 128, 0)
radius = 10
def roundline(srf, color, start, end, radius=1):
dx = end[0]-start[0]
dy = end[1]-start[1]
distance = max(abs(dx), abs(dy))
for i in range(distance):
x = int( start[0]+float(i)/distance*dx)
y = int( start[1]+float(i)/distance*dy)
pygame.draw.circle(srf, color, (x, y), radius)
try:
while True:
e = pygame.event.wait()
if e.type == pygame.QUIT:
raise StopIteration
if e.type == pygame.MOUSEBUTTONDOWN:
color = (random.randrange(256), random.randrange(256), random.randrange(256))
pygame.draw.circle(screen, color, e.pos, radius)
draw_on = True
if e.type == pygame.MOUSEBUTTONUP:
draw_on = False
if e.type == pygame.MOUSEMOTION:
if draw_on:
pygame.draw.circle(screen, color, e.pos, radius)
roundline(screen, color, e.pos, last_pos, radius)
last_pos = e.pos
pygame.display.flip()
except StopIteration:
pass
pygame.quit()
Ответ 2
Не биение на каждом шаге цикла может улучшить скорость рисования (использование этого кода, адаптированного из предыдущего, позволяет устранить проблему с задержкой на моей машине)
import pygame, random
screen = pygame.display.set_mode((800,600))
draw_on = False
last_pos = (0, 0)
color = (255, 128, 0)
radius = 10
def roundline(srf, color, start, end, radius=1):
dx = end[0]-start[0]
dy = end[1]-start[1]
distance = max(abs(dx), abs(dy))
for i in range(distance):
x = int( start[0]+float(i)/distance*dx)
y = int( start[1]+float(i)/distance*dy)
pygame.display.update(pygame.draw.circle(srf, color, (x, y), radius))
try:
while True:
e = pygame.event.wait()
if e.type == pygame.QUIT:
raise StopIteration
if e.type == pygame.MOUSEBUTTONDOWN:
color = (random.randrange(256), random.randrange(256), random.randrange(256))
pygame.draw.circle(screen, color, e.pos, radius)
draw_on = True
if e.type == pygame.MOUSEBUTTONUP:
draw_on = False
if e.type == pygame.MOUSEMOTION:
if draw_on:
pygame.display.update(pygame.draw.circle(screen, color, e.pos, radius))
roundline(screen, color, e.pos, last_pos, radius)
last_pos = e.pos
#pygame.display.flip()
except StopIteration:
pass
pygame.quit()
Ответ 3
Для первой проблемы вам нужен фон, даже если это только цвет. У меня была та же проблема с репликой, что я сделал. Вот пример программы рисования реплик, которую я сделал, щелкните левой кнопкой мыши для рисования, щелкните правой кнопкой мыши, чтобы удалить, щелкните по цветному изображению, чтобы выбрать цвет, и кнопку "вверх" для очистки экрана:
import os
os.environ['SDL_VIDEO_CENTERED'] = '1'
from pygamehelper import *
from pygame import *
from pygame.locals import *
from vec2d import *
from math import e, pi, cos, sin, sqrt
from random import uniform
class Starter(PygameHelper):
def __init__(self):
self.w, self.h = 800, 600
PygameHelper.__init__(self, size=(self.w, self.h), fill=((255,255,255)))
self.img= pygame.image.load("colors.png")
self.screen.blit(self.img, (0,0))
self.drawcolor= (0,0,0)
self.x= 0
def update(self):
pass
def keyUp(self, key):
if key==K_UP:
self.screen.fill((255,255,255))
self.screen.blit(self.img, (0,0))
def mouseUp(self, button, pos):
pass
def mouseMotion(self, buttons, pos, rel):
if pos[1]>=172:
if buttons[0]==1:
#pygame.draw.circle(self.screen, (0,0,0), pos, 5)
pygame.draw.line(self.screen, self.drawcolor, pos, (pos[0]-rel[0], pos[1]-rel[1]),5)
if buttons[2]==1:
pygame.draw.circle(self.screen, (255,255,255), pos, 30)
if buttons[1]==1:
#RAINBOW MODE
color= self.screen.get_at((self.x, 0))
pygame.draw.line(self.screen, color, pos, (pos[0]-rel[0], pos[1]-rel[1]), 5)
self.x+= 1
if self.x>172: self.x=0
else:
if pos[0]<172:
if buttons[0]==1:
self.drawcolor= self.screen.get_at(pos)
pygame.draw.circle(self.screen, self.drawcolor, (250, 100), 30)
def draw(self):
pass
#self.screen.fill((255,255,255))
#pygame.draw.circle(self.screen, (0,0,0), (50,100), 20)
s = Starter()
s.mainLoop(40)