mmofacts.com

Ideensammlung - Bauschleife

gepostet vor 16 Jahre, 4 Monate von s1x

Hallo und einen guten Abend zu dies später Stunde,

ich hab nun seit mehren Stunden, und zwei Tagen ein kopfzerbrechends Problem wo ich nicht weiter komme und jetzt einfach mal, fragen wollte um somit eventuell ein bischen Ordnung in mein Kopf zu kriegen. Wie auch immer kommen wir zu meinem Problem. Es liegt hierbei nicht an der Programmierung direkt sondern an der Umsetztung, genau da stehe ich auf dem Schlauch.

Ich möchte für meine Einheiten im Browsergame eine Bauschleife.
Kurz zum Prinzip, die Einheiten sind unterteilt in 3 verschiedene Typen. Die "0" steht für Infanterie, "1" für schweres Gerät (Panzer & Co.), "2" steht für die Luftwaffe.

Umgesetzt habe ich bereits das maximal zehn Aufträge ausgeführt werden (was für eine Meisterleistung ). So zudem wird jede Einheit einzeln produziert - spricht wenn ein Spieler den Auftrag gibt 100 Soldaten zu produzieren die 3600 Sekunden (eine Stunde) "Bauzeit" benötigen wird trotz alle dem für Minute der eine Soldat produziert und von der Gesamtmenge abgezogen. Soweit funktioniert das ganze auch ohne Problem.

Eigentlich sollte jetzt der Banale teil kommen, aber hier stehe ich anscheined auf dem Schlauch.
Ich habe mir das so vorgestellt das die Liste abgearbeitet wird, und nach der Fertigstellung zum nächsten "weiterspringt". Und das es natürlich möglich ist jeden Auftrag wieder abzubrechen.
Hierbei habe ich mir die Spalten überlegt die ich mindestens brauche um die Datenbank mit den neuen Einheiten zu füttern.

Das sind diese hier:
id | eid (Einheiten ID) | menge | sid (Stadt ID) | typ

Hierzu hatte ich dann eine Tabelle angelegt die auf den Spalten oben basierte, das sah dann so aus:
id | eid (Einheiten ID) | menge | sid (Stadt ID) | starttime | endtime | bauzeit (gesamt) | typ

Das hatt auch alles funktioniert, doch da kam mir die Idee - Ich muss ja noch das Abbrechen der Produktion einbauen. Aber genau da wurde es schwierig und es schien mir gar unmöglich mit diesem Aufbau das Abbrechen zu ermöglichen. Die |starttime| sowie die |endtime| basieren nämlich auf der Rechnung wann die vorherige Einheit gestartet bzw fertiggstellt werden soll. Somit müsste man alle Sachen neu berrechen. Kurzum empfand ich das als eine relative Schwachsinnige Idee und nahm mir zu Herz eine einfachere Methode zu entwickeln. Mit dieser bin ich dann aber noch mehr gescheitert.

Inzwischen sieht meine Datenbank so aus:
id | sid | eid | menge | endtime| typ | position

Dort war es dann so das ich die Position durch die Angabe von num_rows gemacht habe. Sprich die Einträge gezählt +1 und das war dann die Position. Das Problem kam aber genauso schnell. Ich musste wieder alle Einträge verändern und das kam mir ebenso schwachsinnig vor. Also hab ich diese Idee auch wieder verworfen.

Nun und jetzt stehe ich komplett auf dem Schlauch, ich hab keine Ahnung wie ich sinnvoll diesen Weg angehen soll, und hoffe das ihr mich enventuell kleine Denkhilfen verpassen könntet.
Wie gesagt mir ist es wichtig folgende Punkte zu erfüllen:

  1. Bauschleife (max 10 Einträge)
  2. Jede Einheit wird nach ihrer Bauzeit eingetragen (Siehe Anmerkung oben)
  3. Aufträge laufen nacheinander ab
  4. Abbrechen soll möglich sein
Ich bedanke mich für das aufmerksame lesen und hoffe das mir jemand auf den Sprung hilft.
Schönen Abend noch, s1x

gepostet vor 16 Jahre, 4 Monate von Fobby

Ich weiß ja nicht, in welchen Größenordnungen bei dir Einheiten produziert werden aber der meiner Meinung nach einfachste Weg wäre hier ein Eintrag pro Einheit mit Start- und Endzeit. So kann der Bau jeder einzelnen Einheit (oder aller Einheiten, das ist dann aber eher Aufgabe der GUI, das nett zu gestalten) simpel durchgeführt werden.

Natürlich hast du so mehr Datenbankeinträge aber das sollte sich ja in Grenzen halten. Wie gesagt, kommt ganz auf die Mengen an. Wenn ein Spieler am Tag 10.000 Einheiten bauen kann, sieht das schon ekliger aus.

Ein anderer Ansatz wäre das Gruppieren von Bauaufträgen. z.B. könnte ein Auftrag von 100 Soldaten in 10 Aufträge zu je 10 Soldaten aufgeteilt werden. Heißt. es werden immer 10 Soldaten gleichzeitig ausgebildet und es können nur 10er-Trupps abgebrochen werden. Inwiefern das jetzt den Spieler einschränkt, kann ich nicht beurteilen, ist lediglich ein Vorschlag.

gepostet vor 16 Jahre, 4 Monate von s1x

Erst einmal danke fürs antworten ;)
Das mit den Einzelaufträgen hatte ich mir auch bereits überlegt. Ich hab dann auch Nachgerechnet, im "worst case" Fall würde ein Spieler pro Tag 12.551 Einheiten produzieren (sprich das volle Lager ausnutzen zum produ. in die billigste Einheit). Das sind dann bei bei 100 Spielern die das machen ~ 1.000.000 Einträge wenn man die bereits gebauten dann mal abzieht. Also zu viel. Man könnte natürlich hier einfach auf die Quantität verzichten Preise einfach alle multiplizieren somit kommt dann weniger die Masse sondern die Qualität. Hierbei kommt aber wieder das Problem was ich angesprochen habe. Trage ich Start und Endzeit in die Datenbank einer einheit, wir das abbrechen ein Kraus.

Hier ein Beispiel, ich baue eine Liste mit 5 Einheiten:

#|NAME|MENGE|START|ENDE
1|xxxx|   5     | 13:05 | 13:06
2|xxxx|   5     | 13:06 | 13:07
3|xxxx|   5     | 13:07 | 13:08
4|xxxx|   5     | 13:08 | 13:09
5|xxxx|   5     | 13:09 | 13:10

Nun stelle dir mal vor ich breche Auftrag nummer 2 ab. Nun muss ich jeden Auftrag die Zeit von Auftrag nummer 2 abziehen. Das wäre schon möglich. Aber das sind dann bei max. 10 Einträgen, im worst case 9 Einträge die ich ändern müsste. Das wäre meiner Meinung nicht optimal.

Das ganze zu Gruppieren wäre dazu die alternative das ist richtig. Doch dann kommt wieder das mit dem Abbrechen hinzu. Langsam kommt mir die Frage ob es vielleicht doch nicht anders geht? ;)

Vielen Dank, s1x

gepostet vor 16 Jahre, 4 Monate von Fobby

Original von s1x

[...], im "worst case" Fall würde ein Spieler pro Tag 12.551 Einheiten produzieren

Und inwiefern ist das realistisch? Interessant ist in dem Fall doch eher der average case. Ich nehm einfach mal an, dass der deutlich darunter liegt.

Original von s1x

#|NAME|MENGE|START|ENDE
1|xxxx|   5     | 13:05 | 13:06
2|xxxx|   5     | 13:06 | 13:07
3|xxxx|   5     | 13:07 | 13:08
4|xxxx|   5     | 13:08 | 13:09
5|xxxx|   5     | 13:09 | 13:10

Nun stelle dir mal vor ich breche Auftrag nummer 2 ab. Nun muss ich jeden Auftrag die Zeit von Auftrag nummer 2 abziehen. Das wäre schon möglich. Aber das sind dann bei max. 10 Einträgen, im worst case 9 Einträge die ich ändern müsste. Das wäre meiner Meinung nicht optimal.

Klar änderst du 9 Einträge - aber mit einem einzigen Query. Das ist ein nicht zu verachtender Unterschied. Und um den Query kommst du sowieso nicht drumrum, mit keiner Lösung :)

gepostet vor 16 Jahre, 4 Monate von exe

Im Grunde reichen schon 3 Spalten. Die Anzahl der Einheiten die noch ausstehen, die Zeit wann die letzte Einheit fertig gestellt wurde und die Bauzeit pro Einheit.

Der Zeitpunkt der letzten Einheit wird bei einem neuen Auftrag auf den Startzeitpunkt des Auftrags gesetzt. Bei einem Folgeauftrag setzt du den Zeitpunkt einfach auf den Zeitpunkt des vorherigen Auftrags und addierst die Einheitenzahl * Bauzeit pro Einheit dieses Auftrags dazu.

Wenn du wissen willst wieviele Einheiten eines Auftrags fertig geworden sind:

abrunden((aktuelle Zeit - Zeit letzte Einheit) / Zeit pro Einheit)

Wenn du einen Auftrag löschst setzt du den Zeitpunkt aller Folgeaufträge folgendermaßen neu:

Zeitpunkt aller verbleibenden Aufträge -= Verbleibende Einheiten des gelöschten Auftrags * Bauzeit pro Einheit

Wenn du die Aufträge ausliest sortierst du nach Zeitpunkt der letzten Einheit.

Die Berechnung würde ich in eine Funktion kapseln und einfach an allen Stellen, wo die Einheiten ausgelesen werden, vorher aufrufen. Damit sparst du dir eine extra Bauschleife die im Hintergrund läuft und ständig Resourcen frisst und aktualisierst die Datenbank nur dann wenn die Daten auch wirklich genutzt werden. Die fertiggestellten Einheiten kannst du dann auch schon in der Datenbank rechnen wenn du die obige Formel einfach in dein SELECT einbaust.

gepostet vor 16 Jahre, 4 Monate von cherry

Wenn Du nicht alle Eintraege aendern willst koenntest Du die Datenstruktur so sehen:

Bauschleife

 - Eintrag1

 - Eintrag2

 - Eintrag3

In der Bauschleife speicherst Du wann der ganze Spass gestartet ist, also wann der Schleife was hinzugefuegt wurde. Und da dran haengst Du einfach die Baueintraege mit EinheitenID und Menge und Dauer. Macht das ganze halt komplizierter weil Du ne Tabelle mehr kriegst (die die Bauschleifen enthaelt) aber vielleicht dafuer logischer und einfacher zu durchschauen.

gepostet vor 16 Jahre, 4 Monate von s1x

Original von Fobby

[..]

Klar änderst du 9 Einträge - aber mit einem einzigen Query. Das ist ein nicht zu verachtender Unterschied. Und um den Query kommst du sowieso nicht drumrum, mit keiner Lösung :)

 Stimmt, habe ich gerade auch gemerkt.

Original von exe

Im Grunde reichen schon 3 Spalten. Die Anzahl der Einheiten die noch ausstehen, die Zeit wann die letzte Einheit fertig gestellt wurde und die Bauzeit pro Einheit.

Der Zeitpunkt der letzten Einheit wird bei einem neuen Auftrag auf den Startzeitpunkt des Auftrags gesetzt. Bei einem Folgeauftrag setzt du den Zeitpunkt einfach auf den Zeitpunkt des vorherigen Auftrags und addierst die Einheitenzahl * Bauzeit pro Einheit dieses Auftrags dazu.

Wenn du wissen willst wieviele Einheiten eines Auftrags fertig geworden sind:

abrunden((aktuelle Zeit - Zeit letzte Einheit) / Zeit pro Einheit)

Wenn du einen Auftrag löschst setzt du den Zeitpunkt aller Folgeaufträge folgendermaßen neu:

Zeitpunkt aller verbleibenden Aufträge -= Verbleibende Einheiten des gelöschten Auftrags * Bauzeit pro Einheit

Wenn du die Aufträge ausliest sortierst du nach Zeitpunkt der letzten Einheit.

Die Berechnung würde ich in eine Funktion kapseln und einfach an allen Stellen, wo die Einheiten ausgelesen werden, vorher aufrufen. Damit sparst du dir eine extra Bauschleife die im Hintergrund läuft und ständig Resourcen frisst und aktualisierst die Datenbank nur dann wenn die Daten auch wirklich genutzt werden. Die fertiggestellten Einheiten kannst du dann auch schon in der Datenbank rechnen wenn du die obige Formel einfach in dein SELECT einbaust.

 Perfekt. Inzwischen habe ich es geschafft, genau das hat mir gefehlt. Nun klingt es sogar für mich logisch, wieso ich nicht gleich darauf gekommen bin. :)
Dadurch ist mir dann auch die Möglichkeit gekommen geschickt abzubrechen. Einfach alle Einträge die nach dem, der gerade in Bau ist die startzeit ändern und abziehen. Wieso ich da nicht gleich darauf gekommen bin frage ich mich aber.. Nungut besser jetzt als nie.

Original von cherry

Wenn Du nicht alle Eintraege aendern willst koenntest Du die Datenstruktur so sehen:

Bauschleife

 - Eintrag1

 - Eintrag2

 - Eintrag3

In der Bauschleife speicherst Du wann der ganze Spass gestartet ist, also wann der Schleife was hinzugefuegt wurde. Und da dran haengst Du einfach die Baueintraege mit EinheitenID und Menge und Dauer. Macht das ganze halt komplizierter weil Du ne Tabelle mehr kriegst (die die Bauschleifen enthaelt) aber vielleicht dafuer logischer und einfacher zu durchschauen.

 Das ist richtig. Hätte ich das jetzt nicht so gelöst hätte ich die Variante benutzt. Das wäre auch sehr interssant da man so die Einträge leichter von der Position ändern könnte. Aber immoment bin ich nur froh wenn die Bauschleife bugfrei läuft. Hab erstmal genug von der. :D

Und auch hier nochmal ein kräftiges Danke an euch, bin ich froh das es euch sowie die Community gibt, im Internet hab ich echt rein garnichts gefunden. Bzw. wusste ich garnicht wonach ich suchen sollte. :)
Recht herzlichen Dank, und schönen Abend / Nacht noch.
Gruß, s1x

gepostet vor 11 Jahre, 5 Monate von Alublech

Hey Leute.

Ich weiß dieser Thread ist schon fast 5 Jahre alt. Aber ich bräuchte eure Hilfe bezüglich der Bauschleife.

Ich programmiere zurzeit auch ein Browergame und hänge nun bei der Bauschleife für Einheiten fest. Wenn der Eintrag in die Datenbank erst getätigt wird, wenn man die EInheiten baut, wie frage ich dann ab, ob die Einheit fertig ist oder nicht? Hätte einer vielleicht sogar ein Beispielscript für mich?

gruß

Alublech

Auf diese Diskussion antworten