Pygame instanzen unterscheiden

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Ben_Dektor
User
Beiträge: 9
Registriert: Donnerstag 28. Februar 2019, 16:28

Hallo,

ich habe ein Programm mit Python geschrieben, welches ein Fenster mit Kästen zeichnet, wobei man die Zeilen und Spalten mit variablen bestimmt und dadurch eine Anzahl an gleich großen Kästen gezeichnet wird.
Jetzt wollte ich die Farben der Kästen ändern wenn der Mauszeiger drüber fährt. Soweit bin ich aber noch nicht gekommen weil ich es nicht geschafft habe die einzelnen Instanzen der Klasse Kästen aufzurufen, da diese als Instanzen in der Liste gespeichert werden und nicht als Variablen und dadurch die Schleife for neuerkasten in kastenliste nicht funktioniert.

Hat jemand eine Idee wie ich die Instanzen einzeln aufrufen kann (auch in einer Schleife) und somit verändern kann.

Danke im voraus.

Bin neu hier und neu beim Programmieren also auch andere Tipps geben

Code: Alles auswählen

import pygame

aktiv = True


class Kastenklasse():
    def __init__(self,farbe,xposition,yposition,groese,randdicke):
        self.farbe = farbe
        self.xpos = xposition
        self.ypos = yposition
        self.groese = groese
        self.randdicke = randdicke
        
    def zeichneKasten(self):
        pygame.draw.rect(screen,self.farbe,[self.xpos,self.ypos,self.groese,self.groese],0) 
        pygame.draw.rect(screen,[255,255,255],[self.xpos,self.ypos,self.groese,self.groese],self.randdicke) 
        
    def get_xy_bereich(self):
        xbereich = self.xpos, self.xpos + self.groese
        ybereich = self.ypos, self.ypos + self.groese
        return xbereich , ybereich
    
anzahl_zeilen = 4
anzahl_spalten = 4
kastengroese = 30
hintergrundfarbe = [255,255,255]
randdicke = 1
kastenfarbe = [0,0,0]
randdicke = 1

screen = pygame.display.set_mode([anzahl_spalten*kastengroese,anzahl_zeilen*kastengroese]) #fensterkastengroese entspricht anzahl reihen und spalten
screen.fill(hintergrundfarbe)


kastenliste = []


x = 0
y = 0


for i in range(anzahl_zeilen*anzahl_spalten):
    
    neuerkasten = Kastenklasse(kastenfarbe,x,y,kastengroese,randdicke)
    neuerkasten.zeichneKasten()
    kastenliste.append(neuerkasten)
    
    x = x+kastengroese
    if (i+1)%anzahl_spalten==0:                                             #hier wird in eine neue reihe gewechselt    
        y = y+kastengroese
        x = 0
    pygame.display.flip()
    

    
    
while aktiv:
            Mausposition = pygame.mouse.get_pos()
            #print kastenliste
            
            
            for event in pygame.event.get():
                #for neuerkasten in kastenliste:
                    #print kastenliste[neuerkasten]
                    #if Mausposition[0]<kastenliste[0] and Mausposition[1]<15:
        
                    #pygame.display.flip()
                    if event.type == pygame.QUIT:
                            aktiv = False  
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du musst halt durch alle Kaesten durchlaufen, und pruefen, ob ihr Rechteck die Mausposition beinhaltet. Wenn du statt dem etwas muehseligen

[self.xpos,self.ypos,self.groese,self.groese]

gleich eine pygame.Rect-Instanz anlegst, ist dieser Test sehr einfach:

Code: Alles auswählen

class Kastenklasse():

     def __init__(self, ...):
           self._rect = pygame.Rect( xposition,  yposition, groese, groese)

     ...
     def __contains__(self, point):
           return self._rect.collidepoint(point)

for kasten in kaesten:
     if mousepos in kasten:
             ....
Ben_Dektor
User
Beiträge: 9
Registriert: Donnerstag 28. Februar 2019, 16:28

__deets__ hat geschrieben: Donnerstag 28. Februar 2019, 17:11 Du musst halt durch alle Kaesten durchlaufen, und pruefen, ob ihr Rechteck die Mausposition beinhaltet. Wenn du statt dem etwas muehseligen

[self.xpos,self.ypos,self.groese,self.groese]

gleich eine pygame.Rect-Instanz anlegst, ist dieser Test sehr einfach:

Code: Alles auswählen

class Kastenklasse():

     def __init__(self, ...):
           self._rect = pygame.Rect( xposition,  yposition, groese, groese)

     ...
     def __contains__(self, point):
           return self._rect.collidepoint(point)

for kasten in kaesten:
     if mousepos in kasten:
             ....
Danke für die Antwort kannst du mir noch erklären was das __contains__ macht
und wie dieses if mousepos in kasten funktioniert.

ich habs jetzt so verstanden, dass ich der Klasse kasten gleich ein self Attribut gebe das rect heißt wodurch ich collidepoint() einfacher nutzen kann. Des point in collidepoint(point) sollen die Mauskoordinaten sein und wenn die Mauskoordinaten im Rechteck sind wird True ausgegeben aber dieses if mousepos in kasten hab ich nicht ganz verstanden und ich kann dieses __contains__ nicht schreiben da gibts eine Fehlermeldung ( ich weiß aber auch gar nicht was das ist).
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sowas kannst du durchaus auch selbst mal nachschauen - das ist ja alles dokumentiert.

__contains__ ruft Python auf, wenn man eben "x in a" hinschreibt. Dann muss a eine __contains__-Methode haben, und zurueck liefern ob x nun in a ist oder nicht. So wie von dir benoetigt.

Das du das nicht hinschreiben kannst kann nicht sein. Da ich es schon hunderte male hingeschrieben habe, liegt der Fehler wohl eher auf deiner Seite, und ohne sowohl deinen Code als auch die echte, ungekuerzte Fehlermeldung kann man dazu nur sagen "joa, bei mir geht's aber".
Ben_Dektor
User
Beiträge: 9
Registriert: Donnerstag 28. Februar 2019, 16:28

__deets__ hat geschrieben: Donnerstag 28. Februar 2019, 17:50 Sowas kannst du durchaus auch selbst mal nachschauen - das ist ja alles dokumentiert.

__contains__ ruft Python auf, wenn man eben "x in a" hinschreibt. Dann muss a eine __contains__-Methode haben, und zurueck liefern ob x nun in a ist oder nicht. So wie von dir benoetigt.

Das du das nicht hinschreiben kannst kann nicht sein. Da ich es schon hunderte male hingeschrieben habe, liegt der Fehler wohl eher auf deiner Seite, und ohne sowohl deinen Code als auch die echte, ungekuerzte Fehlermeldung kann man dazu nur sagen "joa, bei mir geht's aber".
Danke nochmal, ich hatte mich vertippt xD....... Und des war nicht die Fehlermeldung sondern ich wollte nur mitteilen dass ich gar nicht weiß was contains macht.
Hab auf YT wegen dem contains nachgeschaut und habs auf die schnelle nicht gefunden (die ist wahrscheinlich zu kompliziert xD) .
Zuletzt geändert von Ben_Dektor am Donnerstag 28. Februar 2019, 17:58, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn es jetzt klappt, ist ja gut. Und bitte nicht immer full-quote eines Beitrags, der direkt darueber steht. Das blaeht das Thema nur unnoetig auf.
Ben_Dektor
User
Beiträge: 9
Registriert: Donnerstag 28. Februar 2019, 16:28

Code: Alles auswählen

import pygame

aktiv = True


class Kastenklasse():
    def __init__(self,farbe,xposition,yposition,groese,randdicke):
        self._rect = pygame.Rect(xposition,yposition,groese,groese)
        self.farbe = farbe
        self.xpos = xposition
        self.ypos = yposition
        self.groese = groese
        self.randdicke = randdicke
        
    
    def __contains__(self,point):
        return self._rect.collidepoint(point)
        
    
    def zeichneKasten(self):
        pygame.draw.rect(screen,self.farbe,[self.xpos,self.ypos,self.groese,self.groese],0) 
        pygame.draw.rect(screen,[255,255,255],[self.xpos,self.ypos,self.groese,self.groese],self.randdicke) 
        
anzahl_zeilen = 2
anzahl_spalten = 2
kastengroese = 30
hintergrundfarbe = [255,255,255]
randdicke = 1
kastenfarbe = [0,0,0]
randdicke = 1

screen = pygame.display.set_mode([anzahl_spalten*kastengroese,anzahl_zeilen*kastengroese]) #fensterkastengroese entspricht anzahl reihen und spalten
screen.fill(hintergrundfarbe)


kastenliste = []


x = 0
y = 0


for i in range(anzahl_zeilen*anzahl_spalten):
    
    neuerkasten = Kastenklasse(kastenfarbe,x,y,kastengroese,randdicke)
    neuerkasten.zeichneKasten()
    kastenliste.append(neuerkasten)
    
    x = x+kastengroese
    if (i+1)%anzahl_spalten==0:                                             #hier wird in eine neue reihe gewechselt    
        y = y+kastengroese
        x = 0
    pygame.display.flip()
    

    
    
while aktiv:
            Mausposition = pygame.mouse.get_pos()
            
            
            
            for event in pygame.event.get():
                for neuerkasten in kastenliste:
                    if Mausposition in neuerkasten:
                        neuerkasten.farbe = [100,100,0]
                        neuerkasten.zeichneKasten
                        #print(neuerkasten.farbe)
                        pygame.display.flip()
        
                    
                    if event.type == pygame.QUIT:
                            aktiv = False  

Leider immer noch nicht geschafft, was ist hier noch falsch.
Muss ich den point in der __contains__ methode noch in __init__ definieren?
Weil das Programm irgendwie nicht in die __cotains__ Methode geht, aber in die if Mausposition in neuerkasten.
Ben_Dektor
User
Beiträge: 9
Registriert: Donnerstag 28. Februar 2019, 16:28

Fehler gefunden hab die runden Klammern beim zeichnen vergessen
Noch eine letzte Frage wenn ich das Programm starte wird automatisch bei einem Kasten ausen die farbe auf der höhe des mauszeigers verändert kann man des irgendwie deaktivieren des erst ein event ausglöst wird wenn der zeiger im bild ist.

Noch mal vielen vielen Dank
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie ist denn dann der Wert der mausposition?
Ben_Dektor
User
Beiträge: 9
Registriert: Donnerstag 28. Februar 2019, 16:28

__deets__ hat geschrieben: Donnerstag 28. Februar 2019, 19:34 Wie ist denn dann der Wert der mausposition?
In dem Beispiel mit 2 Reihen und 2 Spalten und Kastengroese 30, ist der Wert 59,59 und dann wird die farbe von dem Kasten rechts unten verändert obwohl ich beim starten nicht im Bild bin kann aber auch vllt sein das des an eclipse liegt
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hm. Laut Doku sollte das nicht so sein. Was du natürlich machen kannst ist einen 1 Pixel breiten Rand um deine Kästen zu lassen.
Ben_Dektor
User
Beiträge: 9
Registriert: Donnerstag 28. Februar 2019, 16:28

hatte ich aber eigentlich eh schon im Programm ich hab ja einen Kasten ohne rand gezeichnet und dann einen mit Rand wodurch ich die Farbe von Rand und Kasten bestimmen kann

Jetzt hab ich nen bug entdeckt xD erste Errungenschaft.
Antworten