سؤال

كما أراها، هناك طريقتان للتعامل مع أحداث الماوس لرسم صورة.

الأول هو اكتشافه عندما يتحرك الماوس ورسم خطا إلى حيث الماوس، يظهر هنا. وبعد ومع ذلك، فإن المشكلة مع هذا هو أنه مع حجم فرشاة كبيرة، تظهر العديد من الثغرات بين كل "خط" غير مباشرة لأنها تستخدم حجم السطر السكتة الدماغ لإنشاء خطوط سميكة.

في الاتجاه الآخر هو استخلاص دوائر عندما يتحرك الماوس كما هو موضح هنا. وبعد المشكلة في هذه هي أن الثغرات تظهر بين كل دائرة إذا كان الماوس يتحرك بشكل أسرع من اكتشاف الكمبيوتر إدخال الماوس.

إليك لقطة شاشة مع مشكلاتي مع كليهما:

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

ما هي أفضل طريقة لتنفيذ فرشاة مثل MS Paint's، مع حجم فرشاة كبيرة بشكل رائع مع عدم وجود فجوات في السكتة الدماغية من الخط أو لا توجد فجوات بين كل دائرة؟

هل كانت مفيدة؟

المحلول

لماذا لا تفعل كليهما؟

ارسم دائرة في كل نقطة نهاية وخط بين الاثنين.

تعديل rofl، فقط لا يمكن أن يمنع نفسي.

في الواقع، أنت لا تريد استخدامها pygame.draw.line لأنه يغش. يملأ صف أو عمود واسع 1 بكسل (اعتمادا على زاوية الهجوم) من البكسل. إذا ذهبت في زاوية عمودي تقريبا، فستني درجة أو 90 درجة، هذه ليست مشكلة، ولكن عند 45 عاما، ستلاحظ نوعا من سلسلة فول تأثير.

الحل الوحيد هو رسم دائرة في مسافة بكسل. هنا...

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

نصائح أخرى

لا تخفف في كل خطوة حلقة يمكن أن تحسن سرعة الرسم (باستخدام هذا الرمز الذي تم تكييفه من السابق السماح بإزالة مشكلة تأخر على جهازي)

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

بالنسبة للمشكلة الأولى، تحتاج إلى وجود خلفية، حتى لو كان لونها فقط. كان لدي نفس المشكلة مع لعبة بونغ المتماثلة التي صنعتها. هنا مثال على برنامج الطلاء المتماثل الذي قمت به، انقر بزر الماوس الأيمن، انقر بزر الماوس الأيمن لمحو، انقر فوق صورة اللون لاختيار اللون، وزر أعلى لتخفيف الشاشة:

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)

إليك نسخة مبسطة من ماثيو مثال وهذا ليس للأسف غير قابل للعادة.

عندما يتم نقل الماوس، pygame.MOUSEMOTION تتم إضافة الأحداث إلى قائمة انتظار الحدث التي تحتوي على الموضع والحركة النسبية. يمكنك استخدام هذه لحساب الموضع السابق ثم تمر النقاط pygame.draw.line.

pygame.MOUSEMOTION الأحداث لديها أيضا buttons السمة التي يمكنك استخدامها للتحقق من زر الماوس هو الموجود حاليا.

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()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top