我正在创建一个基本的绘画应用程序,我想创建一个喷枪功能,并具有用于不同样式的画笔的其他功能。基本上,用户单击图标以选择画笔的样式,然后在单击并按住画布时,相应的画笔将在画布上进行绘制。这是我的代码: 主循环:
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()
图标功能:
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))
喷枪功能
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)
如何使喷枪功能起作用?在运行该应用程序时,它不会返回任何错误,而根本不起作用
答案 0 :(得分:1)
您的代码有几个缺陷:
icon
函数中,您正在设置局部变量(例如airbrush
和pencil
等),这不会影响具有相同名称的全局变量。同样,您在设置它们后返回它们的值,并且永远不要使用该值。airbrush
函数,则永远都不会离开该函数,因为无法将airbrush
设置为false 您应该利用多态性,例如:
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()
在此示例中,我们有一个Brush
基类,它处理图标的绘制并跟踪笔刷的active
状态,而子类则处理实际的绘制。
通过这种方式,我们可以通过创建新类并实现draw_to_canvas
函数来轻松地轻松添加新的画笔/工具。