Frage

Wie ich es sehe, gibt es zwei Möglichkeiten Maus-Ereignisse zu behandeln, ein Bild zu zeichnen.

Die erste ist, wenn sich die Maus bewegt, zu detektieren und eine Linie zu ziehen, wo die Maus ist, gezeigt hier . Dies ist jedoch das Problem mit, dass mit einer großen Pinselgröße, erscheinen viele Lücken zwischen dem einzelnen „Linie“, die nicht gerade ist, da es die Linie der Strichgröße wird mit dicken Linien erstellen.

Der andere Weg ist Kreise zu ziehen, wenn die Maus bewegt, wie gezeigt wird, hier . Das Problem dabei ist, dass Lücken zwischen den einzelnen Kreis angezeigt, wenn die Maus bewegt sich schneller als der Computer-Maus-Eingang erkennt.

Hier ist ein Screenshot mit meinen Problemen mit den beiden:

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

Was ist der beste Weg, um eine Bürste wie MS Paint, mit einer anständig großen Pinselgröße ohne Lücken im Takt der Linie oder ohne Lücken zwischen dem einzelnen Kreis?

implementieren
War es hilfreich?

Lösung

Warum nicht beides tun?

Zeichnen Sie einen Kreis an jedem Endpunkt und eine Linie zwischen den beiden.

Bearbeiten rofl, konnte einfach nicht aufhören mich.

Eigentlich wollen Sie nicht pygame.draw.line verwenden, weil es betrügt. Es füllt eine 1-Pixel-breite Zeile oder Spalte (je nach Anstellwinkel) von Pixeln. Wenn Sie an einem etwa senkrechten Winkel gehen Sie, 0 ° oder 90 °, ist dies kein Problem, aber bei 45 ist, erhalten Sie eine Art von string bean merken Effekt.

Die einzige Lösung ist, einen Kreis an jedem Pixel der Abstand zu ziehen. Hier ...

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

Andere Tipps

Nicht bei jedem Schleifenschritt Blitten die Geschwindigkeit der Zeichnung verbessern (diesen Code aus dem vorherigen ermöglichen angepasst mit Verzögerung Problem auf meinem Rechner entfernen)

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

Für das erste Problem, benötigen Sie einen Hintergrund haben, auch wenn es nur eine Farbe. Ich hatte das gleiche Problem mit einem Replika-Pong-Spiel, das ich gemacht. Hier ist ein Beispiel für eine Replik Malprogramm ich gemacht, klicken Sie links zu ziehen, klicken Sie rechts zu löschen, klicken Sie auf das Farbbild mit einer Farbe zu wählen, und die Aufwärtstaste Bildschirm zu löschen:

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)

Hier ist eine vereinfachte Version des Matthäus Beispiel die leider nicht runnable.

Wenn die Maus bewegt wird, pygame.MOUSEMOTION Ereignisse an die Ereigniswarteschlange hinzugefügt werden, welche die Position und die relative Bewegung enthält. Sie können diese verwenden, um die vorherige Position zu berechnen und dann die beiden Punkte zu pygame.draw.line passieren.

pygame.MOUSEMOTION Ereignisse haben auch ein buttons Attribut, das Sie verwenden können, um zu überprüfen, welche Maustaste ist zur Zeit nach unten.

import os
import random

import pygame as pg


class App:

    def __init__(self):
        os.environ['SDL_VIDEO_CENTERED'] = '1'
        pg.init()
        self.w, self.h = 800, 600
        self.screen = pg.display.set_mode((self.w, self.h))
        self.screen.fill(pg.Color('white'))
        self.clock = pg.time.Clock()
        self.drawcolor = (0, 0, 0)

    def mainloop(self):
        while True:
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    return
                elif event.type == pg.MOUSEBUTTONDOWN:
                    if event.button == 2:  # Color picker (middle mouse button).
                        self.drawcolor = self.screen.get_at(pos)
                        # Pick a random color.
                        # self.drawcolor = [random.randrange(256) for _ in range(3)]
                elif event.type == pg.MOUSEMOTION:
                    pos, rel = event.pos, event.rel
                    if event.buttons[0]:  # If the left mouse button is down.
                        # Draw a line from the pos to the previous pos.
                        pg.draw.line(self.screen, self.drawcolor, pos, (pos[0]-rel[0], pos[1]-rel[1]), 5)
                    elif event.buttons[2]:  # If the right mouse button is down.
                        # Erase by drawing a circle.
                        pg.draw.circle(self.screen, (255, 255, 255), pos, 30)

            pg.display.flip()
            self.clock.tick(30)


if __name__ == '__main__':
    app = App()
    app.mainloop()
    pg.quit()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top