我正在尝试使用Pygame在Python中编写一个简单的圆形计时器。 目前它看起来像这样:
如您所见,蓝线非常波浪状,内部有白点。我通过使用pygame.draw.arc()函数实现了这条蓝线,但它没有消除锯齿并且看起来很糟糕。我希望它是消除锯齿的,但gfxdraw模块应该让我实现这一点,并不支持弧宽选择。这是代码片段:
pygame.draw.arc(screen, blue, [center[0] - 120, center[1] - 120, 240, 240], pi/2, pi/2+pi*i*koef, 15)
pygame.gfxdraw.aacircle(screen, center[0], center[1], 105, black)
pygame.gfxdraw.aacircle(screen, center[0], center[1], 120, black)
答案 0 :(得分:0)
我不知道有任何pygame函数可以解决这个问题,这意味着你基本上必须自己编写一个解决方案(或者使用除pygame之外的其他东西),因为draw
已被破坏,因为你已经注意到了并且gfxdraw
不会给你厚度。
一个非常丑陋但简单的解决方案是在弧段上绘制多次,总是稍微转移到"填充"缺少的差距。这仍然会在计时器弧的最前面留下一些别名,但其余部分将被填入。
import pygame
from pygame.locals import *
import pygame.gfxdraw
import math
# Screen size
SCREEN_HEIGHT = 350
SCREEN_WIDTH = 500
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREY = (150, 150, 150)
RED = (255,0,0)
# initialisation
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
done = False
clock = pygame.time.Clock()
# We need this if we want to be able to specify our
# arc in degrees instead of radians
def degreesToRadians(deg):
return deg/180.0 * math.pi
# Draw an arc that is a portion of a circle.
# We pass in screen and color,
# followed by a tuple (x,y) that is the center of the circle, and the radius.
# Next comes the start and ending angle on the "unit circle" (0 to 360)
# of the circle we want to draw, and finally the thickness in pixels
def drawCircleArc(screen,color,center,radius,startDeg,endDeg,thickness):
(x,y) = center
rect = (x-radius,y-radius,radius*2,radius*2)
startRad = degreesToRadians(startDeg)
endRad = degreesToRadians(endDeg)
pygame.draw.arc(screen,color,rect,startRad,endRad,thickness)
# fill screen with background
screen.fill(WHITE)
center = [150, 200]
pygame.gfxdraw.aacircle(screen, center[0], center[1], 105, BLACK)
pygame.gfxdraw.aacircle(screen, center[0], center[1], 120, BLACK)
pygame.display.update()
step = 10
maxdeg = 0
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
maxdeg = maxdeg + step
for i in range(min(0,maxdeg-30),maxdeg):
drawCircleArc(screen,RED,(150,200),119,i+90,max(i+10,maxdeg)+90,14)
#+90 will shift it from starting at the right to starting (roughly) at the top
pygame.display.flip()
clock.tick(2) # ensures a maximum of 60 frames per second
pygame.quit()
请注意,我已从https://www.cs.ucsb.edu/~pconrad/cs5nm/08F/ex/ex09/drawCircleArcExample.py
复制了degreesToRadians
和drawCircleArc
我一般不推荐这种解决方案,但它可能会在紧要关头。
答案 1 :(得分:0)
好的,这真的很老,但是为什么不尝试画馅饼呢。例如,绘制一个饼图,然后绘制一个未填充的圆作为外圈,然后绘制一个填充的圆作为内圈,再绘制一个未填充的圆作为内圈。
所以pie -> unfilled circle -> filled circle -> unfilled
。
该命令在某种程度上是任意的,但是如果您仍然有此问题,请尝试一下。 (顺便说一句,我还没有尝试过,但是我认为它可以工作)
答案 2 :(得分:0)
我是用多边形创建弧的。
def drawArc(surface, x, y, r, th, start, stop, color):
points_outer = []
points_inner = []
n = round(r*abs(stop-start)/20)
if n<2:
n = 2
for i in range(n):
delta = i/(n-1)
phi0 = start + (stop-start)*delta
x0 = round(x+r*math.cos(phi0))
y0 = round(y+r*math.sin(phi0))
points_outer.append([x0,y0])
phi1 = stop + (start-stop)*delta
x1 = round(x+(r-th)*math.cos(phi1))
y1 = round(y+(r-th)*math.sin(phi1))
points_inner.append([x1,y1])
points = points_outer + points_inner
pygame.gfxdraw.aapolygon(surface, points, color)
pygame.gfxdraw.filled_polygon(surface, points, color)
当然可以使用生成器更优雅地创建for循环,但是我对python并不十分了解。
弧线肯定比pygame.draw.arc更好,但是当我将其与Mac上的屏幕渲染进行比较时,还有改进的余地。
答案 3 :(得分:0)
为自己使用,我编写了一个简单的包装函数,并且为了处理斑点弧,我使用了一个丑陋的循环多次绘制同一弧。
def DrawArc(surface, color, center, radius, startAngle, stopAngle, width=1):
width -= 2
for i in range(-2, 3):
# (2pi rad) / (360 deg)
deg2Rad = 0.01745329251
rect = pygame.Rect(
center[0] - radius + i,
center[1] - radius,
radius * 2,
radius * 2
)
pygame.draw.arc(
surface,
color,
rect,
startAngle * deg2Rad,
stopAngle * deg2Rad,
width
)
我知道这不是一个很好的解决方案,但是可以正常使用。
重要的一点是,我添加了“宽度-= 2”以希望至少更精确地保留了圆弧的预期大小,但这导致最小宽度增加了2。
对于您而言,您可能需要考虑做更多的事情来解决由此导致的问题。
答案 4 :(得分:0)
你是对的,一些 pygame 渲染函数确实很糟糕,所以你可以用 PIL
来实现类似的功能。
pie_size = (40, 40) # defining constants
pil_img = PIL.Image.new("RGBA", pie_size) # PIL template image
pil_draw = PIL.ImageDraw.Draw(pil_img) # drawable image
pil_draw.pieslice((0, 0, *[ps - 1 for ps in pie_size]), -90, 180, fill=(0, 0, 0)) # args: (x0, y0, x1, y1), start, end, fill
这将创建一个 PIL 形状。现在我们可以将其转换为 pygame。
data = pil_img.tobytes()
size = pil_img.size
mode = pil_img.mode
pygame_img = pygame.image.fromstring(data, size, mode)
但不要忘记pip install pillow
和
import PIL.Image
import PIL.ImageDraw