HighEnergy ... Projekt von Anfängern

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

MC_MO hat geschrieben:Naja Funktionen hab ich ja so weit wie möglich verwendet, das Problem ist halt dass sich die Geschwindigkeit des Rotors sehr oft ändert, um einen realistischen Bewegungsablauf zu zeigen...
Dann lagere doch die sich ändernden, aber zusammengehörigen Werte in einer Datenstruktur, die Du dann eben in einer Funktion verarbeitest.

Versuch zu analysieren, was die sich immer wiederholenden Schritte alle gemeinsam haben. Welche Art von Daten benötigen sie? Wie kann man diese gut aggregieren? Dazu kann man vermutlich Listen und Dictionaries nutzen, ggf. auch in Kombination.

Ich hab den Code von Dir grad nicht zur Hand, daher kein konreter Ansatz :-)
MC_MO
User
Beiträge: 25
Registriert: Sonntag 28. März 2010, 10:07

Also eigentlich sieht die Bewegung so aus:

Code: Alles auswählen

    for i in range (50):
        rate(25)
        hauptarm.rotate(angle=radians(-0.6),
                        axis=(-1,0,0),
                        origin=(0,2.5,0))
        Fahrtbewegung()
Es verändert sich nur die Dauer "range" und die Drehgeschwindigkeit "angle=radians". Über die Veränderung dieser 2 Werte konnte ich eine relativ flüssige Bewegung im echten Fahrturnus machen (Mit Ausschwingen beim Start, bis zum Überschlag, nach ein paar Runden ein Stop ganz oben und dann noch drehen in die andere Richtung, dann wieder anhalten).

Die Methode "Fahrtbewegung" beinhaltet das Drehen der Spinne um die eigene Achse sowie das drehen der Sitze um deren Aufhängung.

mfg
MC MO

P.s:Wer sich darunter nichts vorstellen kann, hier nochmal der Link zu einem YouTube-Video des Fahrgeschäftes:http://www.youtube.com/watch?v=XI6kVbBw38E
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

MC_MO hat geschrieben:Es verändert sich nur die Dauer "range" und die Drehgeschwindigkeit "angle=radians".
Und was spricht gegen eine Funktion, die diese 2 Parameter entgegennimmt?! ;-)
„Lieber von den Richtigen kritisiert als von den Falschen gelobt werden.“
Gerhard Kocher

http://ms4py.org/
MC_MO
User
Beiträge: 25
Registriert: Sonntag 28. März 2010, 10:07

Äääähm...

Danke für den Hinweis, das bau ich doch glatt gleich ein...LOL!
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Und die Werte packst Du ann eben z.B. in ein Tupel von Tupeln:

Code: Alles auswählen

# inner tuple: (count, angle)
move_data = (
    (50, -0.6),
    (45, 0.3),
    ...
)

# irgend wann dann eben so was:
for move in move_data:
    do_move(*move)
MC_MO
User
Beiträge: 25
Registriert: Sonntag 28. März 2010, 10:07

Achso...ich hätte es so gemacht:

Code: Alles auswählen

def move(x,y)
    for i in range (x):
        rate(25)
        hauptarm.rotate(angle=radians(y),
                        axis=(-1,0,0),
                        origin=(0,2.5,0))
        Fahrtbewegung()

#beimFahren dann:
move(50,-0.6)
move(70,-0.8)
#und so weiter
Welcher Ansatz ist "ordentlicher" (bevor ich jetzt Anfang die gesamte Fahrt neu zu erstellen^^)?
Die 2 Werte sollten nicht miteinander gekoppelt sein (also z.B. 45/0.6 und 50/0.8 ), sondern individuell anpassbar sein (z.B. 45/0.8 damit ich am Ende einen sauberen Halt bei 0° machen kann).

Und wo müsste ich bei dir die "Formeln" (hauptarm.rotate etc) reinschreiben?
Zuletzt geändert von MC_MO am Freitag 2. April 2010, 07:56, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ok ;-)

Vor allem, weil Du die so auch leicht in eine Externe Datei schreiben kannst! Somit ist es recht einfach, die Routen dynamisch zu gestalten, indem man eben einfach andere Daten in das Programm läd.

Dazu könntest Du Dir mal JSON (json-Modul) angucken. Das ist echt extrem simpel!

Als "Krönung" verwendest Du dann noch das optparse-Modul und ermöglichst es so, die Daten-Datei frei wählbar zu machen :-)
MC_MO
User
Beiträge: 25
Registriert: Sonntag 28. März 2010, 10:07

So hier ein Update:

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

Was könnte man noch machen? Die Bank-Erstellung find ich noch zu lang, das beheb ich noch ;)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Öhm, der Code ist immer noch total grausam ;-) Dir sollte eigentlich aufgefallen sein, dass ein Großteil deines Codes nahezu identisch ist, dann sollte man das auch zusammenfassen. Ein sehr schlechtes Zeichen sind Copy&Paste und die Durchnummerierung von Namen.

Und dann überall diese ganzen Zahlen. Benutze doch mal Konstanten. Wenn du in deinem Code irgendwo eine Einstellung anpassen willst, dann musst du das an ca. 100 Stellen tun. Mit Konstanten hast du genau eine Stelle.

Deine Klassen sind übrigens total überflüssig. Dort passiert genau nichts. Außerdem muss der Ganze Code raus aus der Modulebene in Funktionen. So kann man dein Modul nicht verwenden. Außerdem solltest du den Hinweis von Hyperion umsetzen. Die Funktionsaufrufe am Ende sind unglaublich unflexibel. Funktionen sind übrigens auch Objekte.

Und dann schaue doch bitte PEP 8 an. Die ganzen

Code: Alles auswählen

class Stair:
    def __init__ (self):
        Stair=list()
treiben einen doch in den Wahnsinn ;-)

Sebastian
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich finde das alles ziemlich "lang"!

Wozu die ganzen Klassen? Eigentlich halten die nur Attribute - das könnte man dann auch über ein Dictionary lösen.

Außerdem sind viele Attribute der Klassen auch nur copy&paste! Wieso nicht weiter abstrahieren und dann Listen vbon Objekten gleichen Musters anlegen?

Ich würde generell diese vielen Daten auslagern (-> JSON, o.a.). Die gehören imho ja nicht direkt zum eigentlich Programm.

Code: Alles auswählen

bench_1.rotate(angle=0*pi/3,axis=(0,1,0))
bench_2.rotate(angle=1*pi/3,axis=(0,1,0))
bench_3.rotate(angle=2*pi/3,axis=(0,1,0))
bench_4.rotate(angle=3*pi/3,axis=(0,1,0))
bench_5.rotate(angle=4*pi/3,axis=(0,1,0))
bench_6.rotate(angle=5*pi/3,axis=(0,1,0))
Wieso packst Du das nicht in eine Liste? Wenn man Bezeichner durchnummeriert, hat man etwas falsch gemacht!

Wieso nutzt Du keine Funktionen? Zudem ist der ganze Code auf Modulebene! Das ist ziemlich unschön.

Code: Alles auswählen

"""Motion"""
while True:
    time.sleep(5)
    move_spider(1,0.1)
    move_spider(2,0.2)
    move_spider(3,0.3)
    move_spider(4,0.4)
    # usw.
Wieso nicht diese Werte auch in eine Datenstruktur auslagern (Hatte ich doch schon mal angeregt iifc!) und dann mit einer Schleife iterieren?

Das ganze ist irgend wie komplett unschön!

Viel zu viele Magic Numbers im Quellcode.

Ich würde versuchen fast alle diese Werte in eine externe Datendatei auszulagern und diese zu Beginn einzulesen und dann Schritt für Schritt Objekte zusammenzubauen, die sich sinnvoll aus den kleint möglichen Wertpaaren zusammensetzen.

Beispiel:

Code: Alles auswählen

        PILLAR_1=box(pos=(310,-660,-230),
                     length=30,
                     width=30,
                     height=1500,
                     color=(0.8,0.8,0.8),
                     material=materials.emissive)
Davon hast Du in der Klasse Scenery drei Stück.

Augenscheinlich brauchst Du für eine box also die Parameter: pos, length, width, height, color und material.

in JSON sähe das so aus:

Code: Alles auswählen

{
    "box_mitte": {
        "type": "box"
        "pos": [310,-660,-230],
        "length": 30,
        "width": 30,
        "height": 1500,
        "color": [0.8, 0.8, 0.8],
        "material": "emissive"
    },
...
}
Dies könntest Du nun parsen und eine neue box anlegen:

Code: Alles auswählen

import json

def load_data(filename):
    with open(filename, "r") as infile:
        scene = json.load(infile)
    return scene


def create_scene():
    create_funcs = {
        "box": create_box,
        "sphere": create_sphere,
        # usw.
    }
    # hier ein Dictionary für die fertigen Objekte
    objects = {}
    scene_data = load_data("scene.json")
    for name, values in scene_data.iteritems():
        objects[name] = create_funcs[values["type"]](**values)
    return objects
Die einzelnen "create"-Funktionen erzeugen dann eben je nach Art ein solches Objekt und geben es zurück. Dieses wird dann in das Dict objects gepackt und kann später weiter genutzt werden; etwa zum Bewegen einzelnen Objekte.
Dies könnte man auch in die JSON-Datei integrieren

Code: Alles auswählen

{
    "sphere_aussen": {
        "type": "sphere",
        "pos"= [0, -1615, 0],
        "radius": 15000,
        "color": [0, 0, 0.5]
        "rotations": [
            {
            "angle": ...
            },
            usw.
        ]
    }
}
Um diesen Klasse-Wust wegzubekommen, könnte man noch eine weitere Ebene in die JSON-Datei einbauen und in Python dann als "höchstes" Dictionary ablegen.

Code: Alles auswählen

{
    "scenery": {
        hier dann alle Daten für die Scene
    },
    "schriftzug": {
        hier alles für diesen High enegery Text
    },
    usw.!
}
So, ich hoffe das waren mal ein paar Anregungen!

Auf jeden Fall sagt dieses Script, dass Du von guter Modellierung noch weit entfernt bist - das ist kein Wunder als Anfänger, aber ein Zeichen, sich nicht zu hohe Ziele zu stecken (ich verweise da mal auf den Idee-Thread ;-) )

Wichtig ist immer, zu erkennen, welche Strukturen man geschickt und sinnvoll zusammenpacken kann. Für diese implementiert man dann Datenstrukturen und Operationen darauf. So wächst Stück für Stück etwas zusammen.
MC_MO
User
Beiträge: 25
Registriert: Sonntag 28. März 2010, 10:07

Wow deine Ideen hören sich (für mich) echt genial an!
Wozu die ganzen Klassen
Naja ich finde die machen das ganze optisch deutlich übersichtlicher. Ohne die sahs noch konfuser aus ;)
Wieso nutzt Du keine Funktionen?
Weil ich nicht weiß was für Funktionen du meinst :oops:
Zudem ist der ganze Code auf Modulebene! Das ist ziemlich unschön
Finde ich auch, aber was ist Modulebene? :(
Das ganze ist irgend wie komplett unschön!
Kann man so sagen...naja wie ich erwähnte, ich habe seit 2 Jahren Informatikunterricht. Mittlerweile sind wir von Robot Karol auf BlueJ umgestiegen :D Im Unterricht bin ich einer der einzigen die was kapieren, aber viel lernen tun wir da nicht.
Jetzt war ich bei diesen 4-tägigen "Probestudium" und da haben wir mit Python gearbeitet. Ich finds richtig cool, aber natürlich hab ich noch kein Wissen. Gibt es sozusagen "Einführungen" in Python oder gute Bücher (bitte möglichst deutsch)? Ich würd mir ja gerne selbst Sachen beibringen, aber ich weiß net wie...

Jedenfalls danke für deine/eure Hilfe!
mfg
MC MO
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Zum Thema "Einstieg" & "Lernen" gibt es hier massig Threads - such einfach mal. Generell gilt: Arbeite das offizielle Tutorial durch (enthalten in der Doku) und schau mal in die Wiki FAQ (oben im Board verlinkt).

Edit: Ich habe mir mal unter Windows dieses visual-Modul installiert. Dein ergebnis sieht schon ziemlich gut aus imho. Aber der inhalt ist irgend wie pfui :-D Aber die Tutorials sind ja auch nur auf diese Art und Weise aufgebaut...

Was mich am meisten wundert: Es scheint tatsächlich keine eingebaute Persistenz zu geben... oder kennt da jemand was?
BlackJack

@MC_MO: Mit Funktionen sind hier wohl die gemeint die *Du* schreiben solltest.

Zum Beispiel sind Deine Klassen eigentlich keine Klassen sondern Funktionen. Soweit ich das sehe wird keine einzige wirklich als Klasse verwendet. Das ist immer nur Code der in der `__init__()`-Methode ausgeführt wird und `self` überhaupt nicht verwendet. *Das* kann man auch ohne ``class`` haben indem man einfach Funktionen definiert die den Inhalt von `__init__()` haben. Dass das keine Klassen sind die als Vorlage für Objekte verwendet werden, sieht man auch ziemlich deutlich daran, dass Du zwar die Objekte an Namen bindest (Zeile 894 ff.) die aber nicht weiter verwendest. Wenn das tatsächlich objektorientiert entworfen wäre dann hättest Du Objekte die den jeweiligen Teil modellieren und die zu einem Gesamtmodell zusammengesetzt werden. Und dann wäre so etwas wie `move_spider()` eine Methode auf dem Objekt, welches die Spinne modelliert und keine Funktion die auf ein `spider` zugreift, dass aus dem nichts zu kommen scheint.

Code auf Modulebene ist alles was nicht in Klassen oder Funktionen steckt. Und da sollte halt so gut wie nichts stehen ausser eben Klassen, Funktionen, und Konstanten. Dann gäb's auch `spider` und `rotor` nicht "einfach so", das müsste man dann als Argument an Funktionen übergeben, oder sie an ein Objekt binden.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hier mal ein Schnellschuss:
http://paste.pocoo.org/show/196863/

Eine zugehörige JSON-Datei:
http://paste.pocoo.org/show/196865/

Wie ich gesehen habe, hast Du natürlich durchaus auch Dynamiken drin, also Objekte, die Du anhand eines Parameters variiert anlegst. Dass kan dieses Modell so noch nicht.

Dafür müßte man sich noch etwas ausdenken... evtl. könnte man da was einfaches mittels Template-Engine basteln... *grübel*

Aber immerhin könntest Du den ganzen statischen Kram so auslagern.
MC_MO
User
Beiträge: 25
Registriert: Sonntag 28. März 2010, 10:07

Vielen Dank, jetzt hab ich das immerhin bisschen verstanden. Mal ausprobieren :D
Antworten