Tetris mit SDL - Tastenproblem
-
Hallo ich versuche zurzeit ein Tetris mit hilfe von SDL zu programmieren, leider hab ich es noch nicht hinbekommen dass das kästchen nur zur seite rückt, wenn ich die taste los lasse, im moment ist es so dass es bei einmal drücken, gleich drei sätze in die entsprechende richtung macht. kann mir jemand hilfen? Wer will, dem kann ich auch die resaucen schicken, also die Bilddateien.
//#ifdef WIN32 //#pragma comment(lib, "SDL.lib") //#pragma comment(lib, "SDLmain.lib") //#endif #define fenster_breite 350 #define fenster_hoehe 260 #define farbtiefe 16 #include <stdlib.h> #include "SDL/SDL.h" SDL_Surface * farbe(int int_farbe) { SDL_Surface *bild; switch (int_farbe) { case 1: bild = SDL_LoadBMP("skins/simpleskin/st1.bmp"); //Gelb break; case 2: bild = SDL_LoadBMP("skins/simpleskin/st2.bmp"); //Grün break; case 3: bild = SDL_LoadBMP("skins/simpleskin/st3.bmp"); //Rot break; case 4: bild = SDL_LoadBMP("skins/simpleskin/st4.bmp"); break; case 5: bild = SDL_LoadBMP("skins/simpleskin/st5.bmp"); break; case 6: bild = SDL_LoadBMP("skins/simpleskin/st6.bmp"); break; case 7: bild = SDL_LoadBMP("skins/simpleskin/st7.bmp"); break; case 8: bild = SDL_LoadBMP("skins/simpleskin/st8.bmp"); break; default: bild = SDL_LoadBMP("skins/simpleskin/st0.bmp"); } if (bild == NULL) { printf("Das Bild konnte nicht geladen werden: %s\n", SDL_GetError()); exit(1); } return bild; } void hintergrund(SDL_Surface *bildschirm, SDL_Rect *altes_ziel) { SDL_Surface *hintergrund; hintergrund = SDL_LoadBMP("skins/simpleskin/bg.bmp"); if (hintergrund == NULL) { printf("Konnte den Hintergrund nicht laden: %s\n", SDL_GetError()); exit(1); } SDL_BlitSurface(hintergrund, altes_ziel, bildschirm, altes_ziel); SDL_UpdateRect(bildschirm, 0,0,0,0);//altes_ziel->x, altes_ziel->y, altes_ziel->w, altes_ziel->h); SDL_FreeSurface(hintergrund); } void klotz_zeichnen(SDL_Rect *ziel, SDL_Rect *altes_ziel, SDL_Surface *bildschirm, SDL_Surface *bild) { if(ziel->x != altes_ziel->x || ziel->y != altes_ziel->y)//damit der klotz nicht neu gezeichent wird, wenn es gar nicht nötig ist { /* auf den Bildschirm kopieren */ SDL_BlitSurface(bild, NULL, bildschirm, ziel); /* den veränderten Bildschirm-Bereich auffrischen */ SDL_UpdateRects(bildschirm, 1, ziel); //SDL_FillRect(bildschirm, altes_ziel, SDL_MapRGB(bildschirm->format, 255, 255, 0)); //zum test, damit ich eine eine gelbe spur hinter mir her ziehen kann. //SDL_Flip(bildschirm); /* den alten veränderten Bildschirm-Bereich wieder löschen */ hintergrund(bildschirm, altes_ziel); } } void klotz_fallen_lassen(SDL_Surface *bildschirm, int int_farbe, int art, int x) { int y=0, i, intervall; SDL_Surface *bild; SDL_Rect ziel, altes_ziel; Uint8 *taste; SDL_Event ereigniss; bool ende = false; /* lädt die BMP-Datei*/ bild = farbe(int_farbe); while (!ende) { intervall = 200; while (SDL_PollEvent(&ereigniss)) { if(ereigniss.type == SDL_QUIT) { ende = true; } } taste = SDL_GetKeyState(NULL); intervall = 200; if (y <= (fenster_hoehe - 15)) { y = y + ziel.h; //fall nach unten, wenn pfeiltaste nach unten gedrückt wird, fällt der Stein schneller. if (taste[SDLK_DOWN]) { if (y < fenster_hoehe - 15) { intervall = intervall - 150; } } } for(i = 0; i < 3;i++) { if(taste[SDLK_RIGHT]) { if(x < fenster_breite - 100) { x = x + ziel.w; } } if (taste[SDLK_LEFT]) { if (x > 56) { x = x - ziel.w; } } taste = SDL_GetKeyState(NULL); /* wo wird das neue Kästchen sein?*/ ziel.x = x; ziel.y = y; ziel.w = bild->w; ziel.h = bild->h; klotz_zeichnen(&ziel, &altes_ziel, bildschirm, bild); /* wo wird das alte Kästchen gelöscht?*/ altes_ziel.x = x; altes_ziel.y = y; altes_ziel.w = bild->w; altes_ziel.h = bild->h; } SDL_Delay(intervall); } /* löscht die BMP-Datei wieder aus den Surface */ SDL_FreeSurface(bild); } int main(int argc, char *argv[]) { SDL_Surface *bildschirm; SDL_Event event; bool done = false; //MessageBox (0, "Achtung, dies ist erst die Alphaversion!", "Tetris-Hinweis", 0); if (SDL_Init(SDL_INIT_VIDEO) == -1) { printf("Kann SDL nicht initialisieren: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); bildschirm = SDL_SetVideoMode(fenster_breite, fenster_hoehe, farbtiefe, SDL_HWSURFACE); if (bildschirm == NULL) { printf("Vidio Modus kann nicht eingerichtet werden: %s\n", SDL_GetError()); exit(1); } hintergrund(bildschirm, 0); klotz_fallen_lassen(bildschirm, 5, 0, 100); while (!done) { while (SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: done = true; break; } } } return 0; }
-
Frag im Eventloop die Keyboard Events ab. Wenn die Taste "Links" nach unten gedrückt wurde, schiebst du den Block einen nach links.
-
Gas mache ich ja schon, nur das ich nicht abfrage ob die Taste gedrückt wurde sondern ob sie gedrückt wird, und ich wüsste halt gerne, was ich ändern muss damit ich abfrage wann die Taste losgelassen wurde, statt wann die taste runter gedrückt wurde.
-
Sag ich doch! Es gibt auch ein Keyboard Event, dass dir anzeigt, in welchem Moment die Taste losgelassen wird.
Event: http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fEvent
Keyboard Event: http://www.libsdl.org/cgi/docwiki.cgi/SDL_5fKeyboardEvent
-
kannst du mir auch sagen wie ich das einsetzte? Ich hab sowas schon einmal in einem tutorial gelesen aber nicht hinbekommen...
-
Das steht alles auf den Seiten der SDL.
http://www.libsdl.org/cgi/docwiki.cgi/Handling_20the_20Keyboard
-
waa ich dreh noch durch, ich wuschtel da jetzt schon so lange dran rum, also ich habe es jetzt eigebaut, dass er nur regieren soll wenn SDL_KEYUP. Aber das hat mein Proble leider nicht gelöst, jetzt springt das kästen gar nicht mehr zu seite sondern nur noch ganz selten und wenn es doch zur seite springt, dann immer noch ganze 3 mal (wegen for-schleife bis 3) hat jemand ein lösungsvorschlag? hier der neue code:
//#ifdef WIN32 //#pragma comment(lib, "SDL.lib") //#pragma comment(lib, "SDLmain.lib") //#endif #define fenster_breite 350 #define fenster_hoehe 260 #define farbtiefe 16 #include <stdlib.h> #include "SDL/SDL.h" SDL_Surface * farbe(int int_farbe) { SDL_Surface *bild; switch (int_farbe) { case 1: bild = SDL_LoadBMP("skins/simpleskin/st1.bmp"); //Gelb break; case 2: bild = SDL_LoadBMP("skins/simpleskin/st2.bmp"); //Grün break; case 3: bild = SDL_LoadBMP("skins/simpleskin/st3.bmp"); //Rot break; case 4: bild = SDL_LoadBMP("skins/simpleskin/st4.bmp"); break; case 5: bild = SDL_LoadBMP("skins/simpleskin/st5.bmp"); break; case 6: bild = SDL_LoadBMP("skins/simpleskin/st6.bmp"); break; case 7: bild = SDL_LoadBMP("skins/simpleskin/st7.bmp"); break; case 8: bild = SDL_LoadBMP("skins/simpleskin/st8.bmp"); break; default: bild = SDL_LoadBMP("skins/simpleskin/st0.bmp"); } if (bild == NULL) { printf("Das Bild konnte nicht geladen werden: %s\n", SDL_GetError()); exit(1); } return bild; } void hintergrund(SDL_Surface *bildschirm, SDL_Rect *altes_ziel) { SDL_Surface *hintergrund; hintergrund = SDL_LoadBMP("skins/simpleskin/bg.bmp"); if (hintergrund == NULL) { printf("Konnte den Hintergrund nicht laden: %s\n", SDL_GetError()); exit(1); } SDL_BlitSurface(hintergrund, altes_ziel, bildschirm, altes_ziel); SDL_UpdateRect(bildschirm, 0,0,0,0);//altes_ziel->x, altes_ziel->y, altes_ziel->w, altes_ziel->h); SDL_FreeSurface(hintergrund); } void klotz_zeichnen(SDL_Rect *ziel, SDL_Rect *altes_ziel, SDL_Surface *bildschirm, SDL_Surface *bild) { if(ziel->x != altes_ziel->x || ziel->y != altes_ziel->y)//damit der klotz nicht neu gezeichent wird, wenn es gar nicht nötig ist { /* auf den Bildschirm kopieren */ SDL_BlitSurface(bild, NULL, bildschirm, ziel); /* den veränderten Bildschirm-Bereich auffrischen */ SDL_UpdateRects(bildschirm, 1, ziel); //SDL_FillRect(bildschirm, altes_ziel, SDL_MapRGB(bildschirm->format, 255, 255, 0)); //zum test, damit ich eine eine gelbe spur hinter mir her ziehen kann. //SDL_Flip(bildschirm); /* den alten veränderten Bildschirm-Bereich wieder löschen */ hintergrund(bildschirm, altes_ziel); } } void klotz_fallen_lassen(SDL_Surface *bildschirm, int int_farbe, int art, int x) { int y=0, i, intervall; SDL_Surface *bild; SDL_Rect ziel, altes_ziel; Uint8 *taste; SDL_Event ereigniss; bool ende = false; /* lädt die BMP-Datei*/ bild = farbe(int_farbe); while (!ende) { intervall = 200; while (SDL_PollEvent(&ereigniss)) { if(ereigniss.type == SDL_QUIT) { ende = true; } } taste = SDL_GetKeyState(NULL); intervall = 200; if (y <= (fenster_hoehe - 15)) { y = y + ziel.h; //fall nach unten, wenn pfeiltaste nach unten gedrückt wird, fällt der Stein schneller. if (taste[SDLK_DOWN]) { if (y < fenster_hoehe - 15) { intervall = intervall - 150; } } } for(i = 0; i < 3;i++) { taste = SDL_GetKeyState(NULL); switch(ereigniss.type) { case SDL_KEYUP: if(taste[SDLK_RIGHT]) { if(x < fenster_breite - 100) { x = x + ziel.w; } } if (taste[SDLK_LEFT]) { if (x > 56) { x = x - ziel.w; } } break; default: break; } /* wo wird das neue Kästchen sein?*/ ziel.x = x; ziel.y = y; ziel.w = bild->w; ziel.h = bild->h; klotz_zeichnen(&ziel, &altes_ziel, bildschirm, bild); /* wo wird das alte Kästchen gelöscht?*/ altes_ziel.x = x; altes_ziel.y = y; altes_ziel.w = bild->w; altes_ziel.h = bild->h; } SDL_Delay(intervall); } /* löscht die BMP-Datei wieder aus den Surface */ SDL_FreeSurface(bild); } int main(int argc, char *argv[]) { SDL_Surface *bildschirm; SDL_Event event; bool done = false; //MessageBox (0, "Achtung, dies ist erst die Alphaversion!", "Tetris-Hinweis", 0); if (SDL_Init(SDL_INIT_VIDEO) == -1) { printf("Kann SDL nicht initialisieren: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); bildschirm = SDL_SetVideoMode(fenster_breite, fenster_hoehe, farbtiefe, SDL_HWSURFACE); if (bildschirm == NULL) { printf("Vidio Modus kann nicht eingerichtet werden: %s\n", SDL_GetError()); exit(1); } hintergrund(bildschirm, 0); klotz_fallen_lassen(bildschirm, 5, 0, 100); while (!done) { while (SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: done = true; break; } } } return 0; }
-
Es macht nur Sinn ein SDL_PollEvent zur gleichen Zeit zu benutzten.
Du solltest deine Tastenabfrage hier einfügen:
while (SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: done = true; break; } } }Desweiteren kann es nicht schanden, sich mal durchzulesen, was SDL_PollEvent macht.
-
danke, das gleiche ist mir eben auch eingefallen, jetzt geht es, auch wenn es nicht daran lag dass ich darauf warten musste, dass die Taste losgelassen wird, sondern weil ich die komplette tastenabfrage umgestallten musste, geht es jetzt trotzdem^^ *freu* dann mal auf, das Tetris weiter zu machen und entlich zu vollenden *g