breakout in Winapi mit GDI und c++
-
Stimmt,GDI ist langsam, aber wenn man das Programm, wie bei DirectX auch oft gemacht wird, in der Hauptschleife laufen lässt, kann man noch ein bischen mehr Geschwindigkeit herausholen. Man muss dann halt mit PeekMessage arbeiten...
@Ethereal
Ist wirklich ein hübsches Spiel. Hast du die Musik eigentlich selbst gemacht? Und wieviele Levels hat das Spiel? Hast du einen Leveleditor benutzt?Mfg
OP
-
Hast du die Musik eigentlich selbst gemacht?
Ja. Alles ganz allein komponiert
Ich spiele auch noch Klavier und interessiere mich für Musik, deswegen macht's mir auch Spass, sowas zu komponieren.
Und wieviele Levels hat das Spiel?
Man, das ist schon etwas her....hmm, also ich glaub so zehn level, ja müsste eigentlich hinkommen.
Hast du einen Leveleditor benutzt?
Nein, sowas habe ich (leider) nicht. War auch ein bissl mühselig, aber im Prinzip ist es bei so einem Spiel noch nicht so schwer.
Jede Blockart bekommt halt ne ID, also z.B. 1 für rot, 2 für blau usw.. 0 ist dann leerer Raum.
Das ganze ist in nem Header als Level1/2/3...-Array deklariert, also wirklich nichts aufwendiges. Etwas nerviges war allerdings, zehn level à 160 potentiellen Blockpositionen als Array zu schreiben, is also ne Menge Schreibarbeit, die an sich keinen besonderen Spass macht, aber gelegentlich konnte ich auch ein paar Zeilen aus vorigen Levels per Copy&Paste übernehmen.
So, das war eigentlich das ganze Geheimnis
Gruß
E-the-Real
-
danke für deine ausführliche hilfe,
so, hab mich nun entschieden, dass ich erstmal nur nehn schläeger mach. (Ist schwer genung für mich
)
Ich hab mal DAS geschrieben:
#include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); mousko(LPARAM lparam); class schlaeger { public: static short xt, yt; //Temp koordinaten static short x,y; //Koordinaten bool move; //wird bewegt? void mDraw(HDC hdc, LPARAM lParam); }stick; void schlaeger:: mDraw(HDC hdc, LPARAM lParam) { y = 300; x = mousko(lParam); xt = x + 70; yt = y + 20; Rectangle(hdc, x, y, xt, yt); } int mousko(LPARAM lParam) { return LOWORD(lParam); } int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static char szAppName[] = "B" ; HWND hwnd ; MSG msg ; WNDCLASS wc ; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; RegisterClass (&wc); hwnd = CreateWindow (szAppName, "Fenstername", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { case WM_CREATE : return 0 ; case WM_PAINT : PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hwnd, &ps); stick.mDraw(hdc, lParam); EndPaint(hwnd, &ps); return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }
Fehlermeldung:
WINMAIN.obj : error LNK2001: Nichtaufgeloestes externes Symbol "public: static short schlaeger::yt" (?yt@schlaeger@@2FA)
WINMAIN.obj : error LNK2001: Nichtaufgeloestes externes Symbol "public: static short schlaeger::xt" (?xt@schlaeger@@2FA)
WINMAIN.obj : error LNK2001: Nichtaufgeloestes externes Symbol "public: static short schlaeger::x" (?x@schlaeger@@2FA)
WINMAIN.obj : error LNK2001: Nichtaufgeloestes externes Symbol "public: static short schlaeger::y" (?y@schlaeger@@2FA)was heisst den das?
-
Hi,
warum machst du denn deine xt,yt,x,y - Koordinaten static ???
Lass es mal weg, dann solltest du keine Link-Probleme haben, alsoclass schlaeger { public: short xt, yt; //Temp koordinaten short x,y; //Koordinaten bool move; //wird bewegt? void mDraw(HDC hdc, LPARAM lParam); }stick;
Das müsste klappen
Gruß
E-the-Real
-
juhu, danke.
daran hät ich jetzt echt nicht gedacht.nun, ich hab sie statisch gemacht weil ich dachte das ich den Variablenwert ja über den "ganzen" code brauche.
So,
#include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); mousko(LPARAM lparam); class schlaeger { public: short xt, yt; //Temp koordinaten short x,y; //Koordinaten bool move; //wird bewegt? void mDraw(HDC hdc, LPARAM lParam); }stick; void schlaeger:: mDraw(HDC hdc, LPARAM lParam) { y = 300; x = mousko(lParam); xt = x + 70; yt = y + 20; Rectangle(hdc, x, y, xt, yt); } int mousko(LPARAM lParam) { return LOWORD(lParam); } int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static char szAppName[] = "B" ; HWND hwnd ; MSG msg ; WNDCLASS wc ; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = szAppName; RegisterClass (&wc); hwnd = CreateWindow (szAppName, "Fenstername", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { case WM_CREATE : return 0 ; case WM_MOUSEMOVE: InvalidateRect(hwnd, NULL, NULL); case WM_PAINT : PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hwnd, &ps); stick.mDraw(hdc, lParam); EndPaint(hwnd, &ps); return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }
Gleich noch neh kurze Frage.
Ich hab jetzt meinen "Schläger".
doch wird der Bildschirm durch InvalidateRect nicht korrekt gelöscht.
durch diese Funktion wird ja das Fenster für ungültig erklärt.
Und dann leer neugezeichnet.
bei mir wird das alte Rechteck aber leider nicht gelöscht.EDIT:
letzten parameter von InvalidateRect auf True!! lang lebe die msdn!!
-
hosti schrieb:
nun, ich hab sie statisch gemacht weil ich dachte das ich den Variablenwert ja über den "ganzen" code brauche.
Statisch heißt, daß die Variable für beliebig viele Instanzen einer Klasse trotzdem nur 1x existiert. Was Du meinst, ist "global"...
-
Wenn ich nun soweit bin, wie weiter.
ich dachte erst mal die bewegung des Balles.. aber dazu brauch ich die kolison.. aber dafür brauch ich einen Ball der sich bewegt...
hmmm... ok vieleicht einfach mal den ball wie wild vom rand abprallen lasse.
Nun stellt sich die Frage, wie ich den Ball schräg über den Bildschirm bewegen könnte.
Mit einer Schleife??So,
if(i < 200)
Ball zeichnen, x+1 y+1hmm. das wäre dann mit einem winkel von 45Grad, und ein murks.
Vektor??
mit Sinus winkel berechnen?? oh gott wie geht denndas in diesem Fall??naja, vieleicht kann mich ja jemand aufklären.
EDIT:
@Sgt. Nukem
nunja, dann müsst ich sie ja ausserhalb eines jeden blockes definieren(dekla)
aber eine statische variable hat doch auch die globale eingenschaft, nicht?
also ich meine der wert wird nicht immer gelöscht, wenn man ausserhalb des blockes kommt
-
ethereal schrieb:
also ich glaub so zehn level, ja müsste eigentlich hinkommen.
10? Ist ja gar nix! Alles unter 100 ist Schrott.
-
mach nun damit weiter, dass ich verhindere das der schläger aus dem Bild fährt.
void schlaeger:: mDraw(HDC hdc, LPARAM lParam) { y = 650; x = mousko(lParam); xt = x + 90; yt = 670; if(xt < 1024) { Rectangle(hdc, x, y, xt, yt); } else { x--; xt = x + 90; Rectangle(hdc, x, y, xt, yt); } }
klappt aber nicht, mir ist nur nicht klar wieso.
wenn der rechte rand aus dem Fenster hängt wird ein pixelabgezogen und neu gezeichnet....
Ich scheitere immer an so doofen kleinigkeiten
-
Soll das ein Witz sein? Wenn x= 10000 ist, dann kann x - 1 nie auf dem Bildschirm sein. Denk mal darüber nach!
Bye, TGGC
-
was??
woher hast du denn die 10000 ??Mein Bildschirm hat eine Horizontale von 1024pixel.
Also sind 1024 das maixmum meines oberen eckpunktes meines rechteckes.also sind alle werte unter 1024+90, oder nicht??
wie würdest denn du das machen?
EDIT:
void schlaeger:: mDraw(HDC hdc, LPARAM lParam) { y = 650; x = mousko(lParam); xt = x + 90; yt = 670; if(xt < 1016) { Rectangle(hdc, x, y, xt, yt); } else { x = 924; xt = 1016; Rectangle(hdc, x, y, xt, yt); } }
Es klappt, scheint aber etwas gemurckst.
Bin ich auf dem richtigen Weg?
-
TGGC schrieb:
ethereal schrieb:
also ich glaub so zehn level, ja müsste eigentlich hinkommen.
10? Ist ja gar nix! Alles unter 100 ist Schrott.
WIE GEMEIN !!!
-
10000 ist nur ein Beispiel. Nach dem Code könnte x ja alles sein.
Wenn du weisst, wie du auf die passenden Zahlen kommst, bist du auf dem richtigen Weg. Sinnvoller ist es aber die Zahl einer Variablen oder Konstanten zuzuweisen und dort die entsprechende Formel hinzuschreiben. Wenn du die Breite des Pads änderst, sollte diese Zahl maximal einmal im Code vorkommen. Genauso die 1024 für die Bildschirmbreite.
Bye, TGGC
-
hi,
ich komm nich weiter (mal wieder)
Wie mach ich die ballanimation oder die kollision.
Ich hab Null ideen, hilfe.
gebt mir bitte einen Gedanken Anstoss
-
Also,
erst mal was zur Kollision:
Die einfachste (und oft auch ausreichende) Methode einer Kollisionsabfrage besteht darin, deine Objekt mit einer Bounding-Box zu umgeben. Das bedeutet konkret: Du legst einen rechteckigen Bereich um das Objekt, der, wenn das Objekt Rechteckig ist, dieselben Masse haben sollte.bool KollisionsTest(void) { int Ballradius_x = BallBreite/2;// Radius der BoundingBox vom Ball int Ballradius_y = BallHoehe/2; int Schlaegerradius_x=SchlaegerBreite/2;/*Radius der BoundingBox vom Schlaeger*/ int Schlaegerradius_y=SchlaegerHoehe/2; //Mittelpunkte beider BoundingBoxes int BallCenter_x = Ball_x + Ballradius_x; //Ball_x ist die x-Koord des B. int BallCenter_y = Ball_y + int Ballradius_y; // analog die y-Koord. int SchlaegerCenter_x = Schlaeger_x + Schlaegerradius_x; int SchlaegerCenter_y = Schlaeger_y + Schlaegerradius_y; // jetzt den Abstand der beiden Mittelpunkte int Abstand_x = abs(SchlaegerCenter_x - BallCenter_x); int Abstand_y = abs(SchlaegerCenter_y - BallCenter_y); // wenn abstand kleiner ist als beide Radien addiert... if((Abstand_x < (Ballradius_x + Schlaegerradius_x))&& (Abstand_y < (Ballradius_y + Schlaegerradius_y))) { //...dann liegt eine Kollision vor, also true zurückgeben return TRUE; } //...ansonsten keine Kollision -> false return FALSE; }
So, hab's jetzt net getestet, aber ich meine, das müsste irgendwie so schon klappen...
Zur Animation:
das ganze ist etwas kompliziert und wird wahrscheinlich ordentlich ruckeln, wenn du immer noch versuchst, GDI zu verwenden, aber prinzipiel würd' das so machen:
du hast eine Bitmap-Datei, in der jeweils in gleicher größe die einzelnen Bilder der Animation gespeichert sind (hintereinander).
Dann würde ich mir (bei GDI min.)zwei (, wenn nicht sogar mehr, falls das geht und effektiv ist bei GDI - Frage an die experten !) Objekte erstellen, in die du dann immer das jeweils nächste Bild lädst. Ein Objekt (ich weiss nicht so genau wie das heisst, kann sein, dass das objekt ein HBITMAP sein muss, vielleicht auch nur BITMAP, frag mal rum !) wird dann immer angezeigt, während in das nächste jeweils der nächste Animationsschritt geladen wird. dann zeigst du dieses an und lädsts in das erste den nächsten Animationsschritt. Such mal nach Backbuffering oder double buffering etc... da solltest du eigentlich einiges finden, ich bin da auch kein experte.
Ansonsten erstmal viel Erfolg
Gruß
E-the-Real
-
Auf www.zfx.info unter Tutorials gib's ein gutes Tutorial zu dem Thema, sehr ausführlich. Es wird beschrieben wie man ein einfaches Breakout programmiert.
-
@lustig:
ich rate erstmal von dem tutorial da ab, denn ich weiss nicht, ob man als anfänger damit...Move(double elapsed, std::list<CRenderable> &bricks, CPaddle &paddle);
...was anfangen kann...
Dazu kommt dynamische speicherallokierung und so'n ganzer kram. brauch man anfangs eigentlich gar nicht. sicher ist dein tip nicht schlecht, aber ich könnt mir vorstellen, dass er erst mal für verwirrung sorgen wird.
Gruß
E-the-Real