PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Spielfeld wie vernünftig ablegen?


Mantarrochen
28.05.2009, 15:30:13
Stellt euch ein schachbrettartiges Spielfeld vor, auf dem Spieler eins Türme platzieren kann, die in eine feste Richtung schauen und eine feste Reichweite besitzen. Tappt Spieler zwei in seiner Runde nun in den Wirkungsbereich der Türme, geschieht ihm halt Unheil. :)

Ich beschäftige mich mit der Frage, wie ich das Setzen der Türme nun vernünftig in einer DB ablegen kann? Mein erster Gedanke war, das Spielfeld 1:1 in eine Tabelle der DB abzubilden mit einem autoincrement vor jeder Reihe und nummerierten Spaltennamen. Liegt ein Spielfeld nun im Wirkungsbereich von Turm 1, so schreibe ich eine 1 in die entsprechende Zelle der Tabelle. Spieltechnisch betrachtet hat das Feld nun den "Zustand 1"; betritt ein Spieler dieses Feld, geschieht mit ihm das, was "Zustand 1" so zu bieten hat.

Jetzt kann es aber passieren, dass die Reichweiten der unterschiedlichen Türme sich auf dem Spielfeld kreuzen - das Feld, auf dem sie sich kreuzen, hätte dann nach obiger Methode zwei "Zustände". Und damit die entsprechende Zelle in der Tabelle zwei Werte.

Was nach meinen anfänglichen, von laienhafter Naivität geprägten Recherchen ganz schlechtes Kino ist. Von wegen "Verstoß gegen xte Normalform" und ähnlichem.

Ergo suche ich jetzt nach Alternativen. Eine erste könnte sein, für jedes Feld eine eigene kleine Tabelle aufzumachen. Diese bestünde nur aus dem autoincrement und der Spalte "Zustand". Somit könnte zu jedem Feld die Zustände untereinander aufgelistet werden. Wäre ne Lösung. Allerdings wie ist denn das: die gesamte Datenbank hätte dann u.U. 100 oder mehr kleine Tabellen - einige bis die meisten davon sogar leer! - ist das chic?

Eine zweite Alternative ist, pro "Zustand" eine Tabelle zu eröffnen. Diese verfügt dann über das autoincrement und die Spalte "Feld". Dort wären dann die Felder untereinander aufgelistet, die den entsprechenden Zustand beherbergen. Da ich aber plane, mehr Zustände als Felder aufzubieten, hätte ich hier gar noch mehr Tabellen als in Option 1. Knifflig.

Ich glaube, ich habe mir während meiner kleinen Abhandlung meine Frage schon fast selbst beantwortet. Vorschlag eins scheint sich als Favorit herauszukristallisieren. Aber was sagt denn ihr dazu, die geneigte Leserschaft? Alles Humbug? Bravo? Wen juckts?

Lasst es mich wissen. :)

Indyk
02.06.2009, 08:50:16
Hallo Mantarrochen,

ich werde nicht weiter auf deine vorschläge einegehen sondern nur schnell schreiben wie "ich" es machen würde, was keines wegs der beste weg sein muss.

Ich würde für die Türme die koordinaten speichern wo sie stehen, deren ausrichtung (himmelsrichtung) und deren reichweite.

Wenn der Spieler jetzt auf das Feld 99:54 geht, Selectiert man alle Türme deren Reichweite dieses Feld einschließt, wenn du dann die Türme hast kannst du ja belieb fortfahren und die eigenschaften der türme selektieren , wie hoch der schaden ist, was für auswirkungen ein treffer hat, trefferchancen, what ever.

ich rate davon ab alle felder in der datenbank abzuspeichern, es ist viel sinnvoller nur die felder abzuspeichern auf denen etwas ist (türme z.b.)

vielleicht hilft dir das.

Mantarrochen
04.06.2009, 14:22:14
Danke, Indyk, für deine Antwort. Ich hatte schon die Befürchtung, meine Anfrage bliebe unbeantwortet. Vielleicht gehört es ja auch einfach zu deinen Aufgaben, bisher unbeachtete Threads mit einer Antwort aufzupeppen.

Nur die Türme anstatt alle Felder abzuspeichern, klingt erst einmal gut. Müsste ich dann nicht auch zu jedem Turm in der Tabelle dann auch die Felder mitabspeichern, die dieser Turm erreicht? In deinem Beispiel wäre das dann

<table>
<tr>
<th>auto</th><th>turm</th><th>steht auf</th><th>wirkt auf(1)</th><th>wirkt auf(2)</th><th>wirkt auf(3)</th><th>wirkt auf(4)</th>
</tr>
<tr>
<td>1</td><td>1</td><td>99:54</td><td>100:54</td><td>101:54</td>
</tr>
</table>

für einen Turm vom Typ 1, der zwei Felder nach rechts wirkt.

Beim OnClick-Event, das der Spieler auslöst, wenn er das nächste Feld betritt, müsste ich dann diese Tabelle absuchen und die "wirkt auf(x)" Spalten nach einer Übereinstimmung des aktuellen Feldes durchsuchen.

Hast du es so gemeint?

PS.: Oh, der Code wird ja gar nicht ausgeführt. Sorry! ^^

Indyk
04.06.2009, 14:38:08
Hallo Mantarrochen, nein.

Du solltest (nach meinem Vorschlag) nur die koordinaten abspeichern wo der Turm steht, in welche richtung er schaut und wie weit er schauen kann! Alles andere kannst du von diesen daten ableiten.

Können diene Türme auch diagonal schießen?

(falls nicht:)
Wenn du auf Feld 0:0 stehst, dann würde ich erstmal schauen ob türme auf der x achse stehen, wenn ja, ob sie in die richtung gucken, wenn ja, ob ich ihn ihrer reichweite bin, selbe prozedur für die y achse.

Vielleicht gibt es ja irgend welche coolen Algorithmen für Koordinaten Berechnung und ähnliches. Um die Entfernungen besser zu brechnen, vll. hast du ja später flächenschaden der dann von zentrum abflacht usw..

bleib am ball ( :

Mantarrochen
04.06.2009, 15:48:24
Um ehrlich zu sein, ich hatte deinen Vorschlag auch schon zuvor verstanden, aber das Ableiten der Daten hat mich etwas abgeschreckt.

Man fängt ja immer mal klein an .-) , deshalb nehmen wir einfach Türme an, die in x- oder y-Richtung schießen. In diesem Fall funktioniert dein Vorschlag sehr gut. Dabei kann man sogar die Orientierung der Türme weglassen - diese läßt sich dann in die Reichweite mit einbauen (mit oder ohne negativem Vorzeichen).

Die Spalten benenne man dann so: auto/turmtyp/turmX/turmY/reichweiteX/reichweiteY. Das Schöne an diesem Fall ist ja, dass man bloß die Zeilen betrachten braucht, in denen entweder SpielerX und TurmX übereinstimmen oder eben dasselbe in grün mit y. Hat die entsprechende Differenz SpielerX-TurmX (oder Y) gleiches Vorzeichen wie die dazugehörige Reichweite und ist vom Betrag her kleiner, ist der Spieler getroffen.

Was ich da gerade formuliert habe, kann man getrost als Metrik bezeichnen. Mit der ich dann fern jeder Datenbank in einem Script ausrechne, ob der Spieler erwischt wird. Ich wiederhole nochmal, das Schöne an dieser einfachen Metrik ist, dass ich in meiner Tabelle nur bestimmte Zeilen zu betrachten brauche und auch leicht sehe, wann eine Abfrage überhaupt nötig ist.

Allerdings sollen die Türme natürlich auch was anderes können als bloß gerade schießen. Du sagst es ja vortrefflicherweise schon selbst: Flächenschaden, diagonal, alles soll dabei sein, hehe. Und dann komme ich in die Lage, alle Türme zu überprüfen und mittels Metrik auszurechnen, ob sie den Spieler erreichen.

Das hieße im Klartext, bei jedem Schritt des Gegenspielers müsste ich die Daten aller Türme auslesen und umrechnen. Auch wenn das aktuelle Feld gar nicht bedroht wird!

Dem gegenüber steht mein ursprünglicher Gedanke. In der Phase, in der ein Turm gesetzt wird, eröffne ich durch das Setzen des Turms eine Tabelle (meinetwegen mit dem Namen "Feld77"). In dieser Tabelle steht nur, von welchem Typ der Turm ist. Eine Metrik rechnet nun aus, welche weiteren Felder von ihm betroffen sind. Sie leitet nun ein, dass auch Tabellen zu den ausgerechneten Feldern eröffnet werden ("Feld78", "Feld79", usw.) bzw. - falls sie schon existieren - unseren Turmtypus unten anhängen.

Was passiert nun in der Phase, in der es darum geht, in die Türme zu tappen? Ich ziehe auf ein Feld, und das Programm prüft, ob die dazugehörige Tabelle existiert. Falls nicht - Glück gehabt. Das klingt für mich nach weniger Arbeit als alle Türme einzulesen und umzurechnen.

Existiert die Tabelle, wird sie Zeile für Zeile abgearbeitet (da stehen nur die Turmtypen untereinander, die auf dieses Feld wirken. Im Prinzip also: Zeile 1, Turm 30, ergo: 20 Schaden; Zeile 2, Turm 7, ergo: nochmal 10 Schaden).

Dieses Vorgehen scheint mir weniger Rechenzeit in Anspruch zu nehmen, laienhaft ausgedrückt. Es werden dabei natürlich eine Menge Tabellen geöffnet und geschlossen. So ein "dynamischer" Datenbankaufbau ist recht verpönt, oder?

Indyk
04.06.2009, 15:59:26
Dein vorschlag kann man auch gut ohne neue Tabellen zu erstellen umsetzen, indem du einfach eine Tabelle hast in der du alle "aktiven" felder speicherst.

Dort schreibst du dann meinet wegen wie vorgeschlagen beim erstellen eines turmes rein welche felder betroffen sind. Wenn turm ID11 3 Felder betrifft dann hast du halt 3 Einträge in dieser Tabelle.

Wenn du jetzt auf feld 0:1 gehst, prüfst du einfach mit einem select ob dieses feld in der action tabelle vorhanden ist, ich denke nicht das dieser select mehr kostet als zu schauen ob eine tabelle existiert.

Wenn ein Feld von mehreren Türmen betroffen ist, hast du halt mehrere Fremdschlüssel die zu den entsprechenden türmen führen. Es ist halt dein prinzip nur in einer tabelle ( ;

Mantarrochen
04.06.2009, 16:16:37
Ja genau. Mensch, das geht ja fix hier. :D

Das wäre dann eben der Vorschlag, den ich in meiner Antwort mit dem HTML-Code ausführte. Ich habe allerdings folgende Bedenken:
In dieser Tabelle habe ich dann zu jedem Turm ein paar Spalten für die Felder, auf die er wirkt. Wieviele? Sind 5 genug? oder 10? Was ist zum Beispiel für den Fall eines ungewöhnlichen 5x50 Spielfeldes und einem "Superturm", der einmal komplett längs dieses Spielfeldes schießt? Dann brauche ich 49 dieser Spalten. Oder man denke sich nur einen großen "Flächenturm".

Denkt man obigen Einwand weiter, kommt man zu meiner zweiten Überlegung: die angesprochene Tabelle kann also recht groß werden je nach Spielfeld und Anzahl der Türme. Dann müsste bei jedem Schritt die ganze Tabelle durchsucht werden, auch wenn es nicht nötig wäre. Selbst wenn es eine simple Select-Anweisung ist - das Programm muss sich trotzdem durch die gesamte Tabelle wühlen. Ob das wirklich besser ist als eine einfache Existenzabfrage?

Aber vielleicht habe ich auch einfach bloß naive Vorstellungen. Das, was ich hier als "große Tabelle" handle, mag wohl in Wahrheit - was die Rechenzeit/den Rechenaufwand betrifft - PillePalle sein. Ich weiß es nicht. Weißt du es? :D

Indyk
04.06.2009, 16:31:36
Du hast es noch nicht ganz verstanden wie mir scheint.

Du erweiterst die Tabelle nicht nach rechts, du machst pro feld eine neue Zeile!

tbTürme

TID
X
Y
TYP
LVL?


hier speicherst du alle türme die auf den feld sind, sobald einer gebaut wird errechnest du z.b. das Turm mit der TID 11 5 Felder weit scheißen kann.

Dann hast du 5 Einträge in der Tabelle für aktive Felder

tbAFelder

ID
TID
X
Y

also:
0, 11, 0, 1
1, 11, 0, 2
2, 11, 0, 3
3, 11, 0, 4
4, 11, 0, 5

In diesem fall würde der Turm auf 0:0 stehen und 5 Felder nach Osten schießen.

und nach meiner Erfahrung wären diese bei richtigen index eher in die Kategorie pillepalle einzuordnen.

Mantarrochen
04.06.2009, 16:47:35
Ach so meinst du das! Na ich bin aber auch ein Dummerchen, was? :D

Jedes aktive Feld wird also unten angehängt. Egal, ob es schon mal drin ist. Ja natürlich, so kann es gehen. Danke schon mal für deine Ideen, es macht Spaß, darüber zu diskutieren.

Für den Fall, dass ich einen Turm wieder vom Spielfeld entfernen möchte, muss ich mir dann wieder was einfallen lassen, um die richtigen Felder zu identifizieren.

Sag mal, gibt es eigentlich einen Grund, eine allzu dynamische Datenbankstruktur bzw. ein allzu exzessives Öffnen und Schließen von Tabellen zu vermeiden? Ich nehme an, den gibt es?

Indyk
04.06.2009, 17:03:53
Irgendwie (nimmst nicht persönlich) hörst du dich an wie mein 60 Jahre alter Kollege der noch mit Foxpro arbeitet und tabellen öffnet ( ;

du meinst erstellen von Tabellen oder? Es gibt sicherlich gute Gründe, ich kann dir im moment leider keine überzeugenden aufzählen das es mir so in die wiege gelegt wurde. Eine Datenbank ist halt im Grunde ein Abbild der Wirklichkeit und man macht nicht für jede Person die man kennt ne neue Tabelle auf, sondern hat eine Tabelle Personen , im schlimmsten fall erweitert man eine Tabelle mal um ein Feld, vll. das geschlecht, wenn man vorher nicht wusste das es 2 davon gibt.

Wie tief steckst du denn in MySql? Das mit dem Löschen ist eigt. überhaupt kein Problem, da du ja eine Relation über den Fremdschlüssel hast.

Wenn du also den Turm mit der TID 11 löscht, löscht du einfach alle einträge in der tbAFelder die auf diesen Turm verweisen. Wenn TID 12 sich mit TID 12 ein Feld geteilt hat, ist TID 12 danach halt alleine auf diesem Feld. Ich sehe da eigt. kein Problem.

Mantarrochen
04.06.2009, 19:06:22
Nee ja nee, is klar. Jetzt hör ich mich schon an wie 60. Nur weil ich eurer verknöcherten Zeit voraus bin. Boink! ;D

Das Löschen der Türme sah ich deswegen problematisch, weil TurmID für uns beide was unterschiedliches ist. Ich sehe darin eine Beschreibung, was der Turm macht - deshalb nannte ich es auch Turmtyp. So einen Turm könnte man also auch zweimal setzen, könnte also auch zu mehreren Türmen gehörend in der Tabelle auftauchen.

Wenn ich dich richtig verstehe, willst du die Türme eindeutig identifizieren. So wird es dann auch letztendlich gemacht, denk ich mal. :D

PS.: Ach ja, und von wegen "das hab ich so in die Wiege gelegt bekommen..." - und was in der Wiege liegt, ist gut, oder was? :D Wenn eine Datenbank die Wirklichkeit abbildet, dann müsst ich ja wohl eine Tabelle zu jeder Person öffnen - ich jedenfalls spendiere jedem Leut, den ich kenn, eine eigene Seite in meinem Poesiealbum. Mit jeweils lustigen Blümchen drangekritzelt - oder halt B-52 Napalmbomber, je nachdem wer es ist. :D

Oh, es gibt zwei Geschlechter? Mensch, ich sollte öfter vor die Tür!

Indyk
05.06.2009, 08:48:37
Deshalb habe ich gefragt wie gut du dich eigt. mit relationalen Datenbankmodellen auskennst, und wie deine sql fähigkeiten sind.

Sonst reden wir schnell an einander vorbei. Natürlich musst du jeden Turm einzeln identifizieren, du musst doch sowieso jeden speichern (wie willst du sonst wissen wer wo aufm spielfeld steht?) deswegen hatte ich in meiner ausführung zuvor auch die Tabelle türme mit aufgeführt (in der der typ gespeichert wurde)
daher dachte ich es wäre klar das ich mit der ID den EINEN turm meine und nicht den Turm typen.

Nein was in der Wiege liegt ist nicht automatisch gut, allerdings wurde ich nicht von Fanatikern der "mache nie eine tabelle zu viel"-Gruppe aufgezogen sondern von meiner Firma, Schule und wenn man es so will von der Schwarmintelligenz dieses Forums und des Internets. Und es waren auch immer gute gründe dabei , die ich mir im Gegensatz zum eigentlich Rat, nicht gemerkt habe.

Ich bin mir sicher das Tante Google oder Onkel Bing dir mehr überzeugende Antworten geben können. Es ist halt das Konzept der Relationalen Datenbanken für das du (dem anschein nach) noch kein gefühl entwickelt hast. Dieses Konzept besteht schon länger als ich lebe, wenn es dir zu alt ist solltest du dich vll. alternativen zuwenden ( :