2 Fragen
-
Hi!
Ich habe(wiedermal) ein Problemchen:
Ich habe folgenden Quellcode:#include <windows.h> #include <conio.h> int lo=10,oo=10; unsigned char chr; int LoadBmp2Console(char *szBitmap, int PosX, int PosY, int breadth, int length) { HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,szBitmap, IMAGE_BITMAP,0,0,LR_LOADFROMFILE); if (!hBitmap) return 1; BITMAP bmp; GetObject(hBitmap,sizeof(bmp),&bmp); HWND hwnd = FindWindow("ConsoleWindowClass",NULL); if (!hwnd) return 2; HDC hDC = GetDC(hwnd); if (!hDC) return 3; HDC hBitmapDC = CreateCompatibleDC(hDC); if (!hBitmapDC) return 4; SelectObject(hBitmapDC,hBitmap); StretchBlt(hDC,PosX,PosY,breadth*bmp.bmHeight,length*bmp.bmWidth,hBitmapDC,0,0,bmp.bmHeight,bmp.bmWidth,SRCCOPY); DeleteObject(hBitmap); ReleaseDC(hwnd,hBitmapDC); ReleaseDC(hwnd,hDC); return 0; } void setposition (int l,int o) { int Status = LoadBmp2Console("Bild.bmp",lo+l,oo+o,1,1); lo+=l; oo+=o; } void main () { do { chr=getch(); { chr=getch(); switch(chr) { //links case 75:{ setposition(-3,0); break;} //rechts case 77:{ setposition(+3,0); break;} //unten case 72:{ setposition(0,-3); break;} //oben case 80/*119*/:{ setposition(0,+3); break;} } } }while(true); }
geschriebn. Dabei ist mir aufgefallen, dass, wenn man z.B. die Pfeiltaste
"Pfeil nach oben" mit "W" vertascht, sich das Bild nur noch seltsam stockend
bewegt.
Frage 1: Woran liegt das, und kann man das irgentwie ändern???
Frage 2: Kann man diese dämlichen Schliern, die das Bild hintersichherzieht
ähh,... >abschaffen< oder so???Danke!!!
-
Zu 1.
Was meinst du da genau?Zu 2.
Du musst den Teil, um dem sich das Bild verschiebt wieder übermalen, sonst bleibt das alte Zeugs am Bildschirm stehen. Wenn dein Bild z. b. ganz links oben in der Ecke ist und du das Bild nun um 3 Pixel nach unten verschiebst, dann musst du die Fläche, die ja nun "leer" sein soll auch "leer" machen (schätzungsweise wieder schwarz übermalen).
-
AJ schrieb:
Zu 1.
Was meinst du da genau?Ich meine: Wenn ich die Tastenbelegnung ändere, also z.B.
119 statt 18 im der switch anweisung nehme, rukelt das Bild
auf einmal viel mehr, wenn man die Taste (in diesem Fall W)
drückt. Sonst gleitet es eignetlich recht sanft, wenn es aber
geändert ist springt das bild vielmehr.AJ schrieb:
Zu 2.
Du musst den Teil, um dem sich das Bild verschiebt wieder übermalen, sonst bleibt das alte Zeugs am Bildschirm stehen. Wenn dein Bild z. b. ganz links oben in der Ecke ist und du das Bild nun um 3 Pixel nach unten verschiebst, dann musst du die Fläche, die ja nun "leer" sein soll auch "leer" machen (schätzungsweise wieder schwarz übermalen).Soll ich also ganz einfach rund um das bild herum schwarze bitmaps anordnen,
um das sofort wieder zu übermalen? Oder geht das auch einfacher?
system("cls"); geht ja nur für text. gibts da auch was für bilderMfG
Canon
-
Zu 1.
Bist du sicher, dass du die andere Taste auch richtig abfrägst? Momentan scheinst du das Verschieben ja mit den Pfeiltasten zu machen (also Sondertasten). Wenn du z. B. einen Buchstaben dafür abfrägst, dann musst du das schon mit dem ersten getch() machen. Wenn das alles passt, dann verwundert es mich, dass es bei dem einen ruckelt und beim anderen nicht. Zeig einfach mal den umgeänderten Quellcode.Zu 2.
Also system("CLS") verwendet man schon mal gar nicht. Ist ganz ganz schlechter Stil. Wenn man schon den ganzen Bildschirm löschen möchte dann verwendet man auch entsprechende Funktionen dafür, wie z. B. clrscr() aus der conio.h. Dazu gibt es auch einen Thread in der Konsolen-FAQ.Allerdings ist es etwas übertrieben gleich den ganzen Bildschirm zu löschen, wenn man nur einen kleinen Bereich wieder schwarz haben will. Die einfachste Methode wäre, dass du über den Bereich, der wieder schwarz werden sollte mit einem schwarz gefüllten Rechteck übermalst. Also nicht das ganze Bild übermalen sondern nur den Teil, der überstehen würde. In deinem Fall verschiebst du das Bild ja immer um 3 Pixel. Der Bereich zwischen der alten Position und der neuen müsstest du dann schwarz auffüllen.
Mit Bitmaps könntest du das auch machen, wäre aber wiederum eine etwas umständliche Lösung.
Am besten also eine Funktion suchen, die einen Bereich mit einer bestimmten Farbe ausfüllen kann.
-
zu 1:
Jo stimmt da war wirklich was falsch. so muss das aussehen:do { chr=getch(); switch(chr) { //links case 75:{ setposition(-3,0); break;} //rechts case 77:{ setposition(+3,0); break;} //unten case 72:{ setposition(0,-3); break;} //oben case 119:{ setposition(0,+3); break;} } }while(true);
zu 2: werd ich mal versuchen!
MfG
Canon
-
ich hab diesen quelltext hier gefunden und versucht ihn gleich zu verwenden weil ich auf der suche nach genau so einem quelltext für mein kleines spielchen war.
nun mein problem:
wenn ich mein programm in vc++ ausprobier läuft alles einwandfrei, wenn ich aber die execute-datei ausführe dann seh ich das bild nichtmehr. kann mir jemand helfen das problem zu beheben?
P.S. hab win2000 wenn relevant
-
hat sich erledigt, vergessen die bitmap ins verzeichnis von der exe reinzuschmeisen...
-
hallo nochmal,
ich hab trotzdem nochmal ne frage bezüglich des Quelltextes, so wie ich das sehe läd man hier die bilder jedesmal neu oder? gibts nicht ne möglichkeit das bild einmal zu laden und dann so zu verwenden?
der hintergund:
ich hab vor ca. 1 woche begonnen ein kleines weltraumspielchen zu basteln. das raumschiff fliegt auch schon so wie ich will(is ja nicht immer so
), heute hab ich noch asteroiden eingefügt. ich hab in meiner schleife nen count drin mit dem ich den speed der asteroiden und des raumschiff steuer und den ich mir auch anzeigen lasse. je nachdem wieviel ich das raumschiff bewege, hört das programm bei einem countstand zwischen 45000 und 80000 auf die bilder hochzuladen (glaub ich jedenfalls weil er sie nichtmehr anzeigt).
kann mir jemand helfen?
danke schonmal im vorraus
-
Das Problem kenn ich..
Du hast recht, das Bild wird jedes mal neu geladen und somit ist der Speicher irgendwann 'voll' und es kann nicht mehr bewegt werden, da es dann ja neu geladen werden müsste..
Aber ich hab leider auch keine Ahnung wie man das Problem beheben könnte.
-
naja wenigstens steh ich mit dem problem nicht alleine da. es wäre schön wenn sich uns einer annehmen würde
ich komme ansonsten mit meinem programm einfach nicht weiter bzw. bringt es auch gar nichts weiter zu programmieren wenn ich noch keine antwort habe
-
Die Konsole ist nicht dafür ausgelegt Weltraumshooter zu basteln :), schau dir dazu mal eine Library wie Allegro (Siehe Spiele/Grafik-FAQ an). Mit Hilfe dieser kannst du a) einfacher und b) ohne Probleme Bitmaps in der Konsole anzeigen lassen
MfG SideWinder
-
Naja gut hier mal meine (auf Anfrage quasi) geistigen Ergüsse:
// Bmp2Console.cpp : Defines the entry point for the console application. // #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include <stdio.h> #include <tchar.h> #include <windows.h> #include <conio.h> void LoadBmp(char *szBitmap, HWND aWindow, BITMAP* aBitmap, HBITMAP* aBitmapHandle, HDC* aBitmapDC) { if (::IsWindow(aWindow) == 0) { throw "The specified window handle is invalid."; } // Load image *aBitmapHandle = (HBITMAP)LoadImageA(NULL,szBitmap, IMAGE_BITMAP,0,0,LR_LOADFROMFILE); if (!*aBitmapHandle) { throw "Failed to load image."; } if (::GetObjectA(*aBitmapHandle, sizeof(*aBitmap), aBitmap) == 0) { throw "Failed to GetObject"; } HDC aDestinationDC = ::GetDC(aWindow); if (aDestinationDC == NULL) { throw "DC for window is invalid."; } *aBitmapDC = ::CreateCompatibleDC(aDestinationDC); if (*aBitmapDC == NULL) { throw "Failed to CreateCompatibleDC."; } } void PaintBitmap(HDC aDestDC, BITMAP aBitmap, HBITMAP aBitmapHandle, HDC aBitmapDC, int PosX, int PosY, int aDestWidth, int aDestHeight) { // select the bitmap ::SelectObject(aBitmapDC, aBitmapHandle); // if same size use BitBlt if ((aBitmap.bmWidth == aDestWidth) && (aBitmap.bmHeight == aDestHeight)) { ::BitBlt( aDestDC, PosX, PosY, aDestWidth, aDestHeight, aBitmapDC, 0, 0, SRCCOPY ); } // else stretch/shrink else { ::StretchBlt( aDestDC, PosX, PosY, aDestWidth, aDestHeight, aBitmapDC, 0, 0, aBitmap.bmWidth, aBitmap.bmHeight, SRCCOPY); } } void InvalidateOldRegion(HWND aWindow, int myPosX, int myPosY, int Width, int Height) { RECT myInvalidateRect; myInvalidateRect.left = myPosX; myInvalidateRect.right = myPosX + Width; myInvalidateRect.top = myPosY; myInvalidateRect.bottom = myPosY + Height; InvalidateRect( aWindow, &myInvalidateRect, true ); } int main () { // Set console title ::SetConsoleTitleA("MyWindow"); HWND myWindow = ::FindWindowA("ConsoleWindowClass","MyWindow"); if (myWindow == NULL) { printf("Failed to get window handle.\r\n"); return 1; } // get the window DC and it's size HDC myWindowDC = ::GetDC( myWindow ); RECT myWindowDimensions; ::GetClientRect( myWindow, &myWindowDimensions); int myWindowWidth = myWindowDimensions.right - myWindowDimensions.left; int myWindowHeight = myWindowDimensions.bottom - myWindowDimensions.top; HBITMAP myBitmapHandle; HDC myBitmapDC; BITMAP myBitmap; LoadBmp("Bild.bmp", myWindow, &myBitmap, &myBitmapHandle, &myBitmapDC); int myPosX = 0; int myPosY = 0; int myDestWidth = myBitmap.bmWidth; int myDestHeight = myBitmap.bmHeight; const int myStepWidthX = 10; const int myStepWidthY = 10; for (int i = 0; i < 25; i++) { for (int j = 0; j < 4; j++) { printf("- This is just some text --"); } printf("\r\n"); } unsigned char chr; while (true) { chr = _getch(); switch ( chr ) { // left case 75: InvalidateOldRegion(myWindow, myPosX, myPosY, myDestWidth, myDestHeight); myPosX = (myPosX <= myStepWidthX) ? 0 : (myPosX - myStepWidthX); PaintBitmap(myWindowDC, myBitmap, myBitmapHandle, myBitmapDC, myPosX, myPosY, myDestWidth, myDestHeight ); break; // right case 77: InvalidateOldRegion(myWindow, myPosX, myPosY, myDestWidth, myDestHeight); // do not move bitmap outside of the window if (myPosX + myStepWidthX >= (myWindowWidth - myDestWidth)) { myPosX = myWindowWidth - myDestWidth; } else { myPosX += myStepWidthX; } PaintBitmap(myWindowDC, myBitmap, myBitmapHandle, myBitmapDC, myPosX, myPosY, myDestWidth, myDestHeight ); break; // down case 80: InvalidateOldRegion(myWindow, myPosX, myPosY, myDestWidth, myDestHeight); if (myPosY + myStepWidthY >= (myWindowHeight - myDestHeight)) { myPosY = myWindowHeight - myDestHeight; } else { myPosY += myStepWidthY; } PaintBitmap(myWindowDC, myBitmap, myBitmapHandle, myBitmapDC, myPosX, myPosY, myDestWidth, myDestHeight ); break; // up case 72: InvalidateOldRegion(myWindow, myPosX, myPosY, myDestWidth, myDestHeight); myPosY = (myPosY <= myStepWidthY) ? 0 : (myPosY - myStepWidthY); PaintBitmap(myWindowDC, myBitmap, myBitmapHandle, myBitmapDC, myPosX, myPosY, myDestWidth, myDestHeight ); break; } } ::DeleteObject( myBitmapHandle ); ::ReleaseDC( myWindow, myBitmapDC ); ::ReleaseDC( myWindow, myWindowDC ); }
Bild kann man nimmer ausm Screen schieben und altes Bild wird gelöscht vorher (=> keine Schlieren).
Problem scheint dass man net so easy an die MessageQueue von der Console kommt.
Per PeekMessage() eine erstelln und GetMessage() in nem extra Thread tut sich jedenfalls nix.
Hook hat auch irgendwie nix gebracht so aufn ersten Blick.Evtl. sollte man noch ENABLE_WINDOW_INPUT setzten damit man mitbekommt wenn sich die Fenstergröße oder so ändert.
Kein Schimmer ob des taugt.MfG
-
So... und was soll das jetzt?
Console ist halt Console und Windows ist halt Windows...
-
Desswegen nennt man's oft auch Console-Window :p
Was der Sinn davon is musste den fragen der den Thread aufgemacht hat