kil*_*rp7 6 python pygame list nested-lists
我正在尝试制作一个 python 程序来绘制一条线,然后使用 pygame 将其变成带有动画的圆圈,但我什至还没有完成绘制线的代码。我注意到python正在更改列表中的错误或两个项目,其中包含用户按下左键单击时的起点,存储为第一个项目,用户鼠标的当前点存储为第二个项目。
这通常是我想要它做的: https: //youtu.be/vlqZ0LubXCA
以下是包含和不包含更新第二项的行的结果:
和:
没有:
正如您所看到的或在描述中阅读的,这条线是覆盖前一帧所必需的。
我用箭头标记了改变结果的行:
import pygame, PIL, random
print('\n')
#data
bubbles = []
color_options = [[87, 184, 222]]
pressed = False
released = False
bubline_start = []
background = [50, 25, 25]
size = [500, 500]
#pygame
display = pygame.display.set_mode(size)
pygame.init()
#functions
def new_bub_color():
color_index = random.randint(0, len(color_options)-1)
lvl = random.randrange(85, 115)
bub_color = []
for val in color_options[color_index]:
bub_color.append(val*(lvl/100))
return bub_color
def bubble_line():
global display, pressed, bubline_start, released, bubbles, color_options
if len(bubbles) > 0:
if not bubbles[-1][0] == 0:
#first frame of click
bub_color = new_bub_color()
bubbles.append([0, bub_color, [bubline_start, list(pygame.mouse.get_pos())]])
pygame.draw.line(display, bub_color, bubline_start, pygame.mouse.get_pos())
else:
#draw after drags
pygame.draw.line(display, bubbles[-1][1], bubbles[-1][2][0], list(pygame.mouse.get_pos()))
bubbles[-1][2][1] = list(pygame.mouse.get_pos())# <-- HERE
else:
#first bubble
bub_color = new_bub_color()
bubbles.append([0, bub_color, [bubline_start, list(pygame.mouse.get_pos())]])
pygame.draw.line(display, bub_color, bubline_start, pygame.mouse.get_pos())
if released:
bubbles[-1][0] = 1
bubbles[-1][2][1] = list(pygame.mouse.get_pos())# <-- HERE
released = False
def cover_prev_frame():
global bubbles, background, size
min_pos = []
max_pos = []
for bubble in bubbles:
min_pos = bubble[2][0]
max_pos = bubble[2][0]
for point in bubble[2]:
#x min and max
if point[0] < min_pos[0]:
min_pos[0] = point[0]
elif point[0] > max_pos[0]:
max_pos[0] = point[0]
#y min and max
if point[1] < min_pos[1]:
min_pos[1] = point[1]
elif point[1] > max_pos[1]:
max_pos[1] = point[1]
max_pos = [max_pos[0]-min_pos[0]+1, max_pos[1]-min_pos[1]+1]
if type(background) == str:
#image background
later = True
elif type(background) == list:
#solid color background
pygame.draw.rect(display, background, pygame.Rect(min_pos, max_pos))
while True:
pygame.event.pump()
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.MOUSEBUTTONDOWN and not pressed:
bubline_start = list(pygame.mouse.get_pos())
pressed = True
elif event.type == pygame.MOUSEBUTTONUP and pressed:
pressed = False
released = True
cover_prev_frame()
if pressed or released:
bubble_line()
try:
pygame.display.update()
except:
break
Run Code Online (Sandbox Code Playgroud)
Rab*_*d76 18
if not bubbles[-1][0] == 0:False只要鼠标不松开。因此,添加许多线段,每条线段bubline_start从当前鼠标位置开始并结束。
您必须重新绘制每一帧中的场景。bubbles是一个气泡列表,每个气泡都有一个点列表。按住鼠标的同时将新点添加到列表中的最后一个气泡。按下鼠标时开始一个新的气泡,松开鼠标时结束一个气泡。这极大地简化了您的代码。
最小的例子
import pygame, random
size = [500, 500]
pygame.init()
display = pygame.display.set_mode(size)
clock = pygame.time.Clock()
pressed = False
bubbles = []
background = [50, 25, 25]
run = True
while run:
clock.tick(100)
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.MOUSEBUTTONDOWN:
start_pos = list(event.pos)
bubble_color = pygame.Color(0)
bubble_color.hsla = (random.randrange(0, 360), 100, 50, 100)
bubbles.append((bubble_color, [start_pos]))
pressed = True
elif event.type == pygame.MOUSEMOTION and pressed:
new_pos = list(event.pos)
if len(bubbles[-1][1]) > 0 and bubbles[-1][1] != new_pos:
bubbles[-1][1].append(new_pos)
elif event.type == pygame.MOUSEBUTTONUP:
pressed = False
end_pos = list(event.pos)
if len(bubbles[-1][1]) > 0 and bubbles[-1][1] != end_pos:
bubbles[-1][1].append(list(event.pos))
display.fill(background)
for i, bubble in enumerate(bubbles):
if len(bubble[1]) > 1:
closed = not pressed or i < len(bubbles) - 1
pygame.draw.lines(display, bubble[0], closed, bubble[1], 3)
pygame.display.update()
pygame.quit()
Run Code Online (Sandbox Code Playgroud)
对于动画,我建议创建一个代表气泡的类和一个animate将多边形慢慢变成圆形的方法。
最小的例子
import pygame, random
size = [500, 500]
pygame.init()
display = pygame.display.set_mode(size)
clock = pygame.time.Clock()
class Bubble:
def __init__(self, start):
self.color = pygame.Color(0)
self.color.hsla = (random.randrange(0, 360), 100, 50, 100)
self.points = [list(start)]
self.closed = False
self.finished = False
def add_point(self, point, close):
self.points.append(list(point))
self.closed = close
if self.closed:
x_, y_ = list(zip(*self.points))
x0, y0, x1, y1 = min(x_), min(y_), max(x_), max(y_)
rect = pygame.Rect(x0, y0, x1-x0, y1-y0)
self.center = rect.center
self.radius = max(*rect.size) // 2
def animate(self):
if self.closed and not self.finished:
cpt = pygame.math.Vector2(self.center) + (0.5, 0.5)
self.finished = True
for i, p in enumerate(self.points):
pt = pygame.math.Vector2(p)
v = pt - cpt
l = v.magnitude()
if l + 0.5 < self.radius:
self.finished = False
v.scale_to_length(min(self.radius, l+0.5))
pt = cpt + v
self.points[i] = [pt.x, pt.y]
def draw(self, surf):
if self.finished:
pygame.draw.circle(surf, self.color, self.center, self.radius, 3)
elif len(self.points) > 1:
pygame.draw.lines(surf, self.color, self.closed, self.points, 3)
bubbles = []
pressed = False
background = [50, 25, 25]
run = True
while run:
clock.tick(100)
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.MOUSEBUTTONDOWN:
bubbles.append(Bubble(event.pos))
pressed = True
elif event.type == pygame.MOUSEMOTION and pressed:
bubbles[-1].add_point(event.pos, False)
elif event.type == pygame.MOUSEBUTTONUP:
bubbles[-1].add_point(event.pos, True)
pressed = False
for bubble in bubbles:
bubble.animate()
display.fill(background)
for bubble in bubbles:
bubble.draw(display)
pygame.display.update()
pygame.quit()
Run Code Online (Sandbox Code Playgroud)