[英]Why is my airbrush function not working in pygame?
I am creating a basic paint app and I want to create an airbrush function, and have other functions for different styles of brushes. 我正在创建一个基本的绘画应用程序,我想创建一个喷枪功能,并具有针对不同样式的画笔的其他功能。 Basically, the user clicks an icon to select the style of brush, and then when they click and hold over the canvas, the respective brush will paint on the canvas.
基本上,用户单击图标以选择画笔的样式,然后在单击并按住画布时,相应的画笔将在画布上进行绘制。 Here is my code: The main loop:
这是我的代码:主循环:
def paintScreen():
intro = True
gameDisplay.fill(cyan)
message_to_screen('Welcome to PyPaint', black, -300, 'large')
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
while intro:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
pygame.draw.rect(gameDisplay, white, (50, 120, displayWidth - 100, displayHeight - 240))
button('X', 20, 20, 50, 50, red, lightRed, action = 'quit')
icon(airbrushIcon, white, 50, displayHeight - 101, 51, 51, white, grey, 'airbrush')
icon(pencilIcon, white, 140, displayHeight - 101, 51, 51, white, grey, 'pencil')
icon(calligraphyIcon, white, 230, displayHeight - 101, 51, 51, white, grey, 'calligraphy')
pygame.display.update()
if cur[0] > 50 < displayWidth - 50 and cur [1] > 120 < displayHeight - 120:
if airbrush == True:
airbrush()
the icon function: 图标功能:
def icon(icon, colour, x, y, width, height, inactiveColour, activeColour, action = None):
cur = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + width > cur[0] > x and y + height > cur[1] > y:#if the cursor is over the button
pygame.draw.rect(gameDisplay, activeColour, (x, y, width, height))
gameDisplay.blit(icon, (x, y))
if click[0] == 1 and action != None:
if action == 'quit':
pygame.quit()
quit()
elif action == 'pencil':
pencil = True
return pencil
elif action == 'airbrush':
airbrush = True
return airbrush
elif action == 'calligraphy':
calligraphy = True
return calligraphy
elif action == 'erase':
eraser = True
return eraser
else:
pygame.draw.rect(gameDisplay, inactiveColour, (x, y, width, height))
gameDisplay.blit(icon, (x, y))
the airbrush function: 喷枪功能:
def airbrush(brushSize = 3):
airbrush = True
cur = pygame.mouse.get_pos() #cur[0] is x location, cur[1] is y location
click = pygame.mouse.get_pressed()
while airbrush == True:
if click[0] == True:
if cur[0] > 50 < displayWidth - 50 and cur[1] > 120 < displayHeight - 120: #if the cursor is above the canvas
#the area of the canvas is x(50, width-50) y(120, width-120)
pygame.draw.circle(gameDisplay, black, (cur[0] + random.randrange(brushSize), cur[1] + random.randrange(brushSize)), random.randrange(1, 5))
pygame.display.update()
clock.tick(60)
What can I do to make the airbrush function work? 如何使喷枪功能起作用? When running the app, it doesn't return any errors, it just doesn't work at all
运行该应用程序时,它不会返回任何错误,而根本不起作用
Your code has several flaws: 您的代码有几个缺陷:
icon
function, you're setting local variables (like airbrush
and pencil
etc), which does not affect global variables with the same name. icon
功能中,您正在设置局部变量(例如airbrush
和pencil
等),该变量不会影响具有相同名称的全局变量。 Also you return their value after setting them and never use that value. airbrush
function would be called, you could never leave that function, because there's no way to set airbrush
to false airbrush
功能,则永远都不能离开该功能,因为无法将airbrush
设置为false You should make use of polymorphism, something like this: 您应该使用多态,例如:
import pygame
import pygame.freetype
import random
def bresenham_line(start, end):
x1, y1 = start
x2, y2 = end
dx = x2 - x1
dy = y2 - y1
is_steep = abs(dy) > abs(dx)
if is_steep:
x1, y1 = y1, x1
x2, y2 = y2, x2
swapped = False
if x1 > x2:
x1, x2 = x2, x1
y1, y2 = y2, y1
swapped = True
dx = x2 - x1
dy = y2 - y1
error = int(dx / 2.0)
ystep = 1 if y1 < y2 else -1
y = y1
points = []
for x in range(x1, x2 + 1):
coord = (y, x) if is_steep else (x, y)
points.append(coord)
error -= abs(dy)
if error < 0:
y += ystep
error += dx
if swapped:
points.reverse()
return points
class Brush(pygame.sprite.Sprite):
def __init__(self, pos, font, canvas, tmpcanvas, icon, brushes, offset):
super().__init__(brushes)
self.image = pygame.Surface((32, 32))
self.image.fill(pygame.Color('grey'))
font.render_to(self.image, (8, 7), icon)
self.other_image = self.image.copy()
pygame.draw.rect(self.other_image, pygame.Color('red'), self.other_image.get_rect(), 3)
self.rect = self.image.get_rect(topleft=pos)
self.active = False
self.canvas = canvas
self.tmpcanvas = tmpcanvas
self.brushes = brushes
self.offset = offset
self.mouse_pos = None
def translate(self, pos):
return pos[0] - self.offset[0], pos[1] - self.offset[1]
def draw_to_canvas(self):
pass
def flip(self):
self.active = not self.active
self.image, self.other_image = self.other_image, self.image
def update(self, events):
for e in events:
if e.type == pygame.MOUSEBUTTONDOWN and self.rect.collidepoint(e.pos):
for brush in self.brushes:
if brush.active:
brush.flip()
self.flip()
self.mouse_pos = self.translate(pygame.mouse.get_pos())
if self.active:
self.draw_to_canvas()
class Pencil(Brush):
def __init__(self, pos, font, canvas, tmpcanvas, brushes, offset):
super().__init__(pos, font, canvas, tmpcanvas, 'P', brushes, offset)
self.prev_pos = None
def draw_to_canvas(self):
pressed = pygame.mouse.get_pressed()
if pressed[0] and self.prev_pos:
pygame.draw.line(self.canvas, pygame.Color('red'), self.prev_pos, self.mouse_pos)
self.prev_pos = self.mouse_pos
class Calligraphy(Brush):
def __init__(self, pos, font, canvas, tmpcanvas, brushes, offset):
super().__init__(pos, font, canvas, tmpcanvas, 'C', brushes, offset)
self.prev_pos = None
def draw_to_canvas(self):
pressed = pygame.mouse.get_pressed()
if pressed[0] and self.prev_pos:
for x, y in bresenham_line(self.prev_pos, self.mouse_pos):
pygame.draw.rect(self.canvas, pygame.Color('orange'), (x, y, 5, 15))
self.prev_pos = self.mouse_pos
class Airbrush(Brush):
def __init__(self, pos, font, canvas, tmpcanvas, brushes, offset):
super().__init__(pos, font, canvas, tmpcanvas, 'A', brushes, offset)
def draw_to_canvas(self):
pressed = pygame.mouse.get_pressed()
if pressed[0]:
pygame.draw.circle(self.canvas, pygame.Color('green'),
(self.mouse_pos[0] + random.randrange(-13, 13), self.mouse_pos[1] + random.randrange(-13, 13)),
random.randrange(1, 5))
class LineTool(Brush):
def __init__(self, pos, font, canvas, tmpcanvas, brushes, offset):
super().__init__(pos, font, canvas, tmpcanvas, 'L', brushes, offset)
self.start = None
def draw_to_canvas(self):
pressed = pygame.mouse.get_pressed()
if pressed[0]:
if not self.start:
self.start = self.mouse_pos
pygame.draw.line(self.tmpcanvas, pygame.Color('yellow'), self.start, self.mouse_pos)
else:
if self.start:
pygame.draw.line(self.canvas, pygame.Color('yellow'), self.start, self.mouse_pos)
self.start = None
class Clear(Brush):
def __init__(self, pos, font, canvas, tmpcanvas, brushes, offset):
super().__init__(pos, font, canvas, tmpcanvas, '*', brushes, offset)
def draw_to_canvas(self):
pressed = pygame.mouse.get_pressed()
if pressed[0]:
self.canvas.fill((1, 1, 1))
self.flip()
def main():
pygame.init()
screen = pygame.display.set_mode((500, 500))
sprites = pygame.sprite.Group()
clock = pygame.time.Clock()
font = pygame.freetype.SysFont(None, 26)
offset = 0, 50
canvas = pygame.Surface((500, 450))
canvas.set_colorkey((1,1,1))
canvas.fill((1,1,1))
tmpcanvas = canvas.copy()
x=10
for tool in (Pencil, Calligraphy, Airbrush, LineTool, Clear):
tool((x, 10), font, canvas, tmpcanvas, sprites, offset)
x+= 40
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
tmpcanvas.fill((1, 1, 1))
sprites.update(events)
screen.fill((30, 30, 30))
screen.blit(canvas, offset)
screen.blit(tmpcanvas, offset)
sprites.draw(screen)
pygame.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
In this example, we have a Brush
base class that handles drawing of the icon and keeping track of the active
-state of the brush, and the subclasses handle the actual drawing. 在此示例中,我们有一个
Brush
基类,该基类处理图标的绘制并跟踪画笔的active
状态,而子类则处理实际的绘制。
This way, we can easily add new brushes/tools quite easily by creating a new class and implementing the draw_to_canvas
function. 这样,我们可以通过创建一个新类并实现
draw_to_canvas
函数,轻松地轻松添加新的画笔/工具。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.