Seite 1 von 2

Problem mit coords

Verfasst: Montag 14. April 2008, 16:43
von Kalkas
Hi,

da ich noch relativ neu in diesem gebiet bin verbessert mich bzw fragt weiter


Das ganze soll irgendwann einmal ein jump&run spiel werden.

In der Methode try_everything soll getestet werden ob sich der Spieler(roter Kreis) noch nach rechts bzw nach links bewegen darf, oder ob er fällt weil er keinen boden mehr unter den "füßen" hat.

Das funktioniert beim vorwärts bewegen und beim "fallen" recht gut, self.FALL und self.FORWARD haben immer den zu erwartenden wert, jedoch funktionier dies bei self.BACK nicht.

Wenn sich das Objekt dem Kreis annähert und dann irgendwann die rechte obere seite des Kreises (world.coords(self.item)[0]) den gleichen x wert hat wie die obere linke seite eines anderen objekts (world.coords(environment_list.item)[0]) und ein paar andere bedingungen erfüllt sind bedeutet das, dass der kreis sich nichtmehr in diese richtung bewegen darf.

aber alleine diese erste bedingung in z 79 (if world.coords(self.item)[0] == world.coords(environment_list[2].item)[2]: ) wird erfüllt obwohl sie den gleichen wert annehmen, wenn man mehrfach nach links drückt.


Ich nehms keinem übel wenn er das nicht versteht was ich da schreib, aber ich weiß einfach nicht wie ichs erklären soll

:cry:


Code:

Code: Alles auswählen

from Tkinter import *
from time import *


            
            
class Foreground:
    def __init__(self,x1,y1,x2,y2):
        self.x1=x1
        self.y1=y1
        self.x2=x2
        self.y2=y2

        self.BACK=True
        self.FORWARD=True
        self.FALL=False

        self.color="black"
        self.fall_counter=0
        
        self.draw_me()

    def draw_me(self):
                
        self.item = world.create_rectangle(self.x1,self.y1,self.x2,self.y2,fill="black")
        world.itemconfig(self.item, fill=self.color)
        
    def set_fill(self,color):
        self.color=color
        
        world.itemconfig(self.item, fill=self.color)


class Player(Foreground):
        
    
    def draw_me(self):
        
        
        self.item = world.create_oval(self.x1,self.y1,self.x2,self.y2,fill="black")
        world.itemconfig(self.item, fill=self.color)
    def go_forward(self,environment_list):
        self.environment_list=environment_list

        for i in range(len(self.environment_list)):
                       world.move(self.environment_list[i].item,-5,0)
                       world.update()
        self.try_everything()
        
    def go_back(self,environment_list):
        self.environment_list=environment_list

        for i in range(len(self.environment_list)):
                       world.move(self.environment_list[i].item,+5,0)
                       world.update()
        self.try_everything()
    def try_everything(self):
        x=0     
        for i in range(len(environment_list)):
            if world.coords(self.item)[3]==world.coords(environment_list[i].item)[1]:
                if world.coords(self.item)[2]>world.coords(environment_list[i].item)[0]:
                    if world.coords(self.item)[0]<world.coords(environment_list[i].item)[2]:
                        self.FALL=False
                        x=1
        if x==0:
            self.FALL=True
        x=0
        for i in range(len(environment_list)):
            if world.coords(self.item)[2]==world.coords(environment_list[i].item)[0]:
                if world.coords(self.item)[3]>=world.coords(environment_list[i].item)[1]:
                    if world.coords(self.item)[1]<=world.coords(environment_list[i].item)[3]:
                        self.FORWARD=False
                        x=1
        if x==0:
            self.FORWARD=True
        print world.coords(self.item)[0],world.coords(environment_list[2].item)[2]
        x=0
        for i in range(len(environment_list)):
            if world.coords(self.item)[0] == world.coords(environment_list[2].item)[2]:
                if world.coords(self.item)[3]>=world.coords(environment_list[i].item)[1]:
                    if world.coords(self.item)[1]<=world.coords(environment_list[i].item)[3]:
                        self.BACK=False
                        x=1
        if x==0:
            self.BACK=True
        print self.FALL,self.FORWARD,self.BACK
        
        
    def fall(self):
        pass
        
    
                
                
class Environment(Foreground):
    pass
        
def vorwaerts(event):
    Mario.go_forward(environment_list)
    
def rueckwaerts(event):
    Mario.go_back(environment_list)



    
    
window = Tk()
world = Canvas(window,bg = "white",width=1100,height=600)
world.pack()

environment_list=[]


Mario= Player(500,400,600,500)
environment_list.append(Environment(0,500,10000,600))
environment_list.append(Environment(800,300,900,400))
environment_list.append(Environment(200,400,300,500))

Mario.set_fill("red")


world.bind_all("<Right>",vorwaerts)
world.bind_all("<Left>",rueckwaerts)




window.resizable(width=0,height=0)
window.mainloop()

Verfasst: Montag 14. April 2008, 19:15
von numerix
Vielleicht wird es für dich und andere leichter nachvollziehbar, wenn du den Code erstmal ein wenig zum Positiven hin überarbeitest. Das gilt z.B. für deine Schleifen, wo du direkt über die Elemente aus der environment_list iterieren kannst. Guckst du hier:

Code: Alles auswählen

>>> tiere = ["Hund","Katze","Affe","Ratte","Pferd"]
>>> for k in range(len(tiere)):
...     print tiere[k]
...
Hund
Katze
Affe
Ratte
Pferd
>>> for tier in tiere:
...     print tier
...
Hund
Katze
Affe
Ratte
Pferd
Du benutzt die erste Variante, die zweite ist die "richtige".

Bei der Farbgebung hast du ein überflüssiges itemconfig. Setz doch gleich die richtige Farbe, statt erst "black" und dann die Wunschfarbe (die ist zwar auch noch "black", aber das willst du vermutlich später noch ändern).

Vielleicht hat sich das Problem dann schon von selbst gelöst.

Verfasst: Montag 14. April 2008, 19:43
von EyDu
Hallo und willkommen im Forum!

Hab' auch noch ein paar Dinge:

Die Klase "Foreground" sollte noch von "object" erben.

Die Koordinaten "x1,x2,y1,y2" würde ich als Tupel erstellen:

Code: Alles auswählen

self.coord1 = (x1, y1)
self.coord2 = (x2, y2)
Bei der Gelegenheit solltest du dier dafür auch einen richtigen Nameneinfallen lassen, zweistellige Bezeichner sind oft sehr nichtssagend.

Dann kannst du neben der bereits erwähnten Vereinfachung der for-Schleifen diese noch weiter vereinfachen:

Dies

Code: Alles auswählen

        x=0     
        for i in range(len(environment_list)):
            if world.coords(self.item)[3]==world.coords(environment_list[i].item)[1]:
                if world.coords(self.item)[2]>world.coords(environment_list[i].item)[0]:
                    if world.coords(self.item)[0]<world.coords(environment_list[i].item)[2]:
                        self.FALL=False
                        x=1
        if x==0:
            self.FALL=True
wird zu:

Code: Alles auswählen

        wc = world.coords(self.item)
        ec = world.coords(env.item)
        for env in range(environment_list):
            if wc[3]==ec[1] and wc[2]>ec[0] and wc[0]<ec[2]:
                self.FALL=False
                break
        else:
            self.FALL=True
Alternativ kannst du den else-Teil auch weglassen und vor der schleife "self.FALL" auf "True" setzen.

Dann hast du im unteren Teil noch sehr viel Code auf modulebene, packe das mal in eine main-Funktion.

Auch die Environment-Liste kannst du ganz ohne append erstellen:

Code: Alles auswählen

environment_list = [
    Environment(0,500,10000,600),
    Environment(800,300,900,400),
    Environment(200,400,300,500)
]
Schau dir doch bitte noch mal PEP8 an.

Lass die *-Importe.

Dann könntest du noch ein paar Konstanten einführen, damit im Quellcode nicht überall Zahlen durch die Gegend fliegen.

Und nicht zu vernachlässigen: es fehlen Kommentare!

Verfasst: Montag 14. April 2008, 20:29
von Kalkas
danke schonmal für euer feedback, ich werde eure ratschläge mal in meinen code einbauen :wink:

Verfasst: Dienstag 15. April 2008, 18:37
von Kalkas
So, ich habe mal den code überarbeitet aber meinen fehler nicht gefunden :(

muss irgendwo in meiner try_everything() methode liegen


Code: Alles auswählen

from Tkinter import *
from time import *


            
            
class Foreground(object):
    def __init__(self, x1, y1, x2, y2):
        self.coord1 = (x1, y1)
        self.coord2 = (x2, y2)


        self.BACK=True    #wird False, wenn die linke Seite des roten Kreises
                          #an die rechte Seite eines schwarzen Objekts stößt
                          #  FUNKTIONIERT NICHT!                             
                   
        self.FORWARD=True #wird False, wenn die rechte Seite des roten Kreises
                          #an die linke Seite eines schwarzen Objekts stößt
        
        self.FALL=False   #wird False, wenn die untere Seite des roten Kreises 
                          #auf der oberen Seite eines schwarzen Objekts liegt

        self.color="black"
        self.fall_counter=0
        
        self.draw_me()

    def draw_me(self):
        self.item = world.create_rectangle(self.coord1[0],self.coord1[1],
                                           self.coord2[0],self.coord2[1],
                                           fill="black")
        
        
    def set_fill(self, color):
        self.color=color
        world.itemconfig(self.item, fill=self.color)


class Player(Foreground):
        
    
    def draw_me(self):
        self.item = world.create_oval(self.coord1[0],self.coord1[1],
                                      self.coord2[0],self.coord2[1],
                                      fill="black")
       
        
    def go_forward(self,environment_list):
        self.environment_list = environment_list

        for i in self.environment_list:
                       world.move(i.item,-5,0)
                       world.update()
        self.try_everything()
        
    def go_back(self, environment_list):
        self.environment_list = environment_list

        for i in self.environment_list:
                       world.move(i.item,+5,0)
                       world.update()
        self.try_everything()
        
    def try_everything(self):
        pc = world.coords(self.item)
        for i in self.environment_list: 
            if pc[3] == world.coords(i.item)[1] and \
               pc[2] > world.coords(i.item)[0] and \
               pc[0] < world.coords(i.item)[2]:
                self.FALL = False
                break
        else:
            self.FALL=True
            
        for i in self.environment_list:
            if pc[2] == world.coords(i.item)[0] and \
               pc[3] > world.coords(i.item)[1] and \
               pc[1] < world.coords(i.item)[3]:
                 self.FORWARD=False
                 break
        else:
            self.FORWARD=True
            
        for i in self.environment_list:
            if pc[0] == world.coords(i.item)[2] and \
               pc[3] > world.coords(i.item)[1]and \
               pc[1] < world.coords(i.item)[3]: 
                self.BACK=False
                break
        else:
            self.BACK=True
            
        print self.FALL,self.FORWARD,self.BACK
        
        
    def fall(self):
        pass
        
    
                
                
class Environment(Foreground):
    pass
        
def vorwaerts(event):
    Mario.go_forward(environment_list)
    
def rueckwaerts(event):
    Mario.go_back(environment_list)


def main():
    global window, world, Mario, environment_list
    
    window = Tk()
    world = Canvas(window, bg = "white", width=1100, height=600)
    world.pack()

    environment_list = [
        Environment(0,500,10000,600),
        Environment(800,300,900,400),
        Environment(200,400,300,500),
        Environment(700,300,800,500)
    ]


    Mario= Player(500, 400, 600, 500)
    Mario.set_fill("red")


    world.bind_all("<Right>", vorwaerts)
    world.bind_all("<Left>", rueckwaerts)
    
    window.resizable(width=0, height=0)
    window.mainloop()

    
main()



Beim ausprobieren stellt man fest das self.BACK sich nie ändert

Verfasst: Dienstag 15. April 2008, 18:54
von BlackJack
Das wird grundsätzlich in Zeile 89 an `True` gebunden.

Verfasst: Dienstag 15. April 2008, 19:01
von Kalkas
ups, ich hab break dort, vergessen

mit break funktionierts leider auch nicht :(

(ich editier ma den code oben)

Verfasst: Dienstag 15. April 2008, 19:20
von numerix
Du bist einem besonderen "Feature" von Python erlegen:

Deine else-Anweisungen sollen sich auf die vorherige if-Anweisung beziehen - tun sie aber nicht. Stattdessen beziehen sie sich auf die for-Schleifen, das gibt es in Python nämlich auch (wobei man das m.E. wirklich selten sinnvoll nutzen kann). Also: Einrückungstiefe ändern und dann nochmal schauen ...

Verfasst: Dienstag 15. April 2008, 19:40
von EyDu
Die Einrückung ist schon genau richtig, du musst dir nur mal den ersten Post von Kalkas anschauen.

Verfasst: Dienstag 15. April 2008, 20:23
von Kalkas
Also die Schleifen habe ich auch EyDU's anweisung geändert und es passt auch, sie funktionieren wie geplant, die funktionalität ist die selbe wie davor.

die ersten beide schleifen machen genau was ich will nur die letzte nicht und ich weiß nicht warum :(

ich muss irgend einen denkfehler bei den if anweisungen gemacht haben, aber ich komme einfach nicht dahinter

Verfasst: Dienstag 15. April 2008, 22:44
von EyDu
So, ich habe jetzt mal ein wenig mit dem Code rumgespielt, jetzt läuft das Programm so, wie ich es erwarten würde:

Code: Alles auswählen

    def go_forward(self,environment_list):
        self.environment_list = environment_list 
        self.try_everything()

        if self.FORWARD:
            for i in self.environment_list: 
                           world.move(i.item,-5,0) 
                           world.update()  
        
    def go_back(self, environment_list):
        self.environment_list = environment_list
        self.try_everything()
        
        if self.BACK:
            for i in self.environment_list: 
                           world.move(i.item,+5,0) 
                           world.update()

Verfasst: Dienstag 15. April 2008, 22:56
von Kalkas
und genau das funktioniert bei mir nich :/


bei der bewegung nach vorne stoppt er wie erwartet aber beim der bewegung zurück gehts bei mir nich...

meine 2 bewegungsmethoden wollte ich erst weiterschreiben wenn das mit der überprüfung überall geklappt hätte und da es bei mir beim rückwärtslaufen nicht funktioniert stoppt er auch nicht

hast du sonst noch was verändert? wie gesagt bei mir wird self.BACK niemals "False"

Verfasst: Dienstag 15. April 2008, 23:01
von EyDu
Hier mal mein kompletter Code:

http://paste.pocoo.org/show/40826/

Verfasst: Dienstag 15. April 2008, 23:05
von Kalkas
Eben deinen code kopiert und ausgeführt und er geht nicht.

Wenn in links drücke geht der rote kreis einfach durch den schwarzen block durch, ist das bei dir anders? :>

Verfasst: Dienstag 15. April 2008, 23:11
von EyDu
Das funktioniert bei mir ziehmlich gut. Eben bin ich einmal durch eine Wand gehüpft als ich RIGHT dauerhaft gedrückt habe, aber normalerweise bleibe ich daran stehen. Sowohl links als auch rechts.

Hast du das Problem auch, wenn du mit einzelnen Tastenanschlägen dich der Wand näherst? Denn sonst würde ich das Problem am "==" vermuten.

Verfasst: Dienstag 15. April 2008, 23:22
von Kalkas
<RIGHT> klappt bei mir wunderbar, aber <LEFT> funktioniert garnicht, egal ob kurz drücken oder gedrückt halten.

Woran kann denn sowas liegen wenns beim einen klappt und beim anderen nicht? am betriebsystem? an der python version?

edit:

gerade wo gelesen das IDLE und Tkinter sich nicht so mögen, ich werds mal anders probieren das programm zu starten (erstmal rausfinden wie :>)

Verfasst: Dienstag 15. April 2008, 23:35
von EyDu
Bei mir geht es sowohl über IDLE als auch die python.exe. Probier doch mal das folgende:

Code: Alles auswählen

def vorwaerts(event): 
    Mario.go_forward(environment_list) 
    
def rueckwaerts(event): 
    Mario.go_forward(environment_list) 
Dann kann man schon mal feststellen, ob es an deinem Code liegt.

Verfasst: Dienstag 15. April 2008, 23:40
von Kalkas
wie erwartet geht er jetzt sowohl bei <RIGHT> als auch bei <LEFT> vorwärts, und da funktioniert ja auch das anhalten

und was sagt uns das jetzt?^^

Verfasst: Dienstag 15. April 2008, 23:42
von EyDu
Das es auf jeden Fall dein Fehler ist und es keine Probleme mit irgend welchen Events von der Tastatur gibt :D

Verfasst: Dienstag 15. April 2008, 23:46
von Kalkas
ich habe eben deinen code kopiert und bei mir getestet also müsste es doch theoretissch bei mir auch funktionieren, das tut es aber nicht :>