Objekte in Python.

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

Hallo liebe Python-Gemeinde.

Ich ersuche erneut eure hilfe.


Diesmal will ich ein PythonObjekt schreiben, welches mit hilfe von gegebenen Vectoren eine kleine Karte der Umgebung generiert und diese als String zurück gibt.

Als beispiel sollte das Objekt etwas in dieser Art zurück geben:

Code: Alles auswählen

#####|#####
#####|#####
#####|#####
#####|#####
#####|#####
-----O-----
#####|#####
#####|#####
#####|#####
#####|#####
#####|#####
Wie unschwer zu erkennen hat diese "MiniKarte einen Mittelpunkt mit den Koordinaten (0|0), der als ein "O" gekennzeichnet ist. Wenn das ganze Objekt fertig ist, soll man nach meinen Vorstellungen eine Art "Gruppe" von VectorKoordinaten erstellen können und diese Gruppe über eine eine eingebaute Funktion (addLocation) an das "Generator"Objekt übergeben werden können. Jede dieser Gruppen soll dann an hand eines Zeichens in der oben beschriebenen Minikarte auftauchen.


Bisher sieht mein Code folgendermaßen aus:

http://pastebin.com/gar7p4HK


Leider bin ich damit noch net so ganz zufrieden, vorallem was das Thema performance angeht, da ich mir ziemlich sicher bin, dass man zumindest eine der "for"-Schleifen einsparen kann.
Ach ja im bin mir natürlich im Klaren, dass der Code im aktuellen zustand (noch) nicht funktioniert. Aber bevor ich mir nun riesen mühe gebe irgendwas zusammen zu basteln, wollte ich gleich mal erfahrenere Leut befragen, die evtl noch ein paar Sinnige ideen mit einbringen können.


MfG
problembär

Ich versteh' noch nicht wirklich, was Du machen willst. "vecmath" ist dieses:

http://code.google.com/p/eventscripts-l ... h.py?r=865

??? So, und Du was willst Du jetzt mit diesen Vector-Objekten machen, um diese Karte zu erstellen? Was sind das überhaupt für Objekte?
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

vecmath ist nicht anderes als ein Modul, das mathematischen Funktionen zum Rechnen mit Vectoren bietet und diese als PythonObjekt repräsentiert.

Die "MiniKarte" die ich Programmieren will hat ein solchen Vector als Mittelpunkt. Von diesem Mittelpunkt aus werden alle anderen Vectoren die man in der Minikarte anzeigen lassen will berechnet und diese sollen in Form eines "eigenen" Zeichens in der Karte dargestellt werden.

Um mal ein konkretes Anwendungsbeispiel dafür zu nennen:

Damit könnte man theoretisch eine Art "Wallhack" programmieren, indem man die Positionen aller "Gegnerischen" Spieler in der Minikarte anzeigen lässt.


Nätürlich könnte man damit noch viele weitere Dinge anstellen. :)
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Ich verstehe nicht wozu du dafür "vecmath" brauchst. Ein 2d-Vektor in Python, wenn man damit nicht rechnen möchte, wäre ein Tupel (x,y). Ein einfacher Ansatz wäre:

Code: Alles auswählen

In [16]: class Minikarte(object):
   ....:     def __init__(self):
   ....:         self.koordinaten = []
   ....:     def __str__(self):
   ....:         karte = [['#' for i in xrange(-10,11)] for j in xrange(-10,11)]
   ....:         for i,j in self.koordinaten:
   ....:             karte[i][j] = 'O'
   ....:         return '\n'.join(''.join(line) for line in karte)
   ....:     

In [17]: m = Minikarte()

In [18]: m.koordinaten.append((13,2))

In [19]: m.koordinaten.append((-5,9))

In [20]: print m
Grüße
Gerrit
BlackJack

@Brainsucker: Warum ist der `OutputBuilder` ein `Vector`!? Und bei der `ObjectLocation` fehlt wahrscheinlich ein Aufruf der `__init__()`-Methode der Basisklasse. Und die Möglichkeit direkt beim Erzeugen einer `ObjectLocation` auch tatsächlich die Koordinaten angeben zu können.

In `addLocation()` fliegt einem ein `NameError` um die Ohren, weil `Group` nirgends definiert ist. Dieser Typtest ist sowieso „unpythonisch”. Wenn sich etwas verhält wie eine `Group` sollte man es auch hinzufügen dürfen wenn es nicht den Typ hat.

Bei den beiden äussersten ``for``-Schleifen in `generate()` versuchst Du IMHO mit dem `abs()` Benutzerfehler zu korrigieren. Würde ich sein lassen. Wenn der Benutzer falsche Werte irgend wo rein füttert, dann sollte er das auch an den Folgen merken, und nicht denken das war schon alles richtig, was ich da gemacht habe.

Statt für jedes Kästchen jedes Objekt zu untersuchen ob es innerhalb eines Rechtecks liegt, könntest Du Anzeigekoordinaten für die Objekte berechnen und die nach Position (Zeile und innerhalb der Zeilen nach Spalten) sortieren. Oder Du baust erst eine verschachtelte Datenstruktur für die Karte auf, platzierst dann die Objekte der Reihe nach darin, und wandelst das dann in eine Zeichenkette um. Siehe den Ansatz von gkuhl.

Dazu solltest Du übrigens nicht die Zeichenkette per ``+=`` aufbauen, sondern die `join()`-Methode auf Zeichenketten verwenden. Jedes mal wenn man eine Zeichenkette mit ``+``/``+=`` erstellt, muss man damit rechnen, dass die alten Daten unnötig kopiert werden.

Du hast die `addLocation()`-Methode offensichtlich nicht ausprobiert, dann ist Dir natürlich auch entgangen, dass die `generate()`-Methode auch nicht korrekt funktioniert wenn tatsächlich ein Objekt "gezeichnet" wird. Dann wird das `token`-Attribut hinzugefügt, aber trotzdem zusätzlich noch entweder eine Linie oder das Füllzeichen.

Du rückst mit Tabs ein, Konvention sind aber vier Leerzeichen pro Ebene. Ausserdem halten sich die Namen nicht an PEP 8 -- Style Guide for Python Code.
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

gkuhl hat geschrieben:Ich verstehe nicht wozu du dafür "vecmath" brauchst. Ein 2d-Vektor in Python, wenn man damit nicht rechnen möchte, wäre ein Tupel (x,y).
Danke, aber wer sagte, dass ich damit nicht rechnen möchte? Außerdem wer sagte, dass ich einen 2D Vector brauche?

Die Vectoren mit denen ich hauptsächlich rechnen muss sind 3 Dimensional. Das Problem nur ist, dass die Form in der ich die Vectoren ausgeben lassen will ohne größeren Aufwand nur 2D Vectoren (x,y) erlauben.

Daher hilft mir das bei meinem Problem nicht weiter. Trotzdem danke für die bemühungen.
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

Soo ich muss den ganzen Post mal ein kleinwenig in Stücke hacken und abschnittsweise meinen Senf dazu geben^^
BlackJack hat geschrieben:@Brainsucker: Warum ist der `OutputBuilder` ein `Vector`!? Und bei der `ObjectLocation` fehlt wahrscheinlich ein Aufruf der `__init__()`-Methode der Basisklasse. Und die Möglichkeit direkt beim Erzeugen einer `ObjectLocation` auch tatsächlich die Koordinaten angeben zu können.
naja ich habe mir gedacht, dass der Mittelpunkt der Minikarte durch einen Vector bestimmt werden soll. Um diesen Punkt herum dreht und wendet sich dann die Karte. Je nach position und "Blickrichtung" (was aber bisher noch nicht vorhanden ist).
In `addLocation()` fliegt einem ein `NameError` um die Ohren, weil `Group` nirgends definiert ist. Dieser Typtest ist sowieso „unpythonisch”. Wenn sich etwas verhält wie eine `Group` sollte man es auch hinzufügen dürfen wenn es nicht den Typ hat.
Das mit dem NameError kommt davon, wenn man den Namen der Klasse ändert und dieses nicht über das komplette Programm hinweg ebenfalls macht :)


Bei den beiden äussersten ``for``-Schleifen in `generate()` versuchst Du IMHO mit dem `abs()` Benutzerfehler zu korrigieren.
So ist es.
Würde ich sein lassen. Wenn der Benutzer falsche Werte irgend wo rein füttert, dann sollte er das auch an den Folgen merken, und nicht denken das war schon alles richtig, was ich da gemacht habe.
Ist sicherlich beim fertigen Programm denkbar, zum jetztigen Zeitpunkt sollte ich mich erstmal auf die Hauptsächliche funktion kümmern. Trotzdem danke für jeden Tipp.

Statt für jedes Kästchen jedes Objekt zu untersuchen ob es innerhalb eines Rechtecks liegt, könntest Du Anzeigekoordinaten für die Objekte berechnen und die nach Position (Zeile und innerhalb der Zeilen nach Spalten) sortieren.
Genau das ist der Hauptgrund für dieses Topic. Ich suche hauptsächlich ein paar Tipps, wie man sowas angeht und möglichst intelligent die berechneten Daten "zwischenspeichert" bis diese benötigt werden. Also so Grundspeichermethoden wie z.B. dictionary fallen mir da natürlich gleich als erstes ein. Nun ist allerdings die frage, ob sich das hier tatsächlich empfielt, und in welcher Form die berechneten Koordinaten in der Minikarte am sinnvollsten gespeichert werden.

Ein Beispiel hierzu wäre:
x und y Koordinate bekommen jeweils für jede Location einen separaten Key indem der jeweilige Wert enthalten ist.

oder

Wie schon genannt die Tuplevariante (x, y) in einer Variablen speichern.

Dazu solltest Du übrigens nicht die Zeichenkette per ``+=`` aufbauen, sondern die `join()`-Methode auf Zeichenketten verwenden. Jedes mal wenn man eine Zeichenkette mit ``+``/``+=`` erstellt, muss man damit rechnen, dass die alten Daten unnötig kopiert werden.
Wäre sicherlich ebenfalls denkbar. Müsste ich dazu nicht eine Liste erstellen, inder ich zuerst alle einzelnen Zeichen hinzufüge und dann am ende der Funktion mit .join() zusammensetzen lassen?
Du hast die `addLocation()`-Methode offensichtlich nicht ausprobiert, dann ist Dir natürlich auch entgangen, dass die `generate()`-Methode auch nicht korrekt funktioniert wenn tatsächlich ein Objekt "gezeichnet" wird. Dann wird das `token`-Attribut hinzugefügt, aber trotzdem zusätzlich noch entweder eine Linie oder das Füllzeichen.
Wie bereits im ersten Post erwähnt, ist mir diese Problematik bereits bewusst :)
Du rückst mit Tabs ein, Konvention sind aber vier Leerzeichen pro Ebene. Ausserdem halten sich die Namen nicht an PEP 8 -- Style Guide for Python Code.
Schon öfter davon gehört, aber nie wirklich beachtet, weil ich das einrücken mit Tabs deutlich schneller finde.
deets

Brainsucker hat geschrieben: Genau das ist der Hauptgrund für dieses Topic. Ich suche hauptsächlich ein paar Tipps, wie man sowas angeht und möglichst intelligent die berechneten Daten "zwischenspeichert" bis diese benötigt werden. Also so Grundspeichermethoden wie z.B. dictionary fallen mir da natürlich gleich als erstes ein. Nun ist allerdings die frage, ob sich das hier tatsächlich empfielt, und in welcher Form die berechneten Koordinaten in der Minikarte am sinnvollsten gespeichert werden.

Ein Beispiel hierzu wäre:
x und y Koordinate bekommen jeweils für jede Location einen separaten Key indem der jeweilige Wert enthalten ist.

oder

Wie schon genannt die Tuplevariante (x, y) in einer Variablen speichern.
Was man da ueblicherweise macht ist schlicht die zu betrachtenden Objekte (also alles was in der Karte erscheinen soll) zuerstmal nach der bounding-box der Karte zu filtern. Die hat ja eine "virtuelle" Aufloesung, sagen wir mal -100 bis +100, in beiden Dimensionen - wird aber selber nur von -10 bis +10 dargestellt.

Dann hast du fuer die Karte ein Array mit allen Farbwerten. Je nachdem was und wie du das machst ist das einfach nur eine verschachtelte Python-Liste mit 10*10 Werten, oder gleich zB ein Pixelbuffer irgendeines Grafik-Systems. In deinem Fall wohl eher ersteres.

Und nun iterierst du ueber alle Objekte, und bildest deren Welt-Koordinate auf die Karten-Koordinate ab. Also zuerst subtrahierst du den Kartenmittelpunkt, und dann dividierst du durch die Skalierung - in diesem Beispiel 10. Runden bzw. auf int casten, und du hast die Koordinaten in Karten-Dimension. Damit indizierst du in die doppelte Liste, und setzt dort den Ausgabewert. Vorbelegt ist die Liste natuerlich mit Spaces oder was auch immer bei dir "hier is nix" anzeigt.

Dann kannst du danach noch dein Fadenkreuz einmalen, und schlussendlich mittels doppeltem join mit "" und "\n" die Ausgabe erzeugen.
Brainsucker
User
Beiträge: 68
Registriert: Mittwoch 16. November 2011, 23:20

deets hat geschrieben:
Brainsucker hat geschrieben: Genau das ist der Hauptgrund für dieses Topic. Ich suche hauptsächlich ein paar Tipps, wie man sowas angeht und möglichst intelligent die berechneten Daten "zwischenspeichert" bis diese benötigt werden. Also so Grundspeichermethoden wie z.B. dictionary fallen mir da natürlich gleich als erstes ein. Nun ist allerdings die frage, ob sich das hier tatsächlich empfielt, und in welcher Form die berechneten Koordinaten in der Minikarte am sinnvollsten gespeichert werden.

Ein Beispiel hierzu wäre:
x und y Koordinate bekommen jeweils für jede Location einen separaten Key indem der jeweilige Wert enthalten ist.

oder

Wie schon genannt die Tuplevariante (x, y) in einer Variablen speichern.
Was man da ueblicherweise macht ist schlicht die zu betrachtenden Objekte (also alles was in der Karte erscheinen soll) zuerstmal nach der bounding-box der Karte zu filtern. Die hat ja eine "virtuelle" Aufloesung, sagen wir mal -100 bis +100, in beiden Dimensionen - wird aber selber nur von -10 bis +10 dargestellt.

Dann hast du fuer die Karte ein Array mit allen Farbwerten. Je nachdem was und wie du das machst ist das einfach nur eine verschachtelte Python-Liste mit 10*10 Werten, oder gleich zB ein Pixelbuffer irgendeines Grafik-Systems. In deinem Fall wohl eher ersteres.

Und nun iterierst du ueber alle Objekte, und bildest deren Welt-Koordinate auf die Karten-Koordinate ab. Also zuerst subtrahierst du den Kartenmittelpunkt, und dann dividierst du durch die Skalierung - in diesem Beispiel 10. Runden bzw. auf int casten, und du hast die Koordinaten in Karten-Dimension. Damit indizierst du in die doppelte Liste, und setzt dort den Ausgabewert. Vorbelegt ist die Liste natuerlich mit Spaces oder was auch immer bei dir "hier is nix" anzeigt.

Dann kannst du danach noch dein Fadenkreuz einmalen, und schlussendlich mittels doppeltem join mit "" und "\n" die Ausgabe erzeugen.
Ahh, vielen Dank für die erklärung. Das erscheint mit sehr plausibel. Ich werd mich mal dran versuchen. Vielen dank auch :)
BlackJack

@Brainsucker: Einrücken mit Leerzeichen ist genau so schnell wie mit Tabs. Man macht da ja nicht vier Leerzeichen mit der Space-Taste sondern konfiguriert den Editor so, dass er bei Tab/Backspace mit Leerzeichen statt mit Tabs ein- und ausrückt.
Antworten