 |
JLI Spieleprogrammierung
|
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen |
Autor |
Nachricht |
manu Super JLI'ler

Alter: 35 Anmeldedatum: 09.03.2006 Beiträge: 327 Wohnort: allgäu (DE) Medaillen: Keine
|
Verfasst am: 23.07.2006, 14:00 Titel: [DirectDraw]Programm lässt sich lediglich 1 mal minimieren |
|
|
Hi ihr,
Ich bin vor kurzem in die Programmierung mit einer Grafik api(in meinem Fall DirectDraw) und vor einer etwas längeren-kurzen Zeit ins programmieren überhaupt eingestiegen. Dies hier ist sozusagen mein allererstes Projekt in der Art. Und nun hab ich mein erstes Problem, dass ich nicht durch stunden langes googlen und Tutorials durchforsten lösen kann...
Und zwar verfügt mein kleines Programm jetzt schon über die Fähigkeit bei einem Surface/device(wie auch immer) lost zu reagieren, sprich alles zu löschen und wieder herzustellen. Das funktioniert auch alles wunderbar, und dank einem Tutorial auf germangamedev hab ich es sogar verstanden . Doch nun kommt besagtes Problem.
ich habe eine kleine Klasse, zum laden von Bitmaps und um diese zu in den Backbuffer zu blitten, gschrieben. Rufe ich jetzt die Funktion " DDLoadBitmap(lpDD, filename, width, height) " auf um einem std::vector ein weiteres Bild hinzuzufügen, funktioniert das Minimieren des Spiels nur einmal. Das Ganze sieht so aus, dass ich einmal minimieren und dannach wieder zum Programm wechseln kann, wenn ich aber jetzt wieder minimieren will(alt+tab), dann passiert das auch, bloß wird immernoch alles gezeichnet und es ist so als ob sich das Programm nicht minimieren würde. Ich bekomme dann zwar immernoch den Frontbuffer meines programms auf meinen Monitor geklatscht, kann aber theoretisch ganz normal mit Windows arbeiten. Praktisch jedoch nicht, da man ja nichts von Windows sieht...
Ist echt schwer zu erklären...
Jetzt ist meine Frage ob mir da irgendjemand weiter helfen kann. ich poste am besten mal ein bisschen von meinem (peinlichen?) Anfängercode um zu zeigen, wie ich das ganze ungefähr mache.
[.......] = hier würde noch anderer, aber glaub belangloser, code stehen
CBitmap.h // die klasse zum laden von Bitmaps
CPP: | struct BMP
{
LPDIRECTDRAWSURFACE7 Bitmap;
int width;
int height;
};
class CBitmap
{
public:
[.......]
bool AddImage(LPDIRECTDRAW7 lpDD, HWND hWnd, LPCSTR filename, int width, int height);
[..........]
protected:
std::vector<BMP> bitmap;
[ ........]
//Ich habe quasi einen vector vom typ der struktur BMP angelegt um mehrere unterschiedliche Bilder mit verschiedener Breite und Höhe zu laden. Z.B. wenn ich mehrere animieren wollte.
};
|
CBitmap.cpp mit dem problem-funktionsaufruf
CPP: | bool CBitmap::AddImage(LPDIRECTDRAW7 lpDD, HWND hWnd, LPCSTR filename, int width, int height)
{
[.......]
m_size++; // bei jedem aufruf die benötigte Größe des vectors um 1 erhöhen
bitmap.resize(m_size);
bitmap[m_anzImages].Bitmap = NULL;
bitmap[m_anzImages].Bitmap = DDLoadBitmap(lpDD, filename, width, height); // Wenn ich diesen Funktionsaufruf weglasse, funktioniert alles perfekt, sprich ich kann mein programm so oft minimieren, wie ich halt bock habe
[.........]
}
|
ein ausschnitt aus dem gameloop meiner main.cpp
CPP: | if(::active && active)
{
if(iDD.checkLost()) //lost?
{
iDD.ClearScreen(200, 200, 255);
iDD.DrawGDITextEx(0, 0, 0, "Hallo DirectDraw", 300, 140, 20, 10, 80);
iDD.DrawGDITextEx(0, 0, 0, "Text geht schon", 300, 200, 25, 12, -80);
iDD.DrawGDITextEx(0, 0, 0, "Aber sowas von", 300, 300, 20, 10, 80);
bmp->drawThis(iDD.getBack(), 10, 10);
iDD.flipBuffers();
}
else //ja! lost ==> aufräumen und alles wieder herstellen
{
iDD.restore();
Shutdown();
InitStuff();
}
}
|
Hab ich alles Grottenfalsch gemacht? oder warum funktioniert das minimieren nur 1 mal wenn ich die besagte funktion, zum laden von bmp Dateien in ein Surface, aufrufe?
vielen dank für jede Antwort
[Info]
DDLoadBitmap() ist in der , mit dem DirectX SDK mitgelieferten, headerdatei "ddutil.h" und quelldatei "ddutil.cpp"
[/info] |
|
Nach oben |
|
 |
DirectXer Dark JLI'ler

Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 23.07.2006, 23:05 Titel: |
|
|
hi,
könntest du bitte noch folgende Codeausschnitte posten? Ich denke, dass man den Fehler dadurch besser aufspüren könnte:
1. bmp->drawThis() - ist bmp eine Instanz von CBitmap? Poste bitte die Funktione drawThis()
2. CBitmap::CBitmap() - also den Konstrukor
3. den Teil deiner CBitmap::AddImage() vor m_size++
4. schreibe bitte kurz auf, welche Sachen die Shutdown()-Methode und die InitStuff()-Methode aufrufen. Wird die Instans bmp dort auch zerstört und neu angelegt? Ich glaube nicht, wenn doch poste bitte auch den Destruktor von CBitmap (wenn bmp wie gesagt eine Instanz von CBitmap ist
Ich weiß, das ist viel, aber genau so schwer wie es für dich ist, das Problem zu beschreiben, so schwer ist es auch für uns, sich ein Bild davon zu machen. Danke
Gruß DXer |
|
Nach oben |
|
 |
manu Super JLI'ler

Alter: 35 Anmeldedatum: 09.03.2006 Beiträge: 327 Wohnort: allgäu (DE) Medaillen: Keine
|
Verfasst am: 23.07.2006, 23:14 Titel: |
|
|
Ja. bmp ist eine instanz von CBitmap
CBitmap::drawThis()
CPP: | bool CBitmap::drawThis(LPDIRECTDRAWSURFACE7 lpBack, int x, int y)
{
if(m_ok)//mindestens ein Bild wurde geladen
{
if(bitmap[m_frame].Bitmap != NULL)
{
SetRect(& m_rectBitmap, x, y, x + bitmap[m_frame].width, y + bitmap[m_frame].height);
lpBack->Blt(&m_rectBitmap, bitmap[m_frame].Bitmap, NULL, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
}
else
{
return false;
}
m_aniTimer++; // wenn alles geht, mach ichs mit zeit
if(m_aniTimer >= 160)
{
m_aniTimer = 0;
m_frame++;
}
if(m_frame > m_anzImages-1)
{
m_frame = 0;
}
}
else
{
return false;
}
return true;
} |
konstruktor und gleich noch der destruktor von CBitmap:
CPP: | CBitmap::CBitmap()
{
m_low = 0;
m_heigh = 0;
m_size = 0;
m_anzImages = 0;
m_aniTimer = 0;
m_frame = 0;
m_ok = false;
bitmap.resize(m_size);
}
CBitmap::~CBitmap()
{
//delete all
for(int i = 0; i < m_size; i++)
{
if(bitmap[i].Bitmap != NULL)
{
bitmap[i].Bitmap->Release();
bitmap[i].Bitmap = NULL;
}
}
bitmap.resize(0);
}
|
die komplette AddImage:
CPP: | bool CBitmap::AddImage(LPDIRECTDRAW7 lpDD, HWND hWnd, LPCSTR filename, int width, int height)
{
m_size++;
bitmap.resize(m_size);
bitmap[m_anzImages].Bitmap = NULL;
bitmap[m_anzImages].Bitmap = DDLoadBitmap(lpDD, filename, width, height);
bitmap[m_anzImages].width = width;
bitmap[m_anzImages].height = height;
if(bitmap[m_anzImages].Bitmap == NULL)
{//Fehler
MessageBox(hWnd, "Fehler beim laden der Bitmap Datei!", "CBitmap ERROR", MB_OK | MB_ICONEXCLAMATION);
return false;
}
else
{
AddColorKey(bitmap[m_anzImages].Bitmap);
m_anzImages++;
m_ok = true;
}
return true;
}
|
und die shutdown + initStuff.
CPP: | int InitStuff()
{
bmp = new CBitmap;
bmp->AddImage(iDD.getLPDD(), hWnd, "test.bmp", 100, 100);
bmp->AddImage(iDD.getLPDD(), hWnd, "test2.bmp", 100, 100);
return 1;
}
int Shutdown()
{
delete bmp;
bmp = NULL;
return 1;
}
|
bmp ist global.
Aber wie gesagt. Ansonsten läuft alles wunderprächtig... bloß halt das dumme mit dem minimieren... |
|
Nach oben |
|
 |
DirectXer Dark JLI'ler

Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 23.07.2006, 23:42 Titel: |
|
|
hast du bei if(::active && active) noch irgendwelche else-Zweige oder anderer Code der ausgeführt wird, wenn minimiert wird? Poste den bitte auch noch(sry, ich will net, dass du hier dein ganzen Projekt postest, aber was sein muss muss sein^^) Bis jetzt vermute ich, dass das so abläuft: wenn active, also net minimiert, wird geprüft, ob etwas verloren wurde. wenn nein, ganz normal rendern ( if(iDD.checkLost()) ). Wenn ja, springt er wahrscheinlich nicht in die if(::active && active). Wenn das Programm nach dem minimieren wieder aktiviert wird, springt er hierrein, oder?: CPP: | iDD.restore();
Shutdown();
InitStuff(); | oder springt er darrein, wenn gerade minimiert wird? Ich nehme an, dass er trotzdem weiterzeichnet, also trotzdem in die if(iDD.checkLost()) springt, obwohl das Programm minimiert ist. Ansonsten: Kann es sein, dass du nach dem Minimieren keinen Clear-Aufruf mehr ausführst?
Gruß DXer |
|
Nach oben |
|
 |
manu Super JLI'ler

Alter: 35 Anmeldedatum: 09.03.2006 Beiträge: 327 Wohnort: allgäu (DE) Medaillen: Keine
|
Verfasst am: 23.07.2006, 23:49 Titel: |
|
|
Also wenn das Programm minimiert ist, wird kein Code Ausgeführt. es wird lediglich geprüft ob Nachrichten vorhanden sind.
CPP: | while(running) //Spielschliefe// läuft solange running true ist
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message == WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
active = !::IsIconic(hWnd);
//Gameloop
if(::active && active)
{
if(iDD.checkLost()) //lost?
{
iDD.ClearScreen(200, 200, 255);
iDD.DrawGDITextEx(0, 0, 0, "Hallo DirectDraw", 300, 140, 20, 10, 80);
iDD.DrawGDITextEx(0, 0, 0, "Text geht schon", 300, 200, 25, 12, -80);
iDD.DrawGDITextEx(0, 0, 0, "Aber sowas von", 300, 300, 20, 10, 80);
bmp->drawThis(iDD.getBack(), 10, 10); iDD.flipBuffers();
}
else //ja! lost ==> aufräumen und alles wieder herstellen
{
iDD.restore();
Shutdown();
InitStuff();
}
}
} |
der Zweig mit dem
CPP: | iDD.restore();
Shutdown();
InitStuff(); |
wird dann ausgeführt, wenn wieder zum Programm gewechselt ist, sprich, wenn verloren wurde...
Aber dasran darf es doch eigentlich nicht liegen, denn wenn ich die Funktion zum Laden der Bitmap Datei weglasse funktioniert ja alles. Mein Front und Backbuffer wird nach jedem minimieren wieder korrekt geladen etc... Also an der technik mit dem lost sollte eigentlich alles passen, vorallem, da ich se mehr oder weniger aus Patricks Tutorial habe  |
|
Nach oben |
|
 |
DirectXer Dark JLI'ler

Anmeldedatum: 05.02.2005 Beiträge: 1201 Wohnort: Köln Medaillen: Keine
|
Verfasst am: 24.07.2006, 00:03 Titel: |
|
|
Also, wenn minimiert wird, wird nur das Bild in der Bitmap weitergezeichnet? Der Rest wird minimiert? Dann liegt das dadran, dass du den Inhalt des Buffers vor dem Minimieren nochmal löschen musst, z.B. mit Clear(). |
|
Nach oben |
|
 |
manu Super JLI'ler

Alter: 35 Anmeldedatum: 09.03.2006 Beiträge: 327 Wohnort: allgäu (DE) Medaillen: Keine
|
Verfasst am: 24.07.2006, 00:11 Titel: |
|
|
DirectXer hat Folgendes geschrieben: | Also, wenn minimiert wird, wird nur das Bild in der Bitmap weitergezeichnet? Der Rest wird minimiert? Dann liegt das dadran, dass du den Inhalt des Buffers vor dem Minimieren nochmal löschen musst, z.B. mit Clear(). |
Hm. verstehe ich nicht ganz. Also wenn minimiert wird, wird eigentlich garnichts gezeichnet. Auch nicht das Bitmap. Hm einmal minimieren funktioniert ja auch noch. Ist ja erst ab dem zweiten mal.. und ich bin echt ratlos....
Zum Buffer löschen. Ich würde halt den Buffer mit einer Farbe füllen. Meinst du das? Wie kann ich das genau vor dem Minimieren machen. Wie finde ich herraus, dass das Programm gerade minimiert wird?
Irgendwie führt alles auf:
DDLoadBitmap(lpDD, filename, width, height);
zurück. Kommentiere ich diese Funktion aus, läuft alles.
Ahja. ich hab es vielleicht vergessen zu erwähnen. Auch wenn ich das Bitmap nichtmal zeichne, sondern nur lade, tritt der fehler schon auf. Ein programm, das sich nicht 2 mal minimieren lässt ist auch irgendwie uncool. |
|
Nach oben |
|
 |
manu Super JLI'ler

Alter: 35 Anmeldedatum: 09.03.2006 Beiträge: 327 Wohnort: allgäu (DE) Medaillen: Keine
|
Verfasst am: 24.07.2006, 00:48 Titel: |
|
|
OK. Das Problem ist gelöst.
Ich hab soeben gedacht, dass ich das Problem einfach ignoriere und mal ein bisschen weitermache. Dann ist mir aufgefallen, dass Surfaces, die teilweise aus dem Bild hinausgehen sofort verschwinden...
Hab dann ein bisschen gesucht und erfahren, dass ich einen Clipper aktivieren muss (oder so ähnlich) um das zu vermeiden. Ich habe dann gerade auch ein tutorial gefunden, das mir gezeigt hat wie es geht und seit dem ich nen Clipper aktiv habe, ist das problem verschwunden...
Ist mir zwar etwas zu hoch, aber wenigstens funktioniert jetzt alles.
Danke trotzdem für die unerschöpfliche Hilfe DirectXer
Hier gibts echt nur nette Leute....
gruß&gute nacht,
manu |
|
Nach oben |
|
 |
GreveN JLI Master

Alter: 38 Anmeldedatum: 08.01.2004 Beiträge: 901 Wohnort: Sachsen - Dresden Medaillen: Keine
|
Verfasst am: 25.07.2006, 08:47 Titel: |
|
|
manu hat Folgendes geschrieben: | Ich habe dann gerade auch ein tutorial gefunden, das mir gezeigt hat wie es geht und seit dem ich nen Clipper aktiv habe, ist das problem verschwunden...
Ist mir zwar etwas zu hoch, aber wenigstens funktioniert jetzt alles. |
Die Sache mit dem Clipper ist eigentlich recht simpel, der macht nix weiter als die Teile einer Surface wegzuschnippeln, die über den Bildschirm bzw. einen Zeichenbereich hinausragen. DD besitzt im übrigen die blöde Eigenschaft im Fenstermodus auch das Zeichnen außerhalb des Fensters zu erlauben, auch da hilft ein Clipper. Theoretisch kann man einen Clipper auch sehr einfach per Hand implementieren, wenn das deinem Verständnis hilft. Der DD-Clipper muss wohl mal hardwarebeschleunigt gewesen sein, ich glaube aber, das spielt heute eh nicht mehr die Rolle bzw. wird sicher über die Software emuliert. |
|
Nach oben |
|
 |
manu Super JLI'ler

Alter: 35 Anmeldedatum: 09.03.2006 Beiträge: 327 Wohnort: allgäu (DE) Medaillen: Keine
|
Verfasst am: 25.07.2006, 11:49 Titel: |
|
|
GreveN hat Folgendes geschrieben: | manu hat Folgendes geschrieben: | Ich habe dann gerade auch ein tutorial gefunden, das mir gezeigt hat wie es geht und seit dem ich nen Clipper aktiv habe, ist das problem verschwunden...
Ist mir zwar etwas zu hoch, aber wenigstens funktioniert jetzt alles. |
Die Sache mit dem Clipper ist eigentlich recht simpel, der macht nix weiter als die Teile einer Surface wegzuschnippeln, die über den Bildschirm bzw. einen Zeichenbereich hinausragen. DD besitzt im übrigen die blöde Eigenschaft im Fenstermodus auch das Zeichnen außerhalb des Fensters zu erlauben, auch da hilft ein Clipper. Theoretisch kann man einen Clipper auch sehr einfach per Hand implementieren, wenn das deinem Verständnis hilft. Der DD-Clipper muss wohl mal hardwarebeschleunigt gewesen sein, ich glaube aber, das spielt heute eh nicht mehr die Rolle bzw. wird sicher über die Software emuliert. |
Jo danke, hab mich jetzt nochmal im Web informiert und so langsam verstehe ich das schon. Ob ich einen Clipper per Hand implementieren könnte, bezweilfe ich, da ich kein Plan hätte wie ich die Surfaces, welche das "Backbuffer Rechteck" teilweise verlassen, zurechtschnippeln sollte.  |
|
Nach oben |
|
 |
GreveN JLI Master

Alter: 38 Anmeldedatum: 08.01.2004 Beiträge: 901 Wohnort: Sachsen - Dresden Medaillen: Keine
|
Verfasst am: 25.07.2006, 11:57 Titel: |
|
|
Naja, einfach beim Blitten das Source-Rect entsprechend anpassen, wäre z.B. eine Möglichkeit. ;) |
|
Nach oben |
|
 |
manu Super JLI'ler

Alter: 35 Anmeldedatum: 09.03.2006 Beiträge: 327 Wohnort: allgäu (DE) Medaillen: Keine
|
Verfasst am: 25.07.2006, 12:00 Titel: |
|
|
GreveN hat Folgendes geschrieben: | Naja, einfach beim Blitten das Source-Rect entsprechend anpassen, wäre z.B. eine Möglichkeit.  |
Ach stimmt. Ich habe immer gemeint, dass das Surface dann gezerrt wird, aber das passiert glaub nur beim verändern des destination rects...
Naja, jetzt gucke ich, dass ich meinem Progrämmchen noch DirectInput - ein gutes Tutorial hab ich schon gefunden - hinzufüge (dann hätte ich alles, was ich für ein kleines Spiel bräuchte) und dann versuche ich mich vielleicht noch mit nem eigenen Clipper.  |
|
Nach oben |
|
 |
|
|
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
|
Powered by phpBB © 2001, 2005 phpBB Group Deutsche Übersetzung von phpBB.de
|