我尝试使用 pygame 在 Python 中按高度制作一个简单的线排序算法。
这个想法很简单。从类中生成 100 个具有随机值高度属性的对象实例到列表中,然后将它们绘制到显示器上。 单击右键盘箭头后,使用排序功能将列表中的对象按高度属性排序并重新绘制。
出于某种原因,它总是绘制列表的未排序/列表版本。所以要么它不能很好地按属性对对象进行排序,要么我在其他地方犯了一个错误。
谁能帮我找出问题所在?
import pygame
import random
import operator
from colors import color_dict
# Initialize pygame essentials
pygame.init()
# Load the background image
image = pygame.image.load("bg.jpg")
image_rect = image.get_rect()
# Screen settings
DISPLAY_WIDTH = 1000
DISPLAY_HEIGHT = 400
# Colors
WHITE = (255, 255, 255)
SCREEN_BG_COLOR = (30, 30, 30)
# Time / FPS
FPS = 1000
# Set the main preview display/window with width and height
display = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))
# Draw the display shape sized and positioned as display
# so we can use its coordinates for positioning other elements
display_rect = display.get_rect()
pygame.display.set_caption("Sorting algorithm")
clock = pygame.time.Clock()
# Width of the line (change for the total number of lines)
line_width = 10
# Total number of lines in the screen
total_lines = int(display.get_width() / line_width)
# Store all drawn lines in the list
drawn_lines = []
line_group = pygame.sprite.Group()
class Line(pygame.sprite.Sprite):
"""A class to manage a single line parameters"""
def __init__(self, color):
super(Line, self).__init__()
self.width = line_width # 10
self.height = random.randint(-400, 0)
self.color = color
self.surface = pygame.Surface((self.width, abs(self.height)))
self.surface.fill(self.color)
self.rect = self.surface.get_rect()
self.rect.x = display_rect.bottomleft[0]
self.rect.bottom = display_rect.bottom
def generate_lines():
"""Generate lines across the screen"""
# Set the random color for every line generation cycle
new_color = random.choice(list(color_dict))
new_color = str(new_color)
# Create the total_lines amount of objects and fill the line list with them
line_x_position = 0
for _ in range(total_lines):
line = Line(new_color)
line.rect.x += line_x_position
drawn_lines.append(line)
line_group.add(line)
line_x_position += line_width
def draw_lines():
"""Draw the generated lines from the line list"""
for line in drawn_lines:
display.blit(line.surface, line.rect)
def redraw_lines():
"""Empty the list filled with line objects.
Generate new lines and redraw them on the screen again."""
drawn_lines.clear()
generate_lines()
draw_lines()
def sort():
"""Sort the objects inside the line list by height"""
drawn_lines.sort(key=operator.attrgetter('height'))
def draw_sorted():
for line in drawn_lines:
display.blit(line.surface, line.rect)
def main():
"""The main loop"""
is_generated = False
is_sorted = False
while True:
# Handle the user input events
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
redraw_lines()
elif event.key == pygame.K_RIGHT:
sort()
is_sorted = True
# Generate lines in list
if not is_generated:
generate_lines()
is_generated = True
# Draws the background image
display.fill(SCREEN_BG_COLOR)
if not is_sorted:
draw_lines()
else:
draw_sorted()
# Refresh/update the images on the display
pygame.display.update()
clock.tick(FPS)
main()
pygame.quit()
最佳答案
每条 Line
都是用 line.rect
属性中存储的大小和位置绘制的。因此,仅对列表进行排序是不够的。您还需要更新直线矩形的 x 坐标。您有 2 种可能性。
选项 1:在对列表进行排序时更新 line.rect.x
坐标:
def sort():
"""Sort the objects inside the line list by height"""
drawn_lines.sort(key=operator.attrgetter('height'))
line_x_position = 0
for line in drawn_lines:
line.rect.x = line_x_position
line_x_position += line_width
选项2:绘制线时根据列表中的位置计算x坐标:
def draw_sorted():
line_x_position = 0
for line in drawn_lines:
sorted_line_rect = line.rect.copy()
sorted_line_rect.x = line_x_position
line_x_position += line_width
display.blit(line.surface, sorted_line_rect)
关于python - 按属性排序后如何从屏幕上的列表中删除对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69417585/