Ankündigung

Einklappen
Keine Ankündigung bisher.

Inventar für ein Browsergame sinnvoll programmieren - Wie?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Inventar für ein Browsergame sinnvoll programmieren - Wie?

    Hallo zusammen!

    Vorab möchte ich nicht unerwähnt lassen, dass ich bereits die Suchfunktion des Forums und natürlich auch die gängigen Suchmaschinen um Hilfe bemüht habe.

    ---

    In meiner Freizeit entwickle ich schon seit Jahren ein kleines Browsergame, das mangels freier Zeit immer wieder zum Erliegen kommt.
    Momentan suche ich eine Antwort auf die Frage, wie ich ein entsprechendes Inventar vor allem hinsichtlich der Ladezeiten sinnvoll programmieren könnte.

    In dem Spiel geht es in erster Linie darum, verschiedenste Rohstoffe zu immer neuen Items weiterzuentwickeln; Ein typisches "Crafting Game" also.

    Derzeit gibt es 22 verschiedene Ressourcen, die im Spielerinventar Platz finden sollen.


    Lösungsansatz 1

    Mein letzter Versuch am Anfang des Jahres sah vor, alle Items in einer Spalte zu hinterlegen (s. Bild).
    Das Problem bei diesem Lösungsansatz ist oder war, dass die Ladezeit erheblich unter dieser Vorgehensweise zu leiden scheint.






    Lösungsansatz 2

    Mein zweiter Lösungsansatz sah vor, für jedes Item eine eigene Spalte anzulegen (s. Bild).
    Diese Vorgehensweise schien hinsichtlich der Ladezeit zwar effizienter zu sein, allerdings beschleicht mich das durchaus irrationale Gefühl, dass dieser Lösungsansatz in Hinblick auf potentiell viele Spieler und eine enorme Anzahl an Datensätzen nicht der richtige Weg ist.





    Lösungsansatz 3

    Nun bin ich nach langer Sucherei auf die Möglichkeit gestoßen JSON zu verwenden (s. Bild)

    Leider habe ich mit JSON bisher keinerlei Erfahrungen gesammelt, so dass ich weder etwas über die Ladezeiten sagen kann noch über die Möglichkeit die Datensätze mittels PHP zu verwalten. Bei meinen experimentellen Versuchen fiel mir lediglich auf, dass das Hinzufügen und Aktualisieren des Datensatzes relativ fehleranfällig ist, wobei ich das durchaus verschmerzen könnte.

    Für mich stellt sich allerdings die Frage, ob JSON wirklich schneller ist, da der Datensatz viele "überschüssige" Zeichen in Form von ", [, {, :, } und ] enthält.





    ---

    Nun, welche Vorgehensweise würdet ihr wählen und warum? Oder würdet ihr es vielleicht ganz anders machen und vor allem: Wie?




    Liebe Grüße, vielen lieben Dank im Voraus und an die stillen Mitleser natürlich schon einmal einen guten Rutsch in das neue Jahr.

    Brombeertee
    Angehängte Dateien

  • #2
    Die Bilder für die Lösungsansätze 2 + 3 werden nicht angezeigt. Zudem wäre es sinnvoller dein SQL-Code zu zeigen.

    Kommentar


    • #3
      Was sind denn items bei dir?
      Zudem sollte man Spalten nicht durchnummerieren.
      Vielleicht hilft es dir auch, wenn du das Thema Normalisierung durcharbeitest.

      Kommentar


      • #4
        Hallo ihr Lieben!

        Die Bilder für die Lösungsansätze 2 + 3 werden nicht angezeigt.
        Seltsam... Ich habe die Bilder direkt über das Forum hochgeladen und bei mir werden sie auch angezeigt.
        Funktioniert es nun?

        Zudem wäre es sinnvoller dein SQL-Code zu zeigen.
        Den alten Code habe ich mittlerweile gelöscht, allerdings war er auch nicht sonderlich repräsentativ. Ich versuche aber gerne, diesen zum Zwecke des Austausch zu rekonstruieren.

        Zu Lösungsansatz 1 und 2

        PHP-Code:
        <?php

        $query 
        mysqli_query($con"SELECT * FROM Inventar WHERE userid=$userid);
        $obj = mysqli_fetch_object($query);

        echo 
        $obj->Item1;
        echo 
        $obj->Item2;
        echo 
        $objs->Item3;

        [...]
        Im Grunde genommen habe ich also einfach nur die einzelnen Spalten innerhalb der Tabelle nach ihren Werten abgefragt und im Anschluss mit PHP mit diesen Werten gearbeitet.



        Was sind denn items bei dir?
        Items sollen alle Gegenstände sein, die aus den Ressourcen heraus geschaffen werden können. Die Ressourcen Holz, Stein, Metall und andere sollen dabei separat in der Datenbank hinterlegt werden. "Echte" Items sind dann also die Erzeugnisse (z.B. Schwerter, Schilde, usw.).

        Vielleicht hilft es dir auch, wenn du das Thema Normalisierung durcharbeitest.
        Hm... Ich fürchte fast, dass mir das nicht weiterhelfen wird. Ich habe mir den Artikel aufmerksam durchgelesen und auch noch andere zu diesem Thema angesehen. Soweit ich das Thema recht verstehe, setze ich diese Form des Datenbankaufbaus teilweise bereits um.

        Die Normalisierung der Datenbanken reduziert die Tabellen aber nicht unbedingt auf ein Minimum, oder? Auch wenn also für die Items und die Ressourcen verschiedene Tabellen angelegt werden, bleibt die Anzahl der Datensätze, die abzufragen sind, identisch hoch.

        Meine Idee, JSON in der Datenbank zu speichern, war also eher ein minimalistischer Gedanke. JSON lässt sich relativ einfach dekodieren und enkodieren und man benötigt lediglich eine Tabelle bzw. Spalte.

        Die Frage ist, ob es Sinn macht JSON so zu verwenden. Ich habe gelesen, dass diese Form der Anwendung durchaus performant und sicher ist. Aber stimmt das auch?

        Zudem sollte man Spalten nicht durchnummerieren.
        Dessen bin ich mir durchaus bewusst, aber vielen Dank. Die Spalten "Item1, Item2, Item3, ..." sollten lediglich zur Veranschaulichung dienen und wären in der Praxis dann entsprechend "Holzschwert, Bronzeschwert, Eisenschwert, ...".



        Liebe Grüße

        Brombeertee

        Kommentar


        • #5
          Lösungsansatz 2 ist der einzig sinnvolle hier.

          Vor der Anzahl der Datensätze braucht man keine Angst haben, wenn die Tabelle sinnvoll indiziert ist.
          Im Durchschnitt wirst du bei den anderen beiden Lösungen auch mehr Speicherplatz verbrauchen, auch wenn es weniger Datensätze sind. Das liegt an den Datentypen bzw. Überflüssigen Spalten.

          Mit Ansatz 2 hast du auch die größeren Freiheiten, mit den Daten zu arbeiten. Es lässt sich beispielsweise auch direkt in der Datenbank nach Menge oder ItemId sortieren. Desweiteren lassen sich sehr einfach neue Items hinzufügen, ohne dass die Struktur der Tabelle angepasst werden muss.

          Im Zuge einer weiteren Normalisierung, wäre noch eine weitere Tabelle notwendig, um das sauber zu machen.

          Tabelle Item_type
          Id - integer / autoincrement
          Name - varchar(20)

          Tabelle Items: Userid - integer
          Itemtypeid - integer
          Amount - integer

          Items.Itemtypeid erhält eine Fremdschlüsselreferenz/ Constraint auf item_type.id

          Einträge mit einem amount von 0 sollten aber auch gar nicht erst in die Tabelle Items eingetragen werden. Darauf sollte man bei der Programmierung achten.

          Kommentar


          • #6
            Hallo Gnom42!

            Erst einmal vielen Dank für deine Ausführung. Ich denke, dass mir das weiterhilft.

            Im Zuge einer weiteren Normalisierung, wäre noch eine weitere Tabelle notwendig, um das sauber zu machen.
            Eigentlich hatte ich nicht vor, den Namen des Items, eine Beschreibung und etwaige Werte (Stärke, Ausdauer, ...) in der Datenbank zu hinterlegen, sondern wollte mit multidimensionalen Arrays arbeiten. Bietet die Arbeit mit MySQL dahingehend Vorteile abgesehen von der Normalisierung? Mein Hintergedanke war dabei vor allem die Möglichkeit, das Spiel zu einem späteren Zeitpunkt gegebenenfalls auch in eine andere Sprache zu übersetzen.



            Liebe Grüße

            Brombeertee




            Kommentar


            • #7
              Zitat von brombeertee Beitrag anzeigen
              Eigentlich hatte ich nicht vor, den Namen des Items, eine Beschreibung und etwaige Werte (Stärke, Ausdauer, ...) in der Datenbank zu hinterlegen

              Zitat von brombeertee Beitrag anzeigen
              hmmm ... sieht für mich aber ganz danach aus.



              Und was hat das Arbeiten mit Arrays im Programm/Script mit der Ablage in der Datenbank zu tun?!
              Das sind unabhängige Dinge, die nicht direkt etwas mit einander zutun habe.

              Und insbesondere, wenn du (später) noch Übersetzungen hinzufügen willst, solltest du einen hohen Grad der Normalisierung einhalten, damit du auf der letzten Ebene dann auf andere Texte verweisen kannst.
              ​​​​​​​Aber das hängt dann ja auch immer davon ab, wie du das umsetzen möchtest mit der Übersetzung.

              Kommentar


              • #8
                Hallo Gnom42!

                Das Bild sollte tatsächlich nur der Veranschaulichung dienen und etwas besser verdeutlichen, worauf ich hinaus möchte.
                In der Praxis sollte die Item ID in der Datenbank dann als 100, 200, 230, ... vermerkt sein.

                In PHP dachte ich dann an eine solche Abfrage:

                translation.php

                PHP-Code:
                $items = array(
                100 => array(
                "name" => "Holzschwert",
                "desc" => "Ein einfaches Schwert, geschaffen aus Holz.",
                "rarity" => "normal"
                ),
                200 => array(
                "name" => "Mithrilschwert",
                "desc" => "Geschmiedet im Feuer des Schicksalsberges.",
                "rarity" => "legendary"
                )
                ); 
                ausgabe.php

                PHP-Code:
                $query mysqli_query($sqli"SELECT itemid, amount FROM inventory WHERE userid='$userid'");
                $itemdata mysqli_fetch_object($query);

                echo 
                'Du besitzt' $itemdata->amount ' ' $items[$itemdata->itemid]['name']; 
                Macht das Sinn?



                Liebe Grüße

                Brombeertee

                Kommentar


                • #9
                  Moin, Moin, brombeertee !

                  Würde wohl funktionieren, habe ich aber etwas Bauchweh mit.
                  Übersetzungsreferenzen sollten immer nur aus key-value Paaren bestehen, keine weitere struktur.

                  Daher folgende Möglichkeiten als Vorschlag.

                  A) Generisch Übersetzungs-Ids.
                  Die Ids für die Items setzen sich direkt aus Eigenschaften des Items zusammen.

                  translation_de.php
                  PHP-Code:
                  <?PHP $translation['item_100_desc'] = 'Ein einfaches Holzschwert';
                  $translation['item_100_name'] = 'Holzschwert';
                  PHP-Code:
                  $query mysqli_query($sqli"SELECT itemid, amount FROM inventory WHERE userid='$userid'");
                  $itemdata mysqli_fetch_object($query);

                  echo 
                  'Du besitzt' $itemdata->amount ' ' $translation['item_'.$itemdata->itemid.'_name']; 
                  Der Vorteil ist, dass man nicht jede Id explizit definieren muss.
                  Nachteil ist, dass sich eine Prüfung auf Vollständigkeit kaum Automatisch durchführen lässt.

                  B) komplette Referenzierung und Datenhaltung in der DB

                  Tabelle inventory
                  userid - int
                  itemid - int
                  amount - int

                  Tabelle Items id - int, autoincrement
                  translationCodeName - varchar(20)
                  translationCodeDesc - varchar(20)
                  rarityId - int

                  Tabelle rarityId
                  Id - int, autoincrement
                  TranslationCode - varchar(20)

                  Tabelle Translation
                  id - int, autoincrement
                  code - varchar(20)
                  language - Char(2)
                  text - varchar (255) oder text

                  Tabelle Language
                  Id - int, autoincrement
                  Code - Char(2) - ISO konformer Sprachcode

                  Zugriff auf die Übersetzung kann man entweder durch direkte SQL Joins realisieren oder über eine Statische Klasse/Methode, die den Zugriff auf die Übersetzungen prinzipiell handhabt.
                  Aus persönlicherpersön empfehle ich letzteres. Solch eine Klasse kann dann auch entsprechend cachen oder Vorladen, um DB Zugriffe zu reduzieren.

                  Die Datenbanklösung hat die weiteren Vorteile, dass sich relativ einfach Inkontinenzen und fehlende Übersetzungen aufspüren lassen und sich einfach eine Administrative Oberfläche zur Pflege der Daten realisieren lässt. Glaube mir, etliche Referenzdateien immer wieder anzupassen geht einem irgendwann ganz schön auf die Nerven

                  C) Mischlösung.
                  Falls du dennoch ein Fan der Referenzdateien bist und es so umsetzen möchtest, dann nutze doch trotzdem auch die Vorteile von Variante B).
                  Lege die Tabelle Translation und Languages an. Der Rest bleibt unverändert.
                  Anstatt die Übersetzungen direkt aus der DB auszulesen während der Laufzeit deines Spieles, küsst dieses die Informationen weiterhin aus Den translation.php Dateien. Diese Dateien werden aber nicht von Hand geschrieben, sondern generiert über eine Administrative Oberfläche.


                  Ich weiss ja nun nicht, ob dein Beispiel aus Ausgabe.php nachher auch so umgesetzt werden soll in dem Stil... Aber falls ja, dann zu es bitte nicht. Verwende bitte Klassen. Da tust du dir selbst ein Gefallen mit. Und auch das Handling mit diversen Eigenschaften der Daten wird erheblich einfacher und übersichtlicher.

                  ​​​​

                  Kommentar


                  • #10
                    Ich halte es nicht für sinnvoll Übersetzung in einer DB zu halten. PHP hat gettext funktion welches explizit dafür gemacht wurde. Außerdem bietet gettext auch noch Plural formen an.

                    LG
                    apt-get install npm -> npm install -g bower -> bower install <package> YOLO [URL]https://www.paypal.me/BlackScorp[/URL] | Mein Youtube PHP Kanal: [url]https://www.youtube.com/c/VitalijMik[/url]

                    Kommentar


                    • #11
                      entwickle ich schon seit Jahren ein kleines Browsergame
                      Stell das doch erst mal in einer Sprache fertig, danach kannst du dich um die Erweiterung kümmern, sonst vergehen wohl wieder Jahre.

                      Kommentar

                      Lädt...
                      X