(SDL): Bitmaps...flimmern

WorldRacer

Erfahrenes Mitglied
Hallo zusammen,

habe ein "Spiel" (lol, was heist Spiel, es kann drei Grafiken ausgeben ;-)) programmiert. Dies habe ich anhand eines Tutorials gemacht, und meinen Code schön säuberlich in Klassen geschrieben, wie es sich gehört ;-). So. Da hab ich nun folgendes:

Die main.cpp (Türlich, der Hauptprogrammablauf.)

Code:
// MaFirstAdventure.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.

#include "stdafx.h"
#include "sgoBitmap.h"
#include "sgoText.h"
#include "include/SDL.h"
#include "include/SDL_main.h"
#include "include/SDL_image.h"
#include "include/SDL_ttf.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>

using namespace std;


#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
#pragma comment(lib, "lib/SDL_image.lib")
#pragma comment(lib, "lib/SDL_ttf.lib")



int _tmain(int argc, _TCHAR* argv[])
{	
	// Biliotheken initialisieren
	if (     SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) {
        fprintf(stderr, "SDL konnte nicht initialisiert werden: %s\n", SDL_GetError());
        exit(1);
    }
	if(TTF_Init()==-1) {
		printf("TTF_Init: %s\n", TTF_GetError());
		exit(2);
	}
	
	// Tastatur-Eventabfrage definieren
	SDL_Event event;
	Uint8 *keystate;
	int gameover = 0;
	
// Fenster: Eigenschaften
		int hoehe = 1152, breite = 864;
		SDL_WM_SetCaption("Mein erstes Adventure", "Mein erstes Adventure");
		SDL_Surface *screen = SDL_SetVideoMode(hoehe, breite, 0, SDL_DOUBLEBUF|SDL_FULLSCREEN|SDL_HWSURFACE);
		SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 255));


// Hardware-Vars:
	// Mausposition:
		int mausx, mausy;
		char mtemp[20];
		char mx[20];
		char my[20];
// Bildmaterial laden!
	// Hintergründe
		sgoBitmap scenery1("haus.jpg", 0,0);
		scenery1.Show();

	// Charakter: Honk
		sgoBitmap honk("honk_back.bmp", 549,381);
		honk.ColorKey(1, 0x000000);
		honk.Show();
	
	// Charakter-Position
		int x = 0;
		int y = 0;

// Textmaterial laden !
	// Text: Hallo!
		int h;
		sgoText hiho("ephesianf", "Hallo! Ich bin Honk. Verschieb mich! Einen Moment bitte...Menü kommt gleich...", 0, 694,  255, 255, 255);
		hiho.Show();

	// Text: Maus-Y
		
		 
		sgoText txtMausx("ephesianf", "Maus X: ", 0, 0,  255, 255, 255);
		txtMausx.getHeight(&h);
		sgoText txtMausy("ephesianf", "Maus Y: ", 0,h+1, 255, 255, 255);
		txtMausx.Show();
		txtMausy.Show();
	
	
		
int step=1;
int menu=0;
int i;
int honkx = 549;
int honky = 381;
bool changestep;
sgoText menu1("ephesianf", "Ein Schritt nach links", 0,694,100,255,100);
sgoText menu2("ephesianf", "Ein Schritt nach rechts", 0,719,255,55,255);
sgoText menu3("ephesianf", "Ein Schritt nach oben", 0,744,255,255,255);
sgoText menu4("ephesianf", "Ein Schritt nach unten", 0,769,255,2,25);
menu1.setColor(255,255,255);
menu2.setColor(255,255,255);
menu3.setColor(255,255,255);
menu4.setColor(255,255,255);
menu1.Show();	
menu2.Show();
menu3.Show();
menu4.Show();
	
		
bool show_hi = true;	

	/* message pump */
  while (!gameover)
  {
    /* look for an event */
    if (SDL_PollEvent(&event)) {
      /* an event was found */
      switch (event.type) {
        /* close button clicked */
        case SDL_QUIT:
          gameover = 1;
          break;

        /* handle the keyboard */
        case SDL_KEYDOWN:
          switch (event.key.keysym.sym) {
            case SDLK_ESCAPE:
            case SDLK_q:
              gameover = 1;
              break;
		

          }
          break;
		/*case SDL_MOUSEMOTION:
			mausx = event.motion.x;
			mausy = event.motion.y;
			printf("2", mausx);
			break;*/


      }
    }

		keystate = SDL_GetKeyState(NULL);
    


    /* collide with edges of screen */
    if ( x < 0 ) {
      x = 0;
    }
    else if ( x > hoehe-231 ) {
      x = hoehe-231;
    }
    if ( y < 0 ) {
      y = 0;
    }
    else if ( y > breite-333 ) {
      y = breite-333;
    }
	

	// Zu guter letzt: Rendern
		
		strcpy(mx,"");
		strcpy(my,"");
		SDL_PumpEvents();
		SDL_GetMouseState(&mausx, &mausy);
		//mx = "";
		//my = "";
		sprintf_s(mx, sizeof(mx)/sizeof(*mx), "%d", mausx);
		sprintf_s(my, sizeof(my)/sizeof(*my), "%d", mausy);
		//sprintf(mx, "%il",10,mausx);
		//sprintf(my, "%il",10,mausy);
		//strcpy(mx, (char *) mausx);
		//strcpy(my, (char *) mausy);

		
		strcpy(mtemp,"Maus X: ");
		strcat(mtemp,mx);
		strcpy(mx,mtemp);

		strcpy(mtemp,"Maus Y: ");
		strcat(mtemp,my);
		strcpy(my,mtemp);
		
		if(step==1){
				
			if (keystate[SDLK_UP] ) {
				if(menu >= 0){
					menu--;
				}
				if(menu+1 == 1){
					menu2.setColor(255,255,255);
					menu1.setColor(255,255,0);
					SDL_Delay(200);
				}
				if(menu+1 == 2){
					menu3.setColor(255,255,255);
					menu2.setColor(255,255,0);
					SDL_Delay(200);
				}
				if(menu+1 == 3){
					menu4.setColor(255,255,255);
					menu3.setColor(255,255,0);
					SDL_Delay(200);
				}
			}
			if (keystate[SDLK_DOWN] ) {
				if(menu <= 3){
					menu++;
				}	
				if(menu-1 == 0){
					menu1.setColor(255,255,255);
					menu2.setColor(255,255,0);
					SDL_Delay(200);
				}	
				if(menu-1 == 1){
					menu2.setColor(255,255,255);
					menu3.setColor(255,255,0);
					SDL_Delay(200);
				}
				if(menu-1 == 2){
					menu3.setColor(255,255,255);
					menu4.setColor(255,255,0);
					SDL_Delay(200);
				}
			}
			if(keystate[SDLK_RETURN]){
					changestep = true;
					if(menu == 0){
						i=0;
						for(i=0; i<=50; i++){
							scenery1.Render(screen);
							honk.Location(honkx-i, honky);
							honk.Render(screen);
							txtMausx.Render(screen);
							txtMausy.Render(screen);
							menu1.Render(screen);
							menu2.Render(screen);
							menu3.Render(screen);
							menu4.Render(screen);
			
							SDL_FillRect(screen, 0, 0x000000);
							SDL_Delay(30);
						}
						honkx -= i;
						SDL_Delay(200);

						
					}
					if(menu == 1){
						i=0;
						for(i=0; i<=50; i++){
							scenery1.Render(screen);
							honk.Location(honkx+i, honky);
							honk.Render(screen);
							txtMausx.Render(screen);
							txtMausy.Render(screen);
							menu1.Render(screen);
							menu2.Render(screen);
							menu3.Render(screen);
							menu4.Render(screen);
			
							SDL_FillRect(screen, 0, 0x000000);
							SDL_Delay(30);
						}
						honkx += i;
						SDL_Delay(300);
					}
					if(menu == 2){
						i=0;
						for(i=0; i<=50; i++){
							scenery1.Render(screen);
							honk.Location(honkx, honky-i);
							honk.Render(screen);
							txtMausx.Render(screen);
							txtMausy.Render(screen);
							menu1.Render(screen);
							menu2.Render(screen);
							menu3.Render(screen);
							menu4.Render(screen);
			
							SDL_FillRect(screen, 0, 0x000000);
							SDL_Delay(30);
						}
						honky -= i;
						SDL_Delay(200);
					}
					if(menu == 3){
						i=0;
						for(i=0; i<=50; i++){
							scenery1.Render(screen);
							honk.Location(honkx, honky+i);
							honk.Render(screen);
							txtMausx.Render(screen);
							txtMausy.Render(screen);
							menu1.Render(screen);
							menu2.Render(screen);
							menu3.Render(screen);
							menu4.Render(screen);
			
							SDL_FillRect(screen, 0, 0x000000);
							SDL_Delay(30);

						}
						honky += i;
						SDL_Delay(200);
					}
			}
		}
		if(step==2){

		}

		
		

		scenery1.Render(screen);
		txtMausx.setText(mx);
		txtMausy.setText(my);
		txtMausx.Render(screen);
		txtMausy.Render(screen);
		honk.Render(screen);
		if(show_hi){
			hiho.Render(screen);
			SDL_Delay(5000);
			hiho.Hide();
			hiho.Destroy();
			SDL_FillRect(screen, 0, 0x000000);
			show_hi = false;
		}
		menu1.Render(screen);
		menu2.Render(screen);
		menu3.Render(screen);
		menu4.Render(screen);
		
		//SDL_FillRect(screen, 0, 0x000000);
		SDL_Flip(screen);
	

  }
  // Bei Programmende: Alle daten aus Speicher löschen
	honk.Destroy();
	hiho.Destroy();
	

	
	


	return 0;
}

Dann die sgoBitmap.h (dort wird die Klasse sgoBitmap deklariert und definiert)

Code:
#include "include/SDL.h"
#include "include/SDL_main.h"
#include "include/SDL_image.h"
#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
#pragma comment(lib, "lib/SDL_image.lib")
class sgoBitmap {
	private: SDL_Surface *suBild;
	         SDL_Rect rcZiel;
			 bool visible;

	public:
		sgoBitmap(char *file, int x, int y);
		void Render(SDL_Surface *suWindow);
		void Hide();
		void Show();
		void Destroy();
		void ColorKey(int flag, Uint32 color);
		void Location(int x, int y);
};
void sgoBitmap::Render(SDL_Surface *suWindow) {
	if(this->visible == true){
		
		SDL_BlitSurface(this->suBild,NULL,suWindow,&this->rcZiel);
		//SDL_UpdateRects(suWindow,1,&this->rcZiel);
		//SDL_Flip(suWindow);
	}
}
void sgoBitmap::Destroy(){
	SDL_FreeSurface( suBild );
}
void sgoBitmap::ColorKey(int flag, Uint32 color){
	if(flag==1)SDL_SetColorKey(this->suBild,SDL_SRCCOLORKEY,color);
	if(flag==2)SDL_SetColorKey(this->suBild,0,color);
}
sgoBitmap::sgoBitmap(char *file, int x, int y){
	if((this->suBild=IMG_Load(file))==NULL)
	{ 
		fprintf(stderr,"Error: %s\n",SDL_GetError());
		
	}
	//this->suBild=SDL_DisplayFormat(this->suBild); 
	this->rcZiel.w=this->suBild->w;
	this->rcZiel.h=this->suBild->h;
	this->rcZiel.x = x;
	this->rcZiel.y = y;
	this->visible = false;
}
void sgoBitmap::Hide(){
	this->visible=false;
}
void sgoBitmap::Location(int x, int y){
	this->rcZiel.x = x;
	this->rcZiel.y = y;
}
void sgoBitmap::Show(){
	this->visible=true;
}

Und die sgoText.h die für das Rendern von Text zuständig ist, speziell für das speichern von Text in Surfaces.

Code:
#include "include/SDL.h"
#include "include/SDL_main.h"
#include "include/SDL_image.h"
#include "include/SDL_ttf.h"

#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
#pragma comment(lib, "lib/SDL_image.lib")
#pragma comment(lib, "lib/SDL_ttf.lib")
class sgoText{
	private:
		char *chFont;
		char *chText;
		TTF_Font *sdlFont;
		SDL_Surface *suTextbild;
	    SDL_Rect rcZiel;
		bool visible, bold, underline, italic;
		SDL_Color sdlColor;
		int style;
		int posY, posX;

	public:
		void loadFont(char *fontname);
		void getPosition(int *x, int *y);
		void getHeight(int *height);
		void setText(char *text);
		void setColor(int r, int g, int b);
		void setItalic(bool b);
		void setBold(bool b);
		void setUnderline(bool b);
		void setLocation(int x, int y);
		void Render(SDL_Surface *suWindow);
		void Hide();
		void Show();
		void Destroy();
		sgoText(char *font, char *text, int x, int y, int r, int g, int b);
};
void sgoText::Hide(){
	this->visible=false;
}

void sgoText::Show(){
	this->visible=true;
}
void sgoText::loadFont(char *fontname){
	this->sdlFont = TTF_OpenFont(fontname, 16);
	if(!sdlFont) {
		printf("TTF_OpenFont: %s\n", TTF_GetError());
		// handle error
	}
}
void sgoText::getPosition(int *x, int *y){
	x = &posX;
	y = &posY;
}
void sgoText::getHeight(int *height){
	TTF_SizeText(this->sdlFont, this->chText, NULL, height);
}
void sgoText::setBold(bool b){
	bold = true;
}
void sgoText::setItalic(bool b){
	italic = true;
}
void sgoText::setUnderline(bool b){
	underline = true;
}


void sgoText::setText(char *text){
	this->chText = text;
	
	/*if(bold == true){
		style = style + TTF_STYLE_BOLD;
	}
	if(underline == true) {
		style = style + TTF_STYLE_UNDERLINE;
	}
	if(italic == true){
		style = style + TTF_STYLE_ITALIC;
	}*/
	//TTF_SetFontStyle(sdlFont, style);
	this->suTextbild = TTF_RenderText_Solid( this->sdlFont, this->chText, this->sdlColor);
}
void sgoText::Render(SDL_Surface *suWindow){
	if(this->visible == true){
		
		SDL_BlitSurface(this->suTextbild,NULL,suWindow,&this->rcZiel);
		//SDL_UpdateRects(suWindow,1,&this->rcZiel);
		//SDL_Flip(suWindow);
	}
}
void sgoText::setColor(int r, int g, int b){
	this->sdlColor.r = r;
	this->sdlColor.g = g;
	this->sdlColor.b = b;
	this->suTextbild = TTF_RenderText_Solid( this->sdlFont, this->chText, this->sdlColor);
}
void sgoText::setLocation(int x, int y){
	this->rcZiel.x = x;
	this->rcZiel.y = y;
}
void sgoText::Destroy(){
	SDL_FreeSurface( suTextbild );
}
sgoText::sgoText(char *font, char *text, int x, int y, int r, int g, int b){
	this->chText = text;
	this->sdlFont = TTF_OpenFont(font, 16);
	if(!this->sdlFont) {
		printf("TTF_OpenFont: %s\n", TTF_GetError());
		// handle error
	}
	this->sdlColor.r = r;
	this->sdlColor.g = g;
	this->sdlColor.b = b;
	//this->suBild=SDL_DisplayFormat(this->suBild); 
	this->suTextbild = TTF_RenderText_Solid( this->sdlFont, this->chText, this->sdlColor);
	this->rcZiel.x = x;
	this->rcZiel.y = y;
	this->visible = false;

}

So. das wär mein Code. Nun zum Problem. Wenn ich das Programm starte und die Bitmaps übereinander lege fangen diese an zu flimmern. Was kann ich dagegen tun?
Habs schon mit SDL_Flip(screen); versucht, aber hat net geklappt.... Wie kann ich manuell flippen?
 
Flimmerfrei Zeichnen, in englisch flicker free drawing ist eine Kunst für sich.
Es gibt ein paar Artikel im Web die sich damit befassen, z.B.
http://www.catch22.net/tuts/flicker

In kurz:
Du brauchst einen sogenannten double-Buffer.
Unter XP recht einfach:

CreateWindowEx(WS_EX_COMPOSITED, ......

aber das funktioniert NUR in XP.
Für alle anderen OS musst du selber buffern.
Google mal, findet viele gute Sachen zu dem Thema.
 
Zurück