Beiträge von Gravedigger

    Jaaa, GanjaManager macht große Fortschritte, nicht zuletzt wegen Florians produktiver Ratschläge. Die Entwicklung der GUI hab ich jedoch erstmal zurück gestellt (will erst das MVC-Pattern komplett verstehen und dann muss mir Florian nochmal sein Template-Konzept genauer erklären) und konzenteriere mich erstmal auf die Plattformunabhängigen Klassen.
    Das eigentlich Framework ist soweit fertig, daher hab ich mir zwischenzeitlich Gedanken darum gemacht, wie der Spieleserver für den Online-Modus funktionieren soll.


    Mir ist dabei aufgefallen, dass lustigerweise meine PHP-Denke die Datenstruktur und das Vorgehen hinsichtlich der Persintenz stark beeinflusst hat. In der Praxis bedeutet dies, dass der Spielserver im Prinzip nur aus einer Datenbank bestehen muss, da die Spielklassen bei jeder Aktion sofort die entsprechenden Änderungen in der DB vornehmen.


    Leider ist mir dabei aufgefallen, dass ich in meinen Klassen intensiven Gebrauch des ContenValues-Objektes gemacht habe, was eigentlich dazu dienen sollte, über das Projekt verstreute SQL-Abfragen im Code zu vermeiden. Hätte ich jedoch die uneleganten SQL-Strings im Code gelassen, hätte meine DB-Klasse diese lediglich an einen MySQL-Server, statt an SQLite weiterleiten brauchen.


    Gibt es eine Möglichkeit den daraus generierten SQL-String auszugeben, bevor er durch getWritableDatabase().insert(table, null, ContentValues); ausgeführt wird? ?(

    Ein (weiteres) Danke an Florian...


    Das Ur-Objekt das du meinst, habe ich ja schon eingebaut, und zwar ist das die extTableManager-Klasse, von dem ich bereits alle anderen Objekte ableite. Bin nun auch am Überlegen ich auch das Lagerort-Objekt davon ableite. Eine "DirtyTrick" - Klasse wäre natürlich auch eine Idee, quasi als Schnittstelle zum sauberen Code und für den Fall, dass ich diesen Mechanismus noch an einer anderen Stelle einsetzen muss.


    Das mit dem Controller zwischen Logik und GUI entspricht wohl einem MVC-Patttern, wobei mir da noch nicht ganz klar ist, wie eine Implementierung aussehen könnte. Ich hatte vor, in den Listenern der GUI-Elemente die jeweiligen Aktionen per Methoden der betreffenden Objekte auszuführen.


    Allerdings hatte ich schon gegrübelt, ob ich für jeden Bildschirm ein XML-Layout mache, oder öfters benutzte Gruppen von Steuerelementen per Code einfüge, was wesentlich flexibler wäre, wovon in den einschlägigen Android Tutorials zwecks Übersicht aber immer abgeraten wird.


    Hier mal einen ersten GUI-Entwurf :


    [Blockierte Grafik: http://www.buschmann-edv.de/tausch/GUI_Entwurf.png]


    Wie zu sehen ist, wiederholt sich das Element zum Auswählen eines Objektes auf fast jeder Seite des Programms. Hab auch schon eine Klasse, sowie ein Interface "Switchable" dafür implementiert. Wie würdest du vorgehen, um solche Elemente einfach wiederzuverwenden, bzw. vom restlichen Code zu trennen?

    Soo, es ging doch etwas mehr Zeit für Planung und Schaffung eines (weitestgehend) sauberen Frameworks drauf. Außerdem hat sich mir nun auch der Nutzen von Interfaces erschlossen, mit denen ich nun Objekte als beladbar oder Ladung deklarieren kann. Bei der OOP unter PHP hatte ich auf Vererbung und Interfaces weitgehend verzichtet, da schon das bloße Benutzen von einfachen Objekten einen exorbitanten Fortschritt gegenüber dem alten Spaghetticode darstellte... :)


    Desweiteren hab ich nun auch ein vorläufiges ER-Model entworfen, bei dem ich jedoch einige schmutzige Tricks anwenden musste. Für Tips zur Vermeidung oder für etwas weniger schmutzige Varianten bin ich offen. Mit Themen wie DAO / JPA / Hibernate bin ich allerdings durch. Lieber schutzig und klein als sauber und overkill... ^^


    Auf dem ER-Model fehlen allerdings noch eine ganze Reihe von Feldern, da ich erstmal nur die Schlüsselfelder berücksichtigt habe. Außerdem kommen noch weitere Tabellen für den Handel/Verkauf von Gütern als auch für die Kunden/Absatz. Auch hier bin ich für Vorschläge offen.


    [Blockierte Grafik: http://www.buschmann-edv.de/tausch/ER_Model_komm.png]

    Da das Spiel im Laufe seiner Entwicklung eine Vielzahl von Objekten enthalten wird, deren Objektzustände in der Datenbank verwaltet werden sollen, hab ich mir jetzt doch ein System zurechtgezimmert, welches man ansatzweise als DAO bezeichnen könnte.


    Und zwar wird in jeder Klasse, die ein solches Objekt darstellt (Grundstück, Plfanze, Gewächshaus, Auto, usw.) ein Array mit seiner Datenbankstruktur definiert:


    Java
    private static String tbName 	= "spieler";
    private static String struct[][] = {
                                {"sp_id", "integer", "primary key", "autoincrement"},
                                {"sp_name", "varchat(32)"},
                                {"sp_geld", "integer(6)"},
                                {"sp_pass", "varchar(32)"},
                                {"sp_email", "varchar(64)"},
                                {"sp_stadt", "integer(3)"}
                                };


    Dieses Array kann an meine DAO-Klasse tableHelper übergeben werden, welche daraus SQL-Abfragen generieren kann. Desweiteren kann die DB-Klasse per statischer Methode von jedem Objekt eine Instanz der tableHelper-Klasse anfordern, welche bereits die Strukturdaten des jeweiligen Objektes enthält. So kann die DB-Klasse automatisch fehlende Tabellen anlegen oder bestehende ändern, falls im Array der Klasse neue Felder hinzugefügt oder geändert wurden.


    Auf diese Weise kann ich jederzeit neue Objekte in mein Spiel einbauen, ohne mich groß um die Datenbankstruktur zu kümmern.
    Natürlich ist das keine Umfassende Lösung, da die relationalen Beziehungen zwischen den Objekten immer noch von Hand hergestellt werden und auch Verbindungstabellen werd ich noch von Hand verwalten müssen.


    Das System ließe sich sicher noch weiterspinnen, allerdings will ich ein Spiel programmieren und kein umfassenden DAO-Framework für Android. Falls dies aber jemand tun will, stelle ich ihm gerne die entsprechenden Klassen und Informationen zur Verfügung.

    Mit Abstrakten Klassen hab ich noch so gut wie nie gearbeitet, wofür würdest du sie genau einsetzen?


    Ich schätze, sie werden mir helfen, wenn ich später verschiedene Objekte als Ladung deklarieren möchte. So soll es möglich sein, ganze Pflanzen, gebrauchsfertiges Dope, aber auch Lampen, Klimaanlagen und Artefakte (so nenn ich mal analog zu Rollenspielen Objekte die Fähigkeiten des Besitzers beeinflussen, zB. die goldene Schaufen die Fähigkeit grüner Daumen) auf dem Abstellplatz das Grundstückes zu lagern, in ein Auto zu verladen oder auf dem Markt zu verkaufen.
    Ladung hat dann unter Anderem Eigenschaften wie Volumen und Gewicht, welche beim Einladen in ein Fahrzeug berücksichtigt werden müssen.


    Außerdem, kann ich mir jezze auch langsam Gedanken um die Präsentation und Spielercharakter machen. So soll man beim Erstellen eines Account grob zwischen Gärtner, Dealer, Kiffer auswählen können, die verschiedene Starteigenschaften mitbrigen:


    Gärtner
    - Grüner Daumen +3
    - Geschäftssinn +1
    - Charisma +1


    Dealer
    - Grüner Daumen +1
    - Geschäftssinn +4
    - Charisma +0


    Kiffer
    - Grüner Daumen +2
    - Geschäftssinn +0
    - Charisma +3


    Je nach Spielerfolg bekommt man Erfahrungspunkte, die man in Gewissen Abständen in verschiedene Fähigkeiten investieren kann.
    Das ganze Erfahrungssystem soll sehr Dynamisch sein, daher darf die Datenbankstruktur entsprechend auch komplexer werden.


    Ich bitte hiermit ausdrücklich um Anregungen... :)

    Es geht gut voran...


    ...meine Datenbankklasse läuft und ich hab das Grundgerüst um das Spiel herum soweit lauffähig:


    Startbildschirm mit Optionen (Account erstellen, Account auswählen, Spieloptionen)


    Hab mich auch etwas mit Exceptions beschäftigt, sodass meine Accountklasse bei Aufruf mit


    Java
    Accounts.addAccount("Florian");


    eine UserExistException auslösen kann.


    Wer sich übrigens die Mindmap mal genauer angesehen hat, dem ist bestimmt aufgefallen, dass die Zweige Grundstücke, Gewächshäuser und Autos nach dem gleichen Schema aufgebaut sind. Jedes dieser Objekte hat Eigenschaften, einen Satz Optionen sowie Unterobjekte (Grundstück hat Gewächshäuser, Gewächshäuser haben Pflanzen, Auto hat Ladung).


    Das läd natürlich dazu ein, die Anzeige dieser Objekte über ein einziges View laufen zu lassen, was Arbeit ersparen und die Bedienung vereinheitlichen dürfte. :)


    Der nächste Schritt wird sein, die Datenbank zu entwerfen, wobei ich große Teile davon schon im Kopf habe und auch aus dem Browsergame übernehmen kann.
    Wenn Interesse besteht, kann ich das ER-Model ja zur öffentlichen Diskussion stellen...

    Um einige meiner Klassen, die keine GUI ansprechen plattformunabhängig zu halten, möchte ich auf das extends Activity verzichten. Das klappt auch soweit ganz gut, abgesehen von der Tatsache, dass natürlich einige Methoden fehlen. Unter anderem die Methode getApplicationContext().


    Da meine Datebankklasse SQLiteOpenHelper verwendet, muss auch der Context verfügbar sein. Diesen muss ich dann von einer Activity-Klasse, über evtl. mehrere Klassen ohne Activity bis zur DB-Klasse durchreichen. Um mir das zu ersparen, habe ich überlegt den Context per Singleton verfügbar zu machen. Bei meinen Recherchen bin ich aber auf einen Artikel gestoßen , der eindringlich von dieser Vorgehensweise abrät, allerdings in Zusammenhang mit einem Spring-Framework, welches mir nicht bekannt ist.


    Meine Frage: Ist es machbar / sinnvoll / elegant den ApplicationContext per Singleton verfügbar zu machen?

    Also, die professionelle Lösung für mein Problem hieße wohl DAO-Pattern um den Datenzugriff komplett zu abstrahieren - hab ich aber keinen Bock drauf.


    Ich werd mehrere Konstruktoren machen, je nachdem ob eine Id oder Cursor Objekt oder Array oder was immer auch zur Ermittlung der Objektdaten hilfreich sein könnte, übergeben wird.


    Mit Hilfe von Interfaces werd ich dann die Existenz der Methoden die für die Feinheiten nötig sind erzwingen und das wars. Dann hab ich zwar immer noch an verschiedensten Stellen SQL-Abfragen, aber eine Datenbank die grundlegende SQL-Befehle versteht, ist dann nunmal Vorraussetzung.


    Danke auf jeden Fall an Jon und ich werd die Lösung hoffentlich in den nächsten Tagen mitteilen... :)

    Ok, dein Verfahren ermöglicht es mir auch die Eigenschaften von von Erweiterungen der Klasse Pflanze wie Sonnenblume oder Gänseblümchen in der Datenbank zu speichern. Mir geht es jedoch hauptsächlich um das möglichs ressourcenschonende Einlesen dieser Daten in die Objekte.


    Wenn ich mich in meinem Gewächshaus Nr. 3 befinde, welches 50 Pflanzen beinhaltet, seinen es einfach nur Pflanzen, Sonnenblumen oder Gänseblümchen, würde eine SQL-Abbfrage ja ungefähr so aussehen


    sql = "SELECT pflanze_id FROM pflanzen WHERE pflanze_gewächshaus = 3";


    dann bekomme ich 50 Datensätze aus denen ich 50 Ojekte mit den Ermittelten Eigenschaften erstellen möchte.
    In der Einfachsten (uneleganten) Variante mache ich eine Schleife


    Java
    for (i=0;i<anzahl;i++)
    {
    id = datensatz[i][pflanze_id];
    
    
    pflanzen[i] = new pflanze(id);
    }


    Im Konstruktor jeder Planze wird dann nochmal eine Abfrage ausgeführt :


    SELECT * FROM pflanzen WHERE pflanze_id = pflanze_id


    Was natürlich eine Menge überflüssige Abfragen zur Folge hat.
    Ein Weg das Problem zu mildern ist, dass diese Abfrage nicht im Konstruktor, sondern in einer separaten Methode ausgeführt wird, welche erst ausgeführt wird, wenn eine Eigenschaft mittels get-Methode wirklich abgefragt wird.


    Eine Weiterentwicklung dieser Lösung war, gleich alle Felder zu ermitteln und den kompletten Datensatz an das Objekt zu übergeben.


    Java
    for (i=0;i<anzahl;i++)
    {
    pflanzen[i] = new pflanze(datensatz[i]);
    }


    in der Klasse Pflanze und ähnlichen Klassen habe ich dann Methoden, die überprüfen, ob eine id oder ein Datensatz übergeben wurde und die damit die entsprechenden Klassenvariablen füllen.


    Nun suche ich immer noch eine Möglichkeit diesen Mechanismus zu vereinheitlichen.

    Ja, Vererbung auf diesem Level beherrsche ich. Im konkreten Fall ging es aber um die Objektrelationale Abbildung, also das Speichern und Verwalten von Objektzuständen in der Datenbank. Wie ich im zweiten Eintrag beschrieben habe, hatte ich mir unter PHP schon ein ziemlich gutes System überlegt um Objekte mit den gespeicherten Eigenschaften aus der Datenbank zu laden. Dazu hatte ich in jeder Klasse, einige Methoden die immer mit nach dem selben Schema arbeiteten.


    Meine Überlegung war es nun in Java mit Hilfe der Vererbung eine Lösung zu finden, verschiedenste Objekte - also auch welche die nichts weiter gemeinsam haben, als dass sie durch einen Datensatz in einer beliebigen Tabelle mit Eigenschaften gefüllt werden - per extends mit diesen immer nach den gleichen Schema arbeitenden Methoden auszustatten. (boa, das war doch mal ein Satz)


    In der Praxis haben die Verschiedenen Klassen natürlich ganz andere Variablen, werden in verschiedenen Tabellen gespeichert und haben eine andere Feldanzahl und Bezeichnungen. Also alles in allem eine Problemstellung die auch für jemanden der OOP bereits verstanden hat nicht ganz einfach ist....


    (Nachtrag : Das genannte Browsergame hatte ich 2004 programmiert und meinte Kenntnisse haben sich seitdem signifikant verbessert ;) )

    Also für ein Projekt an dem viele Leute mitarbeiten sollen, ist der Verwaltungsaufwand für Kommentierung (JavaDoc), Versionierung (mit CVS o.ä.) und Bugtracking (mit Mantis o.ä.) so hoch, dass es sich wirklich nur für gigantische Projekte lohnt und bei kleinen Projekten mehr Arbeit bedeuten würde als die Programmierung ansich.
    Ich selbst hab mir die Programmierung eines sehr komplexen Spieles vorgenommen, aber trotzdem bin ich sicher, dass zu viele Köche den Brei verderben würden.

    Jo, am Anfang soll es eh nur ein offline Tamagotchi werden. Aber die Objektstruktur ist in meinem Kopf schon fast komplett. Auch Autos waren damals im Browsergame schon implementiert und das hat auch alles soweit funktioniert. Lediglich bei den Missionen ist es gescheitert, da das ganze Programm ein hoffnungsloser Spaghetticode war und jede Erweiterung Änderungen an x Stellen notwendig machte.


    Ich werde heute Abend erstmal die Klassen für Grundstück, Gewächshaus und Pflanze erstellen. Die Klassen für Datenbank und Spieler sind bereits lauffähig, sodass ich im Laufe der Woche meine erste Pflanze wachsen sehen werde... :)


    Das mit Länge und Breite (Höhe ist wohl irrelevant) des Gewächshauses ist ne gute Idee, hatte früher einfach nur qm als Eigenschaft für die Größe. Mit den Angaben kann ich dann die Gewächshäuser evtl. soger dynamisch Zeichnen auf einer Map des Grundstückes. Aber das kommt nätürlich erst später...

    Aaaaalso, du startest mit einem ganz kleinen Gewächshäuschen und 4 Samen, sowie 500€.


    Die Samen sähst du in deinem Gewächhaus aus, und giesst. (Jede Connabis-Sorte hat andere Optimalwerte für Wasser und Düngermenge, Lichtbedarf usw. sowie unterschiedliche Toleranzen für davon abweichende Werte)


    Nach einigen (ralen Tagen) siehst du auf deinem Handydisplay einen 2 Pixel großen Sämling.


    Irgendwann fängst du an zu düngen (wann der optimale zeitpunkt ist, muss jeder durch ausprobieren selber herausfinden und ist uU. von der Sorte abhängig)


    Das Startkapital reicht evtl. um eine Lampe zu kaufen, die jeweils einer Pflanze zugewiesen wird. Dadurch kann man abschätzen, wie sehr sich Licht auf das Wachstum auswirkt.


    Dann pflegt man seine Pflanzen auf diese Weise einige (reale) Tage bis Wochen, bis sie erntereif sind. Wann der optimale Zeitpunkt dazu ist, muss der Spieler acuh selbst rausfinden.


    Um die Ernte zu verkaufen, muss der Spieler online gehen, alle Verkaufsoptionen und Dinge die den offenen Markt betreffen, werden online in einer MySQL-Datenbank gespeichert.


    Wenn wieder Geld rein kommt, werden neue Samen gekauft und evtl. ein größeres Gewächshaus, potentere Lampen usw.


    Dazu kommt noch ein Skill-System wie aus Rollenspielen bekannt, mit eigenschaften wie Grüner Daumen, Geschäftssinn, Charisma, Technisches Geschick usw.


    Ideen hab ich da noch tausende um das Spiel umfangreicher und spannender zu machen...^^


    z.B. Missionen wie "bringe x Menge von Sorte y innerhalb von blah Stunden an Ort z", oder "Triff dich mit Spieler xy samt Auto bei z " - dann wird ein Trigger ausgelöst und es kann eine weitere Mission folgen

    Naja, es ist halt ein Managerspiel, wo nichts wirklich in Echtzeit läuft (außer das Pflanzenwachstum), sondern alle Aktionen des Spielers (Plfanze gießen, Auto kaufen) in der Datenbank gespeichert werden und sich auf spätere Aktionen auswirken (Auto wird angezeigt wenn Grundstück aufgerufen wird).


    Die technische Vorgehensweise hatte ich weiter oben eigentlich schon recht ausführlich beschrieben, oder willst du mehr über den Spielinhalt erfahren?


    [Blockierte Grafik: http://www.buschmann-edv.de/tausch/gm_android.png]

    Ich bin mit der OOP ja durchaus vertraut und auch das Prinzip der Vererbung ist mir bekannt, hatte nur gehofft, dass jemand schonmal das gleiche Problem hatte und schon ne Lösung parat hat die ich gleich auf mein Projekt übertragen kann. Aber das Buch ist trotzdem sehr interessant... :)

    Ich finde die vorgeschlagene Struktur von Jon absolut gut.


    Wie er bereits sagte, lohnt es sich nicht Foren zu unterteilen die sowieso kaum verwendet werden. Und in den Hardware-Foren ja kaum was los. Warum auch? Dies ist doch eine Entwicklerseite für Android-Software und keine "Ich hab das dickere Handy-Prollseite". Enstprechend sollte die Forenstruktur auch auf diese Zielgruppe zugeschnitten werden. Für mich als jemanden ganz ohne Android Handy, ist die ganze Sparte sowieso Off-Topic... ;)

    Hab es endlich geschafft die SQLite Datenbank zum Laufen zu kriegen. Das SQLite Tutorial hier im Forum hat mir echt nicht weiter geholfen, da die dortige Vorgehensweise wohl nur innerhalb eines Activity funktioniert und nicht in einer einfachen Klasse. Außerdem verschweigt es die Existenz des SQLiteOpenHelper, welcher die Handhabung der Datenbank auch hinsichtlich der Versionsverwaltung erheblich vereinfacht.


    Da ich nun Android-GUI, Java und Datenbank halbwegs im Griff habe, kann es nun mit der Entwicklung so richtig losgehen, oder mich zumindest mit Problemen auf fortgeschrittenem Level befassen. :D


    Da wäre zum Beispiel das Problem der Objektrelationalen Abbildung meiner Objekte (Grundstücke, Gewächshäuser, Pflanzen usw.) in der Datenbank (JPA gibts unter Adroid nicht).
    Für die oben genannten Objekte exisitiert jeweils eine eigene Tabelle mit Feldern für die Eigenschaften des jeweiligen Objektes. Unter PHP hatte ich es anfangs so gehandhabt, dass ich beim Erstellen eines Objektes die ID übergeben habe und im Konstruktor der entsprechende Datensatz gelesen und die Eigenschaften des Objektes gesetzt wurden.


    Um überflüssige Abfragen beim Erstellen ganzer Listen von Objekten zu sparen, hab ich das Füllen der Eigenschaften in eine loadData() Methode verlagert, die erst in den get-Methoden ausgeführt wird.


    Für den Fall, dass eine Abfrage von außen x Datensätze der Tabelle Spieler liefert, hab ich beim Durchlaufen der Ergebnisse natürlich nicht nur die ID an die Objekte übergeben, sondern den kompletten Datensatz. Dadurch konnten sämtliche Eigenschaften der Objekte mit einer einzigen Abfrage gefüllt werden.


    Dieses Verfahren hab ich bei vielen Klassen angewand und so ähnlich will ich es auch in Java machen. Ich frage mich jetzt nur, ob ich das nicht etwas eleganter implementieren kann, indem ich die dafür nötigen Strukturen nicht in jede Klasse schreiben muss sondern irgendwie vereinheitlichen kann.


    Ich weiß, dass mir die Vererbung dabei irgendwie helfen kann, aber dieser Mechanismus hat sich bei mir noch nicht verinnerlicht.


    Kann mir da irgendwer nen Denkanstoß geben? :)

    Jo, man merkt dass du aus dem C++ bereich kommst. Kann auf die Schnelle keine (dummen) Fehler in deinem Code erkennen, da ich kein C(++) kann. :D
    Bin allerdings sicher, dass es unter Java eine Lösung gibt, die weniger fummelig ist als dein Ansatz.


    Aber versuchs doch mal mit ner SQLite Datenbank. Ich empfehle die Verwendung des SQLiteOpenHelper, die Vorgehensweise des SQLite Tutorials hier im Forum ist nicht weniger fummelig (Sorry ensacom ;) )...