mmofacts.com

Karte mal wieder ...

gepostet vor 18 Jahre, 5 Monate von -Ivanhoe-
Hi,
ich bruache mal eure Hilfe für eine Karte.
Habe mir hier die wenigen Threads drüber durchgelesen, bin aber nciht sooo schlau drauß geworden.
Dann mal zu meinem Prob... ich weiß nicht genau wie ich die Karte ausgeben soll.
Stelle mir das so vor, abfrage was in der nähe bewohnt ist (beispielhaft ne 3x3 Felder Fläche).
Aber da hörts dann eigentlich auf. Wie genau soll ich das auswerten? Habe da schon hin und her überlegt und in einem Thread was von mehrdimensinalen arrays gelesen, weiß aber ehrlich gesagt nicht wie das funktioniert/funktionieren soll
Wäre für ein bisschen Hilfe dankbar.
greetz
gepostet vor 18 Jahre, 5 Monate von kudi
Hi
Also ich mach es so:
Ein Kartenabschnitt ist 32*32 Felder groß und hat die ID's 1-1024. Der zweite Kartenabschnitt dann 1025-2048 und so weiter.
Angenommen du willst jetzt den Umkreis des Felds 500 wissen kannst du in der x-Richtung einfach ID-3 bzw. ID+3. Für die y-Richtung vesetzt du das ganze einfach eines hinauf oder hinunter, also ID-32-3 bzw. ID+32+3.
Dass du überprüfen musst ob das Feld an einer Kante liegt ist dir denke ich klar(Bsp: Feld 1 - 3 --> Fehler)
Das ganze berechnest du einfach mit einem Script und speicherst die ID's die du brauchst in einem Array. Dieses kannst du dann in einen String zusammensetzen und mit der MySQL Funktion IN kannst du jetzt die benötigten Felder auslesen.
Lg Kudi
gepostet vor 18 Jahre, 5 Monate von Drezil
am effizientestern finde ich:
tabelle:
x bigint unsigned not null
y bigint unsigned not null
typ ..
... andere werte ...
x,y primary key
abfrage: select wasauchimmer from tabelle where x between startX and endX && y between startY and endY && blabla order by x,y
=> bekommst erst endX-startX einträge für startY, dann für startY+1, ...
=> bekommst also spalte für spalte..
wenn du order by y,x machst bekomst du ziele für zeile. Das kannst du dann z.B. einfach in ner Tabelle ausgeben etc. pp.
hth
gepostet vor 18 Jahre, 5 Monate von Itchy
Also ich speichere meine Karten (das Gelände) als Bitmap, also 1 Byte pro Feld in einer x-Byte großen Datei (wobei x = Anzahl der Felder. Muß allerdings dazu sagen, daß meine Karten maximal 100x100 Felder klein sind, mit größeren hab ich keine Erfahrung. Bei 100x100 hat man also eine 10k große Datei, da geht der Zugriff wirklich Ratzfatz.
Die Einheiten etc. werden in einer Tabelle gespeichert, wo halt die X/Y Koordinaten hinterlegt sind. So in der Art
ID, X, Y, Typ
gepostet vor 18 Jahre, 5 Monate von Klaus
Original von gollum1990
Hier hast nen Tutorial:
browsergames24.de/modules.php?name=Forums&file=viewtopic&t=2008
Und kommt bitte nicht an mit Verräter, das hab ich schon genug gehört.

Nix verräter, das Script ist einfach nur schlecht. Was sollen die einzelnen Queries in der Schleife? Man macht es einfach so wie Drezil es erläutert hat.
@OP: Wenn du willst kann ich dir auch mein Script zeigen, ich plane sowieso es komplett zu ändern.
Original von Itchy

Also ich speichere meine Karten (das Gelände) als Bitmap, also 1 Byte pro Feld in einer x-Byte großen Datei (wobei x = Anzahl der Felder. Muß allerdings dazu sagen, daß meine Karten maximal 100x100 Felder klein sind, mit größeren hab ich keine Erfahrung. Bei 100x100 hat man also eine 10k große Datei, da geht der Zugriff wirklich Ratzfatz.
Kannst du den Zugriff darauf vielleicht mal zeigen?
gepostet vor 18 Jahre, 5 Monate von -Ivanhoe-
Schonmal danke für die bisherigen antworten.
Nun hab ich endlich nen Ansatz thx
Würde mich trotzdem über weitere Antworten freuen^^
gepostet vor 18 Jahre, 5 Monate von kudi
@Drezil
Ich glaube meine Methode ist schneller weil MySQL die Tabelle nicht mehr durchsuchen muss.
Zwei Betweens auswerten dauert meiner Meinung nach länger als das Script welches die ID's berechnet.
Lg Kudi
gepostet vor 18 Jahre, 5 Monate von Drezil
Original von kudi
@Drezil
Ich glaube meine Methode ist schneller weil MySQL die Tabelle nicht mehr durchsuchen muss.
Zwei Betweens auswerten dauert meiner Meinung nach länger als das Script welches die ID's berechnet.
Lg Kudi

1. 3x darfst du raten, wieso ein PRIMARY KEY auf x,y liegt .. Damit muss MySQL nämlihc GAR NICHT suchen, sondern Adressiert dierekt den Spieicher (sofern du row-format:fixed hast, was bei der Tabelle aber standard sein sollte).
Die Abfrage, wie ich sie beschrieben habe dauert ca. 0.0001 sec (hab keine genauen werte).
2. Jede Mysql-Anfrage verursacht einen OVERHEAD, den man nciht unterschätzen sollte. Bei jeder anfrage hast du ne Verzögerung vpn 0.0xx sec. Das summiert sich. Mag sein, dass meine einzelne Anfrag länger dauert als eine von dir - aber UNTERM STRICH wird dein script immer langsamer laufen. Den Overhead (auch in der DB) den du durch dein zusätzliches Feld erzeugt mal ganz abgesehen.
3. meine Anfrage in Kombi mit mysql_unbuffered_query() statt mysql_query() (bezogen auf PHP) liefert dir die ersten Daten genausoschnell wie deine query. Wenn es nur ums ausgeben geht und man z.B. die Anzahl der Zeilen nicht wissen will, sondern einfach nur nacheinander rausschmeisst, dann ist die unbuffered query besser.
4. Du wagst es eine perfekte Lösung Anzuzweifeln? (Achtung! Sarkasmus!)
Die Idee mit dem Bild ist ne gute alternaive zu einer Datenbank-Lösung. Kommt drauf an, was man speichern will. Irgendwann reichen rgb+alpha-werte nicht mehr aus. Aber wenn man nciht mehr braucht ne gute alternative. Hab mal von einem gelesen, der nen "natur"-system in solche einem Bild umgesetzt hat (planzenanteil: grün, tiere (fleisch): rot, wasser/boden: blau). jeden Tick haben dann Pflanzen Waser verbraucht, Tirere haben Pflanzen verbraucht und tote Tiere haben wieder "Wasser" produziert. Er meinte, dass er nen empfindliches ökologisches Gleichgewicht hatte und sihc z.B. Wüsten (=niedriger pflanzen/wasseranteil) gebildet hatten, woraufhin da nen massensterben einsetzte etc. Er wollte das in sein spiel einbauen, dass der spieler auhc eingreifen kann (abholzen, jagen) und dass sich die Welt auch nach den eingriffen dementsprechend entwickelt.
Hier finde ich z.B. Bilder als Datenspeicher (auch in puncto Visualisierung) sehr gut.

gepostet vor 18 Jahre, 5 Monate von Itchy
Original von Klaus
Kannst du den Zugriff darauf vielleicht mal zeigen?

Kleiner Codeschnippsel, gekürzt ohne Fehlerbehandlung und anderes Zeug:

char * readmap( int x, int y, int size ) {
FILE * map;
char * ret;
int retoffset = 0;
int offset = y * WIDTH + x;
int i;
ret = (char *)malloc( size * size + 1 );
map = fopen( "map.dat", "r" );
for ( i = 0; i < size; i++ ) {
fseek( map, offset, SEEK_SET );
fread( (char *)(ret + retoffset), size, 1, map );
offset += size;
retoffset += size;
}
fclose( map );
return ret;
}
Was darin gemacht wird, sollte recht einleuchtend sein. Es wird innerhalb der Datei die richtige Position (offset) über die X/Y Koordinate ermittelt und es werden dann immer Blöcke von Größe 'size' gelesen und das ganze size-mal, wobei jedes mal dann der offset um eine "Zeile" nach unten verschoben wird.
Es sei noch angemerkt, dass die Funktion nur quadratische Ausschnitte zurückliefert.
gepostet vor 18 Jahre, 5 Monate von KEEN
Original von Drezil
1. 3x darfst du raten, wieso ein PRIMARY KEY auf x,y liegt .. Damit muss MySQL nämlihc GAR NICHT suchen, sondern Adressiert dierekt den Spieicher (sofern du row-format:fixed hast, was bei der Tabelle aber standard sein sollte).
Die Abfrage, wie ich sie beschrieben habe dauert ca. 0.0001 sec (hab keine genauen werte).

Wie groß ist die Karte bei der du es getestet hast? Nach deiner Methode komme ich bei einer 512x512 Karte mit einem Ausschnitt von 7x7 nicht unter 10ms, trotz Primary Key auf x,y.
Der Explain Befehl zeigt warum:
SIMPLE karte range PRIMARY PRIMARY 4 NULL 3695 Using where; Using filesort
Kann mir schwer vorstellen, dass du mit der between xy Methode eine volle Index Verwendung hinbekommst. Bei mir wird nur der x Index im x,y Index verwendet.
gepostet vor 18 Jahre, 5 Monate von Drezil
ich teste das acuh mal grad..
vllt.muss ihc mich korrigieren .. mom
ich hab das vor 3 jahren mal verwendet...
Edit: hast recht. hab mich um 2 Nachkommastellen verschrieben sollte 0.01 sec heissen.
Auf jeden fall ist es so veschwindend gering, dass der Overhead,der duch php ausgelöst wird übersteigt den aufwand der Query bei weitem.
Edit2: es gibt doch nen benchmark-befehl, mit dem man ne query X-mal ausführen kann. wie ging der nochmal? ich find das in der dku grad nicht
gepostet vor 18 Jahre, 5 Monate von KEEN
Einen Benchmark Befehl kenne ich nicht, aber PhpMyAdmin zeigt die Zeit recht gut an, ums genau zu ermitteln kann mans ja ein paar mal ausführen. 10ms ist schon eine akteptable Abfrage Zeit, aber wers nochmal um den Faktor 10 schneller mag,
SELECT * FROM karte WHERE id IN ( 133372, 132860, 132348, 131836, 131324, 130812, 130300, 133373, 132861, 132349, 131837, 131325, 130813, 130301, 133374, 132862, 132350, 131838, 131326, 130814, 130302, 133375, 132863, 132351, 131839, 131327, 130815, 130303, 133376, 132864, 132352, 131840, 131328, 130816, 130304, 133377, 132865, 132353, 131841, 131329, 130817, 130305, 133378, 132866, 132354, 131842, 131330, 130818, 130306 )
Dauer: 0.8ms
ist schneller als
SELECT * FROM karte WHERE x >= '-5' && x <= '1' && y <= '2' && y >= '-4'
Dauer: 7.5ms
gepostet vor 18 Jahre, 5 Monate von Klaus
Du bist unser Held!
Werde es auch auf IDs und Bitmaps umstellen.
gepostet vor 18 Jahre, 5 Monate von Drezil
Und wie groß ist der Overhead, der entsteht, wenn man 500+ ID's in php generiert (und damit ins ram ballert)?
Was ist mit dem overhead, der während der überragung zum DB-server erzeugt wird?
was ist, wenn die anfrage jetzt 1000x in 1 sec kommen würde (zu stosszeiten)? wenn die query dann auch nur nen par kb groß ist, bremst das ganz schön aus .. mehr als du durch angabe der keys sparst, wage ich mal zu behaupten ..
Die geschwindigkeit der query ist eine sache. Eine wichtige sogar. Aber nciht DIE wichtigste allein. Es entsteht immer ein Overhead. Diesen so gering wie möglich zu halten ist eine ebenso wichtige sache.
gepostet vor 18 Jahre, 5 Monate von Sarge
Apache/Php leistung ist billig, datenbank dagegen sehr teuer. Wenn du die möglichkeit hast php overhead zu gunsten db entlastung auszugeben, nutze sie.
Warum?
Du kannst ohne Probleme 20 webserver eine Datenbank bedienen lassen, das clustern von Datenbanken ist allerdings um einiges aufwändiger & kostspieliger.
gepostet vor 18 Jahre, 5 Monate von kudi
Sagt Held zu mir (Das ist auf meine Methode mit IN bezogen falls das jemand nicht versteht...)
4. Du wagst es eine perfekte Lösung Anzuzweifeln? (Achtung! Sarkasmus!)

Ja
gepostet vor 18 Jahre, 5 Monate von -Ivanhoe-
Mh ich habe jetzt hin und herprobiert, aber irgendwie schaffe ich es doch nicht
Ich weiß immer nochnicht wie ich dann gezielt einen User irgendwohin ausgebe.
Also übliches Koordsystem:
_12345
1
2__B
3
4_A
5
zB hier jetzt User A und User B. Wie mache ich das. Ich habe grad irgendwie ne Hirnblockade ....
Irgendein Codeschnippsel oä wäre nett.
Edit:
Hiernblockade gelöst, habe es schon selbstgelöst
gepostet vor 18 Jahre, 5 Monate von kudi
Hallo
Ich kann jetzt nur für mich sprechen und will dich auch nicht kränken, niedermachen oder sonst irgendwas.
Bist du dir sicher, dass dein Wissen über PHP und Mysql ausreicht?
Eigentlich sollte jemand mit der Hilfestellung die er in diesem Thread findet und auch über ausreichend Wissen für die Entwicklung eines Browsergames hat, keine Probleme mehr haben.
Ich für meinen Teil helfe zwar gerne, jedoch nur wenn der Hilfsbedürftige sich auch genug Mühe gibt. Bei dir habe ich das Gefühl, dass du nach Codestücken fragst und diese dann zusammenfügst.
Ich kenne das aus meiner Schulklasse(Informatikschule) und weiß, dass der Lernfortschritt dabei gleich 0 ist.
Du ließt die Daten aus der Datenbank in ein Array aus und gibst diese dann per echo aus.
Das lernt man bei ganz einfachen PHP Tutorials so wie hier.
Und bitte noch einmal: Ich will dir nur helfen. Durch Codekopieren lernst du nichts und das ist ja eigentlich nicht Sinn der Sache.
Sollte ich mich mit meiner Vermutung total irren, entschuldige ich mich natürlich bereits dafür.
In diesem Sinne,
lg Kudi
gepostet vor 18 Jahre, 5 Monate von Murmeltier
Hallo Kudi,
ich muss da Ivanhoe mal in Schutz nehmen *g*
Er ist mein Bruder und ich weiß, dass er den Code nicht zusammen fügt.
Ein Anmeldeskript findest du überall, doch er hat das auch selbst geschrieben.
Manchmal fehlt eine, der Gewisse Denkanstoß und wenn man das dann sieht, wie es eigendlich geht denkt man sich "Oh Mensch, warum bin ich da nicht drauf gekommen"
So geht es mir auch manchmal, wenn wir in der Schule mal wieder irgendwas in C schreiben.
Ich für meinen Teil lerne auch recht gut, wenn ich mir Code anschaue und sehe, wie es geht.
Gruß
gepostet vor 18 Jahre, 5 Monate von kudi
ich hab ja oben bereits gesagt, falls das der Fall ist sry.
Wie gesagt ich kenn es leider anders von meinen Mitschülern
gepostet vor 18 Jahre, 5 Monate von -Ivanhoe-
kudi ich denke deine annahme war schon berechtigt.
Einige fragen hier, oder in anderen Foren, nach kompletten Tuts oder Scripten etc, aber wie Murmeltier sagte code ich das selbst, hatte heute nur ne kleine Hirnblockade
Aber egal
gepostet vor 18 Jahre, 5 Monate von Murmeltier
Ich kenne das auch von Mitschülern
Da wollen sie nur mal schnell schauen, was du so hast und plötzlich sind sie fertig und dir kommt der Quellcode so bekannt vor
Zum Topic:
Habe ihm das mal erklärt, mit den Arrays...
gepostet vor 18 Jahre, 5 Monate von kudi
Gut
Also schau dir mal das an tut.php-q.net/mysql-select-php.html
Die Frage ist was du alles mit den Daten machen willst und wie oft ein Update und damit auch ein Auslesen statt finden soll.
Angenommen du gibst eine Karte aus die 32*32 groß ist und willst type ausgeben(könnte zb eine Grafik sein):

$i=1;
$sql = mysql_query("SELECT type FROM blubb WHERE x BETWEEN 1 AND 32 AND y BETWEEN 1 AND 32 ORDER BY y");
while($ausgabe = mysql_fetch_array($sql))
{
echo $ausgabe['type'];
if($i%32==0)
{
echo "
";
}
$i++;
}
Wobei diese Methode meiner Meinung nach nicht grad die schnellste ist, aber das hatten wir schon Hab das eben bei einer Tabelle mit 1 048 576 Einträgen getestet und dieses Script dauert mit PHP auf meinem PC 1,92sek
Hoffe ich konnte dir helfen,
lg Kudi
gepostet vor 18 Jahre, 5 Monate von Kapsonfire
also das was ich habe um mir eine map zu erzeugen
DIE STRUKTUR

CREATE TABLE `city` (
`ID` int(10) NOT NULL auto_increment,
`name` varchar(30) collate latin1_general_ci NOT NULL default '',
`x` char(3) collate latin1_general_ci NOT NULL default '',
`y` char(3) collate latin1_general_ci NOT NULL default '',
`punkte` int(15) NOT NULL default '0',
`notiz` longtext collate latin1_general_ci NOT NULL,
`besitzer` varchar(50) collate latin1_general_ci NOT NULL default '0',
`beschreibung` longtext collate latin1_general_ci NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

ZUM AUSFÜLLEN

$x = 0;
$y = 1;
while($y < 101)
{
$x++;
if($x == 101)
{
$y++;
$x = 1;
}
mysql_query("INSERT INTO `city` VALUES ('', '', '$x', '$y', 0, '', '', '')");
}
mysql_query("DELETE FROM `city` WHERE y > 100");
UND ICH WEISS ICH HÄTT MIR EIN SCHRITT SPAREN KÖNNEN xD aber das ist so absicht. urpsrünglich war das nur als benchmark gedacht mit das 100 fache an einträgen aber war zu faul das nochmal zu machen, da die daei eh nur einmal aufgerufen wird xD
sind zwar noch keine grafiken drinne kann man aber hinzufügen
gepostet vor 18 Jahre, 5 Monate von mifritscher
bgw, sorry, aber *rülps*.
erstens würde ich x und y als *integer speichern.
zweitens ist die Spalte ID samt dem primary key sinnlos, ich würde den primary Key lieber über X und Y legen
drittens ist deine Schleife, bissle, naja, unkonventionell.
ich hätte wohl einfach

for ($x=1;$x<=100;$x++)
{
for ($y=1;$y<=100;$j++)
{
*insert-query*
}
}
gemacht.
viertens wird dein insert Mist bauen, wenn du auch nur ne Kleinigkeit an der Tabelle änderst.
nen "INSERT INTO city SET x=$x,y=$y" ist bissle freundlicher gegenüber Änderungen
fünftens verstehe ich nicht, warum du erst die Zeien erzeugst, dann aber wieder paar löscht.
sechstens ist das so ziemlich die primitivste Möglichkeit ne Map zu speichern
Sorry für die Klugscheißerei, das musste ich aber einfach mal los werden
gepostet vor 18 Jahre, 5 Monate von gollum1990

INSERT INTO city SET x=$x,y=$y

Das wird wohl so nicht funktionieren,

INSERT INTO city(x,y) VALUES ('$x','$y');
so dürfte das Funktionieren
gepostet vor 18 Jahre, 5 Monate von mifritscher
Also, wenn man nicht grad eine pre 3.22-Version hat (selbst woody hat 3.23) geht es
aber mir ist grad eine andere Idee gekommen:
und zwar kann man ja mittels INSERT INTO tbl_name (x,y) VALUES(1,1),(1,2),(1,3),...; gleich mehrere Zeilen auf einmal schreiben. Könnte man mal testen, ob es schneller wird, wenn man gleich 100 (oder alle 10000) auf einmal schreibt und in den Schleifen nur die/das query/ies zusammenbaut...
(sollte auch schon woodies 3.23 schaffen
)
gepostet vor 18 Jahre, 5 Monate von Klaus
wollte ich dir auch noch vorschlagen, am besten noch als Delayed query, dann führt der Server es aus, wenn genug Luft ist.
gepostet vor 18 Jahre, 5 Monate von Kapsonfire
Mitfrischer:
zweitens ist die Spalte ID samt dem primary key sinnlos, ich würde den primary Key lieber über X und Y legen

sagst du aber eine id kann schon ein paar schritte sparen -.-
gepostet vor 18 Jahre, 5 Monate von mifritscher
naja, dann lasse von mir aus ne ID drin, mach dann aber sowohl über ID als auch über x,y nen "unique-like" Schlüssel, das heißt unique oder primary key.
Aber normalerweise sucht man in einer Map eher nach x,y und nicht nach der ID, oder?
Delayed insert ist mir auch durch den Kopf gegangen, allerdings denke ich, dass man solche Sachen eh dann macht, wenn wenig los und man vielleicht sicher gehen will, dass es auch gespeichert wird (nen kill -9 like Absturz lässt das nämlich untergehen). Außerdem wird man wohl basierend auf die eben erstellte map weiterarbeiten, was dann eh warten müsste, bis das delayed query drin ist.
Wenn diese Bedingungen aber nicht erfüllt sind ist ein delayed sinnvoll, das stimmt :-)
Dann wird das halt zum "Karte mal wieder optimieren"-Thread

Auf diese Diskussion antworten