Bild kann nicht geladen werden?
Übersicht BlitzBasic Beginners-Corner
SnowdragonBetreff: Bild kann nicht geladen werden? |
Sa, Aug 23, 2014 21:39 Antworten mit Zitat |
|
---|---|---|
Hallo,
vorab will ich mich für die sperrlichen Informationen entschuldigen. Mein Code ist mitlerweile recht umfangreich (es geht um ein Kartenspiel) und an jeder möglichen Stelle werden der Hintergrund, alle Karten usw. geladen (wenn ich z.B. in ein anderes "Unterprogramm springe, so müssen ja die Bilder erneut geladen werden). An sich funktioniert alles, doch wenn ich länger Spiele taucht ab und an an verschiedenen Stellen eine Fehlermeldung auf - das Bild kann nicht geladen werden. Liegt es daran, dass ich nicht mit FreeImage arbeite und der Speicher irgendwann volläuft? |
||
DAK |
Sa, Aug 23, 2014 21:56 Antworten mit Zitat |
|
---|---|---|
Ok, als Erstes: du solltest Bilder nicht unnötig neu laden. Wenn du in ein "Unterprogramm springst" (ich nehme an, du redest von Funktionen?), dann sollst du Bilder auch nicht neuladen, sondern Dims oder globale Variablen für die Bilder verwenden, da sie eben global, also von überal zugreifbar sind.
Wenn du den Speicher dauerhaft vollmüllst und nie leerst, dann ist es ja wohl keine Hexerei, dass da bald nix mehr rein geht, oder? Blitz speichert Bilder natürlich unkomprimiert im RAM. Das heißt, jedes Pixel verbraucht 3 Bytes. Ein 500x500-Pixel-Bild kommt also auf 750 KB. Wenn du so ein Bild jedes Frame neu lädst, dann schaft dein Programm gerade mal runde 100 Sekunden, bis es bei 60 FPS die 4-GB-Grenze knackt, die ein 32-Bit-Programm zur Verfügung hat. Also: 1) FreeImage ist nicht etwas, mit dem man optional arbeiten kann oder nicht, sondern absolute Pflicht. Alles, was nicht unbedingt bis zum Ende des Programms benötigt wird, muss geFreed werden! 2) Bilder oder andere Ressourcen in einer Schleife laden ist ganz ganz böse! Macht dein Programm ewig lahm und bringt dir den Speichertod. 3) Um Variablen des Hauptprogramms in Funktionen nützen zu können, verwende globale Variablen oder Dims. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
XeresModerator |
Sa, Aug 23, 2014 23:44 Antworten mit Zitat |
|
---|---|---|
Man braucht FreeImage nur dann, wenn man aus irgendeinem Grund Bilder erzeugt/lädt und dann nicht weiter benutzt. Üblicherweise lädt man aber alle Ressourcen für's Spiel und ändert die dann nicht mehr - der Speicher wird dann beim beenden automatisch frei gegeben.
Variablen enthalten das handle zu einem Bild, nicht das Bild selbst. D.h. du kannst das selbe Bild in mehreren Variablen haben. Wenn du aber die einzige Variable überschreibst, kannst du nicht mehr auf das Bild zugreifen und es auch nicht mehr durch FreeImage löschen. Wenn du noch Fragen hast, poste die passende Abschnitte aus dem Code. Dann kann man dir sagen, ob und wie sinnvoll die sind. |
||
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 THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
Snowdragon |
So, Aug 24, 2014 16:21 Antworten mit Zitat |
|
---|---|---|
Okay danke euch beiden. Ich verwende dann lieber mal Arrays (hab nicht daran gedacht ... hehe ) und teste dann wieder alles ausführlich.
Und das mit Ressourcen in einer Schleife laden ist mir auch schon aufgefallen und habe es deshalb immer unterbunden. Muss also wirklich damit zusammenhängen, dass ich den Speicher komplett vollgemült habe. |
||
Sirrus |
Mo, Aug 25, 2014 11:17 Antworten mit Zitat |
|
---|---|---|
Es ist auch sinnvoll, nicht alle Karten einzeln als Bilder abzuspeichern, sondern die Karten alle zusammen auf einem Bild unterzubringen. Von dort aus kannst du die dann mit DrawImageRect auf die jeweils angezeigten Karten kopieren. Das würde dir dann auch ermöglichen mit relativ wenig Aufwand verschiedene Kartensätze für dein Programm bereit zu stellen.
z.B. Code: [AUSKLAPPEN] Global Kartensatz ;Imagehandel des Kartensatz
Function LadeKartensatz(Dateiname$) ;Falls ein Kartensatz bereits geladen ist If Kartensatz<>0 Then Freeimage Kartensatz ;neuen Kartensatz laden Kartensatz=LoadImage(Dateiname) ;True zurückgeben wenn erfolgreich geladen Return (Kartensatz<>0) End Function |
||
DAK |
Mo, Aug 25, 2014 11:44 Antworten mit Zitat |
|
---|---|---|
Da die Karten wohl alle gleich groß sind, könntest du auch AnimImage verwenden, da du dort nur beim Laden die Größen der einzelnen Karten angeben musst, und dann bei DrawAnimImage nur noch die Nummer der Karte angeben musst. | ||
Gewinner der 6. und der 68. BlitzCodeCompo |
funkmaster5000 |
Di, Aug 26, 2014 17:58 Antworten mit Zitat |
|
---|---|---|
Ich definiere meine Bilder immer als Global und kann sie so in den Functions benutzen. Generell besteht deine Hauptschleife ja aus mehreren Funktionsaufrufen. Ich lasse meine Bilder deswegen in einer Funktion darstellen, genauso wie die Eingaben des Spielers.
Also z. B. Code: [AUSKLAPPEN] Global card% = LoadImage("gfx\image.bmp")
While Not KeyHit(1) Cls DrawCards() PlayerInput() Flip Wend EndGraphics End Function DrawCards() DrawImage card,0,0 End Function Function PlayerInput() If KeyDown(200) Then .... End If End Function |
||
TimBo |
Fr, Aug 29, 2014 14:07 Antworten mit Zitat |
|
---|---|---|
du könntest dir auch eine Art Garbage Collector bauen, indem du trackst, zu welchem Zeitpunkt die Grafik das letzte mal gezeichnet worden ist. Wenn ein gewisser Zeitpunkt überschritten ist, dann wird die Grafik aus dem Speicher automatisch gelöscht.
Beispielsweise würde sich da eine Liste anbieten, bei der du jeden Frame 10 Einträge überprüfst und wenn ein Bild gezeichnet worden ist in einem Zeitintervall, dann schiebste das Element wieder ganz ans Ende. Natürlich musst du beim Malen prüfen, ob das Bild noch geladen ist. Hier würde sich ein HashSet anbieten. Das müsstest du dir aber auch selbst basteln. Oder du nimmst dafür einfach global und setzt es auf true oder false, jenachdem ob das Bild noch geladen ist oder auch nicht. Idee : DrawImage ( getImage ("NameDesBildes") , x , y) getImage schaut in dem Hashset (oder bei der global nach), ob das Bild geladen ist deinen Collector lässt du einfach durchlaufen. Ich weiß nicht, wie komplex dein Projekt und deine Motivation bzw. deine Kenntnisse sind. Den Aufwand würde ich nur machen, wenn ich mir sicher wäre, dass er unumgänglich ist. Grüße TimBo |
||
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31 hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht. |
DAK |
Fr, Aug 29, 2014 14:30 Antworten mit Zitat |
|
---|---|---|
@Timbo: Das ist dann aber schon wirklich was Höheres und macht in dem Fall wohl keinen Sinn. Das braucht man erst, wenn man wirklich annähernd 4 GB an Bildern hat. Hier wird es wohl reichen, wenn nur die Bilder alle je nur ein Mal geladen werden. | ||
Gewinner der 6. und der 68. BlitzCodeCompo |
TimBo |
Fr, Aug 29, 2014 14:31 Antworten mit Zitat |
|
---|---|---|
dem möchte ich nicht widersprechen | ||
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31 hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht. |
Übersicht BlitzBasic Beginners-Corner
Powered by phpBB © 2001 - 2006, phpBB Group