2009-02-28 8 views
11

Jak widzimy, istnieją dwa sposoby obsługi zdarzeń myszy w celu narysowania obrazu.Jak utworzyć klon MS Paint przy pomocy Pythona i pygame

Pierwszym z nich jest wykrywanie, kiedy mysz się porusza i narysowanie linii do miejsca, w którym znajduje się mysz, pokazanego jako here. Problem polega jednak na tym, że przy dużym rozmiarze pędzla pojawia się wiele przerw pomiędzy każdą "linią", która nie jest prosta, ponieważ wykorzystuje rozmiar linii linii do tworzenia grubych linii.

Innym sposobem jest rysowanie kółek, gdy mysz porusza się tak jak pokazano here. Problem polega na tym, że przerwy pojawiają się między każdym kółkiem, jeśli mysz porusza się szybciej, niż komputer wykrywa wejście myszy.

Oto zrzut ekranu z moich problemów z obu:

http://imgur.com/32DXN.jpg

Co jest najlepszym sposobem wdrożenia pędzla jak MS farby, z przyzwoicie-duży rozmiar pędzla bez przerw w skoku linia lub brak przerw między poszczególnymi okręgami?

+0

Nie rozumiem twojego problemu z liniami. Czy mówisz o braku końcówek, czy ...? –

+0

Po prostu połącz oba. Grube linie + okręgi. –

+0

Oto zrzut ekranu z moich problemów z: http://imgur.com/32DXN Używanie grubych linii i okręgów wydaje się być rozwiązaniem problemu, ale nie brzmi to zbyt elegancko, więc pomyślę o to jeszcze trochę i wykorzystaj to jako ostateczność. – Johnston

Odpowiedz

13

Dlaczego nie zrobić obu?

Narysuj okrąg w każdym punkcie końcowym i linię między nimi.

EDYTOWANIE rofl, po prostu nie mogłem się powstrzymać.

W rzeczywistości nie chcesz używać pygame.draw.line, ponieważ jest to kod. Wypełnia on 1 piksel szerokości lub kolumnę (w zależności od kąta natarcia) pikseli. Jeśli idziesz pod kątem w przybliżeniu prostopadłym, 0 stopni lub 90 stopni, to nie jest problem, ale w 45, zauważysz rodzaj efektu fasoli fasoli.

Jedynym rozwiązaniem jest narysowanie okręgu w odległości każdego piksela. Tutaj ...

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

Do pierwszego problemu potrzebne jest tło, nawet jeśli jest to tylko kolor. Miałem ten sam problem z wykonaną przeze mnie repliką ponga. Oto przykład programu farby replika zrobiłem, kliknij lewym przyciskiem myszy, aby narysować, kliknij prawym przyciskiem myszy, aby usunąć, kliknij na kolorowy obraz, aby wybrać kolor, a nawet przycisk, aby ekran Clear:

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

Nie blittingiem na siebie krok pętli może poprawić prędkość rysowania (za pomocą tego kodu zaadaptowanego z poprzedniego pozwala na usunięcie problemu z lagami na mojej maszynie)

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() 
Powiązane problemy