كيفية إنشاء استنساخ MS الطلاء مع Python و Pygame
سؤال
كما أراها، هناك طريقتان للتعامل مع أحداث الماوس لرسم صورة.
الأول هو اكتشافه عندما يتحرك الماوس ورسم خطا إلى حيث الماوس، يظهر هنا. وبعد ومع ذلك، فإن المشكلة مع هذا هو أنه مع حجم فرشاة كبيرة، تظهر العديد من الثغرات بين كل "خط" غير مباشرة لأنها تستخدم حجم السطر السكتة الدماغ لإنشاء خطوط سميكة.
في الاتجاه الآخر هو استخلاص دوائر عندما يتحرك الماوس كما هو موضح هنا. وبعد المشكلة في هذه هي أن الثغرات تظهر بين كل دائرة إذا كان الماوس يتحرك بشكل أسرع من اكتشاف الكمبيوتر إدخال الماوس.
إليك لقطة شاشة مع مشكلاتي مع كليهما:
ما هي أفضل طريقة لتنفيذ فرشاة مثل 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()