Fehler beim Klicken auf das gestapelte Bild in Pygame [Duplikat]

Dec 01 2020

Ich habe einige Codes zum Klicken und Ziehen von Bildern erstellt, um sie irgendwann zu stapeln. Bei den ersten Klicks hat es gut funktioniert, aber wenn ich es mehrmals an derselben Stelle gestapelt habe, kann es plötzlich nicht mehr angeklickt werden. Wie kann ich das Problem beheben und wenn Sie in Ordnung sind, können Sie es kompakter gestalten?

import pygame
from pygame import *
import sys
import os

pygame.init()
s_width = 640
s_height = 480

screen = pygame.display.set_mode((s_width, s_height))
pygame.display.set_caption("TITLE")
bigfont = pygame.font.SysFont(None, 50)
smallfont = pygame.font.SysFont(None, 25)
title = bigfont.render("TITLE", True, (0,0,0))

current_path = os.path.dirname(__file__)
img_path = os.path.join(current_path, "images")

img_list = [] 
place_list = []
temp = []

class Img_Set:
    def __init__(self, path, x_pos, y_pos):
        self.image = pygame.image.load(path)
        self.x_pos = x_pos
        self.y_pos = y_pos
        self.rect = self.image.get_rect()
        self.rect.left = self.x_pos
        self.rect.top = self.y_pos
        img_list.append(self)
        self.click = False
    def offset(self):
        self.offset_len_x = event.pos[0] - self.x_pos
        self.offset_len_y = event.pos[1] - self.y_pos
    def drag(self):
        self.x_pos = event.pos[0] - self.offset_len_x
        self.y_pos = event.pos[1] - self.offset_len_y
        self.rect.left = self.x_pos
        self.rect.top = self.y_pos

class Place_Set:
    def __init__(self, path, x_pos, y_pos):
        self.image = pygame.image.load(path)
        self.x_pos = x_pos
        self.y_pos = y_pos
        self.rect = self.image.get_rect()
        self.rect.left = self.x_pos
        self.rect.top = self.y_pos
        place_list.append(self)
        self.click = False

img1 = Img_Set("images/80x80_blueball.png", s_width/3, s_height/3)
img2 = Place_Set("images/80x80_ball.png", s_width/2, s_height/3)
img3 = Place_Set("images/80x80_greenball.png", s_width/3*2, s_height/3)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:
            if event.button == 1:
                for x in img_list:
                    if x.rect.collidepoint(event.pos):
                        temp.append(x)
                if len(temp) > 0:
                    temp[-1].offset()
                    temp[-1].click = True
                    img_list.remove(temp[-1])
                    img_list.append(temp[-1])
                    temp = []
        elif event.type == MOUSEMOTION:
            for x in img_list:
                    if x.click:
                        x.drag()
        elif event.type == MOUSEBUTTONUP:
            for x in img_list:
                for y in place_list:
                    if x.rect.colliderect(y.rect):
                        x.x_pos = y.x_pos
                        x.y_pos = y.y_pos
            for x in img_list:
                x.click = False
        screen.fill((255, 255, 255))
        for x in place_list:
            screen.blit(x.image, (x.x_pos, x.y_pos))
        for x in img_list:
            screen.blit(x.image, (x.x_pos, x.y_pos))


    pygame.display.update()

Der Code, der gif ausführt, befindet sich unten.

https://i.stack.imgur.com/vAQyU.gif

Antworten

2 Rabbid76 Dec 01 2020 at 23:31

Sie haben das rectAttribut nicht aktualisiert , als die Maustaste losgelassen wurde. Wenn das Bild verschieben, führt dies zu einem Fehler zwischen der Versatz x, yund das rectAttribut:

while True:
    for event in pygame.event.get():
         # [...]

         elif event.type == MOUSEBUTTONUP:
            for x in img_list:
                for y in place_list:
                    if x.rect.colliderect(y.rect):
                        x.x_pos = y.x_pos
                        x.y_pos = y.y_pos
                        x.rect.left = y.x_pos          # <-- ADD
                        x.rect.top = y.y_pos           # <-- ADD


Allerdings müssen Sie nicht die xund yAttribute überhaupt. Verwenden Sie stattdessen den im Attribut rect gespeicherten Speicherort:

import pygame
from pygame import *
import sys
import os

pygame.init()
s_width = 640
s_height = 480

screen = pygame.display.set_mode((s_width, s_height))
pygame.display.set_caption("TITLE")
bigfont = pygame.font.SysFont(None, 50)
smallfont = pygame.font.SysFont(None, 25)
title = bigfont.render("TITLE", True, (0,0,0))

current_path = os.path.dirname(__file__)
img_path = os.path.join(current_path, "images")

img_list = [] 
place_list = []
temp = []

class Img_Set:
    def __init__(self, path, x_pos, y_pos):
        self.image = path # pygame.image.load(path)
        self.rect = self.image.get_rect()
        self.rect.left = x_pos
        self.rect.top = y_pos
        img_list.append(self)
        self.click = False
    def offset(self):
        self.offset_len_x = event.pos[0] - self.rect.x
        self.offset_len_y = event.pos[1] - self.rect.y
    def drag(self):
        self.rect.x = event.pos[0] - self.offset_len_x
        self.rect.y = event.pos[1] - self.offset_len_y

class Place_Set:
    def __init__(self, path, x_pos, y_pos):
        self.image = path # pygame.image.load(path)
        self.rect = self.image.get_rect()
        self.rect.left = x_pos
        self.rect.top = y_pos
        place_list.append(self)
        self.click = False

img1 = Img_Set("images/80x80_blueball.png", s_width/3, s_height/3)
img2 = Place_Set("images/80x80_ball.png", s_width/2, s_height/3)
img3 = Place_Set("images/80x80_greenball.png", s_width/3*2, s_height/3)

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:
            if event.button == 1:
                for x in img_list:
                    if x.rect.collidepoint(event.pos):
                        temp.append(x)
                if len(temp) > 0:
                    temp[-1].offset()
                    temp[-1].click = True
                    img_list.remove(temp[-1])
                    img_list.append(temp[-1])
                    temp = []
        elif event.type == MOUSEMOTION:
            for x in img_list:
                    if x.click:
                        x.drag()
        elif event.type == MOUSEBUTTONUP:
            for x in img_list:
                for y in place_list:
                    if x.rect.colliderect(y.rect):
                        x.rect.x = y.rect.x
                        x.rect.y = y.rect.y
            for x in img_list:
                x.click = False
        screen.fill((255, 255, 255))
        for x in place_list:
            screen.blit(x.image, x.rect)
        for x in img_list:
            screen.blit(x.image, x.rect)

    pygame.display.update()