Zusammenhängende Welt | Arbeitsspeicherverbrauch + MySQL

Übersicht BlitzBasic Allgemein

Neue Antwort erstellen

 

TestServer

Betreff: Zusammenhängende Welt | Arbeitsspeicherverbrauch + MySQL

BeitragFr, Jun 24, 2011 21:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

nach längerer Abwesenheit vom Blitz-Programmieren (vermehrt C++ und Java) wollte ich mal wieder möglichst unkompliziert ein Spiel programmieren. Da bietet sich ja Blitz geradezu an. Also frisch ans Werk und das Projekt mit neuen Kenntnissen begonnen.

D.h. meine Welt soll in eine MySQL-Datenbank (mit BlitzSQL) gespeichert werden. Das funkioniert auch tadellos. Jedoch wird, wenn ich beim Ausführen des Programms den Taskmanager betrachte, der verwendete Arbeitsspeicher von Durchlauf zu Durchlauf grösser. Woran liegt das in meinem Beispiel?

Hier mal mein bisheriger Code:
BlitzBasic: [AUSKLAPPEN]
;; Map-Editor mit MySQL


timer = CreateTimer(60);


Graphics 1024, 768, 0, 2
SetBuffer BackBuffer();


Include "connection.bb"


world$ = "world01";


act_world_query = SQLQuery(stream, "SELECT * FROM tbl_world, tbl_textur WHERE FK_textur=PK_textur AND world_name='"+world+"';");


act_world_row = SQLFetchRow(act_world_query);

textur_path$ = ReadSQLField( act_world_row , "textur_path");
world_id = ReadSQLField( act_world_row , "PK_world");


textur_img = LoadImage(textur_path);


s_x = 0;
s_y = 0;


query_entities = SQLQuery(stream, "SELECT * FROM tbl_entity;");

anz_elements% = SQLRowCount(query_entities);

Dim entity_image(anz_elements);

For i = 1 To anz_elements

row = SQLFetchRow(query_entities);

Print ReadSQLField$( row , "entity_path");

PK = ReadSQLField( row , "PK_entity");

Print "PK: "+PK

entity_image(PK) = LoadImage(ReadSQLField$( row , "entity_path"));

MaskImage entity_image(PK), ReadSQLField( row , "entity_mask_r"), ReadSQLField( row , "entity_mask_g"), ReadSQLField( row , "entity_mask_b")

FreeSQLRow(row)

Next

FreeSQLQuery(query_entities)

; Einstellungen für Editor
Const scroll_spead = 5;


Repeat


Cls

TileBlock textur_img, s_x, s_y;

Text 10, 10, "Test";
Text 10, 30, s_x;
Text 10, 50, s_y;


; Elemente darstellen
query_entities = SQLQuery(stream, "SELECT * FROM tbl_content WHERE FK_world="+world_id);

anz_elements% = SQLRowCount(query_entities);

For i = 1 To anz_elements

row = SQLFetchRow(query_entities);

x = ReadSQLField( row , "content_x")
y = ReadSQLField( row , "content_y")

PK_entity = ReadSQLField( row , "FK_entity");

FreeSQLRow(row)

DrawImage entity_image(PK_entity), x+s_x, y+s_y

Next

FreeSQLQuery(query_entities)

; Steuerung
If(KeyDown(203))
s_x = s_x + scroll_spead;
EndIf

If(KeyDown(205))
s_x = s_x - scroll_spead;
EndIf

If(KeyDown(200))
s_y = s_y + scroll_spead;
EndIf

If(KeyDown(208))
s_y = s_y - scroll_spead;
EndIf



WaitTimer(timer);

Flip 0

Until KeyHit(1)


End

Was habe ich übersehen?

Vielen Dank für die Antworten.


Edit: Es gibt ja auch Code-Boxen mit Syntax-Highlighting. Praktisch Smile
  • Zuletzt bearbeitet von TestServer am So, Jun 26, 2011 18:30, insgesamt 2-mal bearbeitet

Eingeproggt

BeitragFr, Jun 24, 2011 22:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, pro Sekunde 60 SQL-Queries sind schon heftig...
und dann auch noch immer dieselbe... "world_id" ändert sich soweit ich sehen kann in deiner Hauptschleife ja nicht?
Auch wenn du danach BlitzSQL wieder den Free-Befehl mitteilst so vermute ich da noch einen grundlegenden Fehler in deiner Herangehensweise. Wie gesagt, 60 SQL-Queries in der sek. sind meines Erachtens nach nicht im Sinne des Erfinders.

mfG, Christoph.
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9

ToeB

BeitragFr, Jun 24, 2011 22:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Also, ich finde eine Live Übertragung über MySQL ziemlich unnötig. In meinen Augen ist eine MySQL Datenbank in Verbindung mit Blitzbasic nur dazu zu gebrauchen, um Server-Listen zu Hosten, Update Versionen zu speichern, Online Spieler Daten zu Uploaden etc., aber nicht um darüber ein Online-Spiel oder ähliches Laufen zu lassen. Nimm dafür lieber direkt TCP oder besser noch UDP (Oder eine Mischung aus beidem). Dafür müsstest du dir allerdings einen eigenen Server schreiben, der die Spieler verwaltet, sollte aber nicht allzu schwierig sein..


Aber MySQL - Lass es sein Wink

mfg ToeB
Religiöse Kriege sind Streitigkeiten erwachsener Männer darum, wer den besten imaginären Freund hat.
Race-Project - Das Rennspiel der etwas anderen Art
SimpleUDP3.0 - Neuste Version der Netzwerk-Bibliothek
Vielen Dank an dieser Stelle nochmal an Pummelie, welcher mir einen Teil seines VServers für das Betreiben meines Masterservers zur verfügung stellt!
 

TestServer

BeitragSa, Jun 25, 2011 8:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Vielen Dank für eure Antworten.

Ich habe mir jetzt einige Gedanken gemacht über die Mapspeicherung. MySQL bietet sich an, da die Daten zentral gespeichert werden und ich mittels simplen Abfragen Werte erhalte, sortiere, ändere, lösche.

Wie wäre es, wenn ich eine Abfrage am Anfangs mache, sämtlichen Content der Welt in Types speichere und dann in jedem Durchlauf der Repeat-Schleife durchgehe. Das erscheint mir aber nicht sinnvoll, da:

Zitat:
und dann auch noch immer dieselbe... "world_id" ändert sich soweit ich sehen kann in deiner Hauptschleife ja nicht?


Später wollte ich hier dann noch, den Befehl erweitern, dass immer nur der Content zurück gegeben wird, welcher aktuell im Bild ist. Also so in Richtung
Code: [AUSKLAPPEN]
"SELECT * FROM tbl_content WHERE FK_world="+world_id+" AND content_x>"+s_x+" AND content_y>"+s_y+" AND content_x<"+(s_x+1024)+" AND content_y<"+(s_y+768)

damit ich immer nur mit dem Content arbeite, welcher auch tatsächlich auf der Welt zu sehen ist.

Oder sollte ich komplett auf MySQL verzichten und die Map anders abspeichern? Aber wie? Einfach schwach strukturiert in Textdateien schreiben und danach beim Starten sortieren und in Types/Dims speichern? Da hätte ich aber wieder das selbe Problem, dass ich bei jedem Schleifendurchgang überprüfen muss, ob sich das Objekt im sichtbaren Bereich befindet und somit sämtliche Objekte durchgehen muss...

Ich freue mich auf weitere Anregungen!

Xeres

Moderator

BeitragSa, Jun 25, 2011 10:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Hast du eine Tilemap o.ä., benutzte ein Dim Array, für "freie" Objekte Types. Oder mische beides - ist auch möglich. Wie du die Kartendaten speicherst sollte relativ egal sein, wenn sie zur Laufzeit im Speicher sind. Ich kann mir jedenfalls nicht vorstellen, das das Nachschlagen in der Datenbank einen Geschwindigkeitsvorteil bringt.
Wenn du nicht tausende Objekte hast, sollte die Abfrage, was im sichtbaren Bereich liegt, flott genug gehen. Wenn du mehrere tausend Objekte hast, musst du dir prinzipiell Gedanken über Ladezonen / Unterteilungen machen.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Starwar

BeitragSa, Jun 25, 2011 10:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,
Ich halte MySQL nicht für eine gute Idee, weil du dem Nutzer damit einen Hintergrundprozess zumutest, den die meisten nicht verstehen werden. Außerdem könnte es Probleme mit bereits laufenden Datenbanken geben. Ansonsten kann ich mich nur Xeres anschließen. Moderne Spiele lassen "Ladethreads" im hintergrund laufen um Daten zu laden während der Spieler normal weiterspielt. BEi BB wirst du auf die klassischen Ladezonen zurückgreifen müssen. Zum Speichern eignet sich wenn du relativ starr vorgehst eine Binärdatei (hier kann man sich natürlich Systeme ausdenken "objektorientiert" zu speichern) und wenn du sehr dynamisch sein willst (allerdings mit mehr Speicherverbrauch auf der Platte und längeren Ladezeiten) eine XML-Datei, die jedoch einfacher zu manipulieren ist.
MFG
 

PhillipK

BeitragSa, Jun 25, 2011 10:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Um Xeres gedanken der Ladezonen zu erweitern:

Du könntest deine Landschaft in Bereiche unterteilen, ich nenne sie mal Sektoren.

Ein sektor soltle so etwa 1/2 bildschirm entsprechen. Nun kannst du anhand des Bildschirms die Sektoren innerhalb und drumrum "Laden" (Type oder ähnliches) und anzeigen.
Diese Sektoren enthalten alles was auf der map passiert, was ausserhalb ist muss nicht berechnet werden bzw zumindest nicht angezeigt.
Das gibt auch im späteren aufbau des Spiels einen enormen geschwindigkeitsvorteil, allerdings rate ich persönlich dazu, soetwas möglichst früh zu Implementieren. Später Hunderte system umstellen wäre weniger toll Smile
 

TestServer

BeitragSa, Jun 25, 2011 10:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für die Antworten.

Ich habe mich nun entschieden auf MySQL zu verzichten und eure Vorschläge umzusetzen. Ich werde mir also in nächster Zeit wohl einen Speichermethode (ich tendiere zu Binärdateien) überlegen und mir Gedanken über die Ladezonen machen (da es wohl doch mehrere tausend Objekte werden, eine zusammenhängende Welt ist ein Designziel von mir).

Vielen Dank für eure Anregungen. Zum Glück werde ich am Anfang auf solche grundlegenden Mechanismen hingewiesen, da es wahrscheinlich in der Mitte des Projekts sehr viel schwieriger werden würde, das gesamte Konzept über den Haufen zu werfen.


Gruss
TestServer
 

PhillipK

BeitragSa, Jun 25, 2011 11:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier helfen alle gerne.

Und falls doch mal kritik aufkommt, ist sie zu 99% Produktiv, oder zu missachten Wink

Falls du noch weitere fragen hast, scheue dich nicht, hier zu schreiben. Ich denke, jeder hier hat seine speziellen Wissensbereiche, so dass schnell eine antwort gefunden wird Smile

Ich selbst habe als "Hauptprojekt" auch ein Netzwerkspiel mit einer bekannten am laufen, für uns war es leider nicht möglich, eine Zusammenhängende Welt zu schaffen.

Wir schreiben das ganze auf Basis des TNet-mods, ich bin für die Netzwerk-architektur zuständig (obwohl ich dor gänzlich unerfahren war *g*) - vielleicht kann ich dir noch den ein oder anderen kniff aufzeigen, wie ich manche sachen gelöst habe.

gruß, Phillipk

(Ps: Mein wissen über eine Ordentliche Netzwerkstruktur ist quasie gen null, ich schaffe es lediglich irgendwie eine brauchbare Communikation zwischen Server und Clients zu schaffen (und die Synchronisation der Daten aufrecht zu erhalten) - aber ich denke, das ist alles nur minder Optimal gelöst)
 

TestServer

BeitragSa, Jun 25, 2011 13:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Bevor ich jetzt mit dem Programmieren beginne, möchte ich euch mein neues System vorstellen und bitte um Kritik/Verbesserungsvorschläge.

Die Spielwelt wird in Sektoren à 500px eingeteilt (oder grösser/kleiner. Was wäre sinnvoll?). Es werden stets nur die Sektoren geladen, welche auf dem Bildschirm zu sehen sind. Vorher geladenen Sektoren werden wieder gelöscht, sobald sie nicht mehr auf dem Bildschirm sind. Oder wäre hier eine Toleranz von z.B. 300px sinnvoll?

Elemente werden diejenigen angezeigt, welche auf dem Bildschirm effektiv zu sehen wären (+ kleine Toleranz um das Aufploppen von Elementen zu verhindern).

Sämtliche Sektoren werden in einzelne Dateien gespeichert. Damit ich weiss, welche Sektoren geladen werden müssen, werden in einer seperaten Datei sämtliche Sektoren mit ihren Positionen abgespeichert. (Vielleicht sollte hier statt alle Sektoren als Inhaltsverzeichnis in eine Datei zu speichern, die Datei benannt werden, wie die Position an der sie beginnt, um keine zusätzlichen Listen zu führen. Also z.B. "500-500.m01" -> Sektor von 500px : 500px der ersten Map. Existiert die Datei, wird geladen. Ansonsten wird nicht geladen.)

Hier mal ein Bild, um das Ganze zu verdeutlichen:
user posted image
Pink: Geladene Sektoren
Grün: Geladene und sichtbarer Bereich
Rote Linie: Bildschirmgrenze
Orangefarbene Linie: alles innerhalb wird angezeigt
Weinrot: Nicht geladene Sektoren

Ist das Ganze so durchführbar? Sinnvoll? Verbesserungen? Her mit den Meinungen.


Falls mein Prinzip für euch unverständlich ist, bin ich gerne bereit es näher zu erklären!


Gruss
TestServer

Xeres

Moderator

BeitragSa, Jun 25, 2011 13:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie schnell bewegt man sich über den Bildschirm / wie viele Objekte erwartest du durchschnittlich pro Abschnitt?
Ich würde die Abschnitte größer machen - du musst nicht zwangsweise so tun, als hättest du kaum RAM.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

TestServer

BeitragSa, Jun 25, 2011 13:38
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja, du hast Recht Smile

Durchschnittlich könnten es wohl mehrere Pixel pro Durchlauf sein. Vllt. höchstens 5. Darüber habe ich mir aber bisher noch keine Gedanken gemacht. Was wäre denn sinnvoll? 1000 * 1000? Oder noch grösser? Ich kann das im Moment nicht abschätzen. Und es ist natürlich auch abhängig davon, wie viele Elemente in einem Sektor sind. Das kann auch unterschiedlich sein.

Wobei ich in meinem alten Projekt auf 5000*5000-Fläche unzählige Objekte (Edit: 200 habe es gerade nachgeprüft) platziert hatte und das Ganze mit 28 MB RAM (inklusive Speicher für Bilder) lief. Von demher wäre wohl, ca. 2000 * 2000 ein guter Kompromiss. (Ich muss ja auch jedes Element in den Sektoren in einer Schleife immer durchlaufen, von demher darf es ja auch nicht zu gross sein).


Gruss

skey-z

BeitragSa, Jun 25, 2011 14:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Frage ist auch, wie ist die Map grundsätzlich aufgebaut, bei einer TileMap werden die Bilder zumeist mit 2^x Kantenlänge (16/32/64 etc) erstellt.

somit würden sich Zonengrößen von 512/1024/2048 etc anbieten die dann noch mal in Tiles unterteilt sind.
im Endeffekt musst du selber entscheiden wie du es untertielst, du kannst ja mit kleineren Zonen anfangen und wenn du am Ende noch luft hast die Zonen vergrößern.
Awards:
Coffee's Monatswettbewerb Feb. 08: 1. Platz
BAC#57: 2. Platz
Twitter
 

PhillipK

BeitragSa, Jun 25, 2011 15:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Klingt so relativ gut.

In unserem projekt haben wir sogar noch kleinere Sektoren, da wir mit minib3d arbeiten und uns Surfaces selbst zusammenbauen. Unsere sektoren sind in Kacheln aufgeteilt, es sind immer etwa 20 sektoren sichtbar.

Da du das ganze aus dateien laden möchtest, schlage ich vor, die sektoren in einem Array anzuordnen bzw durchzunummerieren.

Mein system sieht etwa so aus:

Ein 2d array, SektorAnzahlX * SektorAnzahlY
die dateien kriegen als namen (SektorX shl 16) | SektorY -> ein wert der (SektorX * SektorAnzahlY) + SektorY entspricht.
So unterbinde ich stringmanipulationen und hole noch ein wenig geschwindigkeit raus, eine Liste mit sektoren+dateinamen braucht man ebenfalls nicht, vorrausgesetzt, mein weiß, welche sektoren man laden muss.
 

TestServer

BeitragSo, Jun 26, 2011 14:54
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe jetzt mal eine Version erstellt, so wie ich es mir vorstelle. Mit dem Laden etc. bin ich eigentlich recht zufrieden. Allerdings gibt es von Zeit zu Zeit immer noch kleinere Ruckler. Das könnte mMn aber auch an dem Timer liegen.

Hier der Download-Link (damit die MapFiles direkt dabei sind, erstellt mit BlitzPlus): https://www.blitzforum.de/upload/file.php?id=10781
Die main.bb-Datei ist die Richtige (die save.bb wurde nur zum Erstellen der Weltfiles benötigt).

Ich würde mich über Feedback freuen Smile

Edit: Die Grafiken sind natürlich von Reiner.

Edit2: Ich habe mal eine neue Version hochgeladen, wo man die Übergänge besser sieht. Ausserdem habe ich den CreateTimer auf 120 hinaufgesetzt. Und den Scrollspeed angepasst.
Download: https://www.blitzforum.de/upload/file.php?id=10782
Screenshot:
user posted image

Ich hoffe weiterhin auf Kritik/Verbesserungsvorschläge/etc.

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group