Python 如何使pygame在2点之间的直线上绘制所有点?

Python 如何使pygame在2点之间的直线上绘制所有点?,python,python-3.x,pygame,Python,Python 3.x,Pygame,我正在尝试制作一个画笔功能,用一种书法风格的画笔在画布上绘制,一种薄,一种厚。现在,画笔示意图的实际绘制工作正常,但代码运行速度不够快,实际线条一直在剪切(如gif所示) 这是我现在的代码: import pygame import os import random from pygame.locals import * flags = DOUBLEBUF pygame.init() pygame.event.set_allowed([QUIT]) current_path = os.pa

我正在尝试制作一个画笔功能,用一种书法风格的画笔在画布上绘制,一种薄,一种厚。现在,画笔示意图的实际绘制工作正常,但代码运行速度不够快,实际线条一直在剪切(如gif所示)

这是我现在的代码:

import pygame
import os
import random
from pygame.locals import *

flags = DOUBLEBUF

pygame.init()
pygame.event.set_allowed([QUIT])

current_path = os.path.dirname(__file__) #The directory the main file is in
iconPath = os.path.join(current_path, 'images') #The icon folder path

displayWidth = 1280
displayHeight = 720

gameDisplay = pygame.display.set_mode((displayWidth, displayHeight), flags)
gameDisplay.set_alpha(None)
pygame.display.set_caption('PyPaint')

black = (0, 0, 0)
white = (255, 255, 255)
grey = (200, 200, 200)
cyan = (0, 200, 255)
green = (0, 150, 0)
lightGreen = (0, 255, 0)
red = (150, 0, 0)
lightRed = (255, 0, 0)

smallfont = pygame.font.SysFont("arial", 40)
medfont = pygame.font.SysFont("arial", 60)
largefont = pygame.font.SysFont("arial", 80)

airbrushIcon = pygame.image.load(os.path.join(iconPath, "airbrush.png"))
pencilIcon = pygame.image.load(os.path.join(iconPath, "pencil.png"))
calligraphyIcon = pygame.image.load(os.path.join(iconPath, "calligraphy.png"))
eraserIcon = pygame.image.load(os.path.join(iconPath, "eraser.png"))

clock = pygame.time.Clock()
FPS = 60

airbrushMode = False
calligraphyMode = False
eraserMode = False

def paintScreen():
    global airbrushMode
    global calligraphyMode
    global eraserMode
    airbrushMode = False
    paint = True
    gameDisplay.fill(cyan)
    message_to_screen('Welcome to PyPaint', black, -300, 'large')
    click = pygame.mouse.get_pressed()
    pygame.draw.rect(gameDisplay, white, (50, 120, displayWidth - 100, displayHeight - 240))
    while paint:
        cur = pygame.mouse.get_pos()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        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')
        icon(eraserIcon, white, 320, displayHeight - 101, 51, 51, white, grey, 'eraser')
        pygame.draw.rect(gameDisplay, cyan, (0, 120, 50, displayHeight - 100))#to clean up the left border of the canvas
        pygame.draw.rect(gameDisplay, cyan, (displayWidth - 50, 120, 50, displayHeight - 100))#to clean up the right border of the canvas
        pygame.draw.rect(gameDisplay, cyan, (0, displayHeight - 120, displayWidth, 20))#to clean up the bottom of the canvas
        pygame.draw.rect(gameDisplay, cyan, (0, 100, displayWidth, 20))#to clean up the top of the canvas
        if airbrushMode == True:
            airbrush()
        elif calligraphyMode == True:
            calligraphy()
        elif eraserMode == True:
            eraser()
        pygame.display.update()

def icon(icon, colour, x, y, width, height, inactiveColour, activeColour, action = None):
    global airbrushMode
    global calligraphyMode
    global eraserMode
    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 clicked
            if action == 'quit':
                pygame.quit()
                quit()
            elif action == 'pencil':
                pencilMode = True
                airbrushMode = False
                calligraphyMode = False
                eraserMode = False
            elif action == 'airbrush':
                airbrushMode = True
                calligraphyMode = False
                pencilMode = False
                eraserMode = False
            elif action == 'calligraphy':
                calligraphyMode = True
                airbrushMode = False
                pencilMode = False
                eraserMode = False
            elif action == 'eraser':
                eraserMode = True
                airbrushMode = False
                pencilMode = False
                calligraphyMode = False
    else:
        pygame.draw.rect(gameDisplay, inactiveColour, (x, y, width, height))
        gameDisplay.blit(icon, (x, y))

def button(text, 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:
        pygame.draw.rect(gameDisplay, activeColour, (x, y, width, height))
        if click[0] == 1 and action != None:
            if action == 'quit':
                pygame.quit()
                quit()
    else:
        pygame.draw.rect(gameDisplay, inactiveColour, (x, y, width, height))
    text_to_button(text, black, x, y, width, height)

def text_to_button(msg, colour, buttonx, buttony, buttonwidth, buttonheight, size = 'small'):
    textSurf, textRect = text_objects (msg, colour, size)
    textRect.center = ((buttonx + (buttonwidth/2)), buttony + (buttonheight/2))
    gameDisplay.blit(textSurf, textRect)

def message_to_screen(msg, colour, y_displace = 0, size = 'small'):
    textSurf, textRect = text_objects (msg, colour, size)
    textRect.center = (displayWidth / 2), (displayHeight / 2) + y_displace
    gameDisplay.blit(textSurf, textRect)

def airbrush(brushSize = 3):
    cur = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    if cur[0] >= 50 and cur[0] <= displayWidth - 50 and cur[1] >= 120 and cur[1] <= displayHeight - 120:
        if click[0] == 1:
            pygame.draw.circle(gameDisplay, black, (cur[0] + random.randrange(-brushSize * 2, brushSize * 2), cur[1] + random.randrange(-brushSize * 2, brushSize * 2)), random.randrange(1, brushSize * 2))

def calligraphy(brushSize = 3):
    cur = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    if cur[0] >= 50 and cur[0] <= displayWidth - 50 and cur[1] >= 120 and cur[1] <= displayHeight - 120:#if cursor is on the canvas
        if click[0] == 1:
            pygame.draw.rect(gameDisplay, black, (cur[0] - brushSize / 2, cur[1] - brushSize / 4, brushSize, brushSize * 3))

def eraser(brushSize = 3):
    cur = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    if cur[0] >= 50 and cur[0] <= displayWidth - 50 and cur[1] >= 120 and cur[1] <= displayHeight - 120:#if cursor is on the canvas
        if click[0] == 1:
            pygame.draw.rect(gameDisplay, white, (cur[0] - brushSize / 2, cur[1] - brushSize / 2, brushSize * 6, brushSize * 6))

def text_objects(text, colour, size):
    if size == 'small':
        textSurface = smallfont.render (text, True, colour)
    elif size == 'medium':
        textSurface = medfont.render (text, True, colour)
    elif size == 'large':
        textSurface = largefont.render (text, True, colour)
    return textSurface, textSurface.get_rect() 

paintScreen()
导入pygame
导入操作系统
随机输入
从pygame.locals导入*
flags=DOUBLEBUF
pygame.init()
pygame.event.set_允许([退出])
当前路径=os.path.dirname(_文件)#主文件所在的目录
iconPath=os.path.join(当前路径,'images')#图标文件夹路径
displayWidth=1280
显示高度=720
gameDisplay=pygame.display.set_模式((显示宽度,显示高度),标志)
gameDisplay.set_alpha(无)
pygame.display.set_标题('PyPaint')
黑色=(0,0,0)
白色=(255,255,255)
灰色=(200200200200)
青色=(0200255)
绿色=(0,150,0)
浅绿色=(0,255,0)
红色=(150,0,0)
浅红色=(255,0,0)
smallfont=pygame.font.SysFont(“arial”,40)
medfont=pygame.font.SysFont(“arial”,60)
largefont=pygame.font.SysFont(“arial”,80)
airbrushIcon=pygame.image.load(os.path.join(iconPath,“airbrush.png”))
pencilIcon=pygame.image.load(os.path.join(iconPath,“pencil.png”))
calligraphyIcon=pygame.image.load(os.path.join(iconPath,“phraphy.png”))
橡皮擦ricon=pygame.image.load(os.path.join(iconPath,“橡皮擦.png”))
clock=pygame.time.clock()
FPS=60
airbrushMode=错误
书法模式=假
橡皮擦模式=错误
def paintScreen():
全局喷枪模式
全球书法乐章
全局橡皮擦极
airbrushMode=错误
油漆=真
gameDisplay.fill(青色)
屏幕上的信息('欢迎使用PyPaint',黑色,-300',大型')
click=pygame.mouse.get_pressed()
pygame.draw.rect(gameDisplay,白色,(50120,displayWidth-100,displayHeight-240))
油漆时:
cur=pygame.mouse.get_pos()
对于pygame.event.get()中的事件:
如果event.type==pygame.QUIT:
pygame.quit()
退出
按钮('X',20,20,50,50,红色,浅红色,操作='quit')
图标(喷枪图标,白色,50,显示高度-101,51,51,白色,灰色,“喷枪”)
图标(铅笔,白色,140,显示屏高度-101,51,51,白色,灰色,'铅笔')
图标(书法图标,白色,230,显示高度-101,51,51,白色,灰色,“书法”)
图标(橡皮擦,白色,320,显示屏高度-101,51,51,白色,灰色,“橡皮擦”)
pygame.draw.rect(gameDisplay,青色,(0,120,50,displayHeight-100))#清理画布的左边框
pygame.draw.rect(gameDisplay,cyan,(displayWidth-50,120,50,displayHeight-100))#清理画布的右边框
pygame.draw.rect(gameDisplay,青色,(0,displayHeight-120,displayWidth,20))#清理画布底部
pygame.draw.rect(gameDisplay,青色,(01000,displayWidth,20))#清理画布顶部
如果airbrushMode==真:
喷枪()
elif calligraphyMode==真:
书法(
elif橡皮擦模式==真:
橡皮擦
pygame.display.update()
def图标(图标、颜色、x、y、宽度、高度、非活动颜色、活动颜色、操作=无):
全局喷枪模式
全球书法乐章
全局橡皮擦极
cur=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
如果x+宽度>cur[0]>x和y+高度>cur[1]>y:#如果光标位于按钮上方
pygame.draw.rect(游戏显示,ActiveColor,(x,y,宽度,高度))
blit(图标,(x,y))
如果单击[0]==1并执行操作!=无:#如果单击
如果操作==“退出”:
pygame.quit()
退出
elif动作==“铅笔”:
铅笔模式=真
airbrushMode=错误
书法模式=假
橡皮擦模式=错误
elif动作==“喷枪”:
airbrushMode=True
书法模式=假
铅笔模式=假
橡皮擦模式=错误
elif动作==‘书法’:
书法模式=真
airbrushMode=错误
铅笔模式=假
橡皮擦模式=错误
elif操作==‘橡皮擦’:
橡皮擦模式=真
airbrushMode=错误
铅笔模式=假
书法模式=假
其他:
pygame.draw.rect(游戏显示,不活动颜色,(x,y,宽度,高度))
blit(图标,(x,y))
def按钮(文本、x、y、宽度、高度、非活动颜色、活动颜色、操作=无):
cur=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
如果x+宽度>cur[0]>x和y+高度>cur[1]>y:
pygame.draw.rect(游戏显示,ActiveColor,(x,y,宽度,高度))
如果单击[0]==1并执行操作!=无:
如果操作==“退出”:
pygame.quit()
退出
其他:
pygame.draw.rect(游戏显示,不活动颜色,(x,y,宽度,高度))
文本按钮(文本、黑色、x、y、宽度、高度)
def text_to_按钮(消息、颜色、按钮X、按钮Y、按钮宽度、按钮H、大小=‘小’):
textSurf,textRect=文本对象(消息、颜色、大小)
textRect.center=((buttonx+(buttonwidth/2)),buttony+(buttonheight/2))
blit(textSurf,textRect)
def消息到屏幕(消息,颜色,y位移=0,大小='small'):
textSurf,textRect=文本对象(消息、颜色、大小)
text rect.center=(显示宽度/2),(显示高度/2)+y_置换
blit(textSurf,textRect)
def喷枪(刷子大小=3):
cur=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
如果cur[0]>=50,cur[0]=120,cur[1]=50,cur[0]=120,cur[1]=50,cur[0]=120,cur[1]I
steps = max(abs(x-prev_x), abs(y-prev_y))
dx = (x - prev_x)/steps
dy = (y - prev_y)/steps
for _ in range(steps):
    prev_x += dx
    prev_y += dy
    pygame.draw.circle(display, BLACK, (round(prev_x - 5), round(prev_y - 5)), 10)
import pygame

# --- constants --- (uppercase)
BLACK = (  0,   0,   0)
WHITE = (255, 255, 255)

WIDTH = 800
HEIGHT = 600
FPS = 60

# --- functions --- (lowercase)

def airbrush(brushSize = 3):
    global prev_x
    global prev_y

    click = pygame.mouse.get_pressed()
    if click[0] == 1:
        x, y = pygame.mouse.get_pos()
        if x >= 0 and x <= WIDTH and y >= 0 and y <= HEIGHT0:
            pygame.draw.circle(display, BLACK, (x - 5, y - 5), 10)

        # if there is previous point then draw missing points 
        if prev_x is not None:
            diff_x = x - prev_x
            diff_y = y - prev_y
            steps = max(abs(diff_x), abs(diff_y))

            # skip if distance is zero (error: dividing by zero)
            if steps > 0:
                dx = diff_x / steps
                dy = diff_y / steps
                for _ in range(steps):
                    prev_x += dx
                    prev_y += dy
                    pygame.draw.circle(display, BLACK, (round(prev_x - 5), round(prev_y - 5)), 10)
        prev_x = x # remeber previous point
        prev_y = y # remeber previous point
    else:
        prev_x = None # there is no previous point
        prev_y = None # there is no previous point

# --- main ---

pygame.init()

display = pygame.display.set_mode((WIDTH, HEIGHT), pygame.DOUBLEBUF)

prev_x = None # at start there is no previous point
prev_y = None # at start there is no previous point

display.fill(WHITE)
clock = pygame.time.Clock()

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()

    airbrush()
    pygame.display.update()
    clock.tick(FPS)
prev_x = x
prev_y = y