python - 按属性排序后如何从屏幕上的列表中删除对象?

标签 python sorting pygame

我尝试使用 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/

相关文章:

python - 类型错误: 'int' 对象在 Python 3.2 中不可调用?

python - 为什么 numpy 混合基本/高级索引取决于切片邻接?

python - 如何用 Python 替换 CSV 文件中的列?

python - 如何pickle从dict派生的python对象

java - java8 按降序对映射进行排序

python - Pygame 具有类似流体的特征

Python 运行时与 C 运行时

java - 使用 Java Comparator 自定义排序 - 保留具有特定值的对象的位置

c# - MongoDB 按 "starts with"排序

python - 如何在 mac OSX 10.9.4 上卸载 pygame