Jump to content
  • Advertisement
Sign in to follow this  
Juanu

[SDL] Problem Displaying Surfaces!

This topic is 4811 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi. First of all i will introduce myself. My name is Juan and I'm From Argentina. I'm 21 years old. I'm a programer and recently started with C++ as well as with SDL. I'm just starting a small project with a friend and wrote a basic engine that displays Mouse-Cursor position, Sprite position and moves the sprite on the screen as well as animates it. The problem y that, I run the program and it goes well, as it shuld But my friend, who uses the same Compiler and has extacly all the same configurations as I, is having problems. He can barely see the sprite (A ball in ths case). The didn't happened to him at first, before animating the ball, but it did when he tried to run it on FullScreen. Now that i added the animation to the spriters it hjappens to him even in Windowed Mode. Please, I'll show you the code and could you tel me whats goind on? Thanx Juan
#include <tchar.h>
#include <stdlib.h>
#include "SDL.h"
#include "SDL_Image.h"
#include "SDL_ttf.h"
//Constants for window resolution and BPP
#include "definiciones.h" 
//Function to draw the sprite on the surface
#include "dibujar.h"

//Mouse position
char chrMousePos[50];
//Sprite Position
char chrSpritePos[50];
//Sprite position X Axis
int SprPosX = 200;
//Sprite position Y Axis
int SprPosY = 200;
//Time from the SDL Timer
int Tiempo = 0;
//Last loop time 
int TiempoAnterior= 0;
//Elapsed time between loops
int TiempoTrans = 0;
//Saves the time to know if it has to change frames
int MSs = 0;
//Frames per second
const int FPS = 16;
//X axis of Sprite's Rect
int frameX = 0;
//Actual Frame
int frame = 0;
//Amount of frames
const int MAX_FRAMES = 7;

//Sprite Width
const int ANCHO_SPRITE = 82;
//Spriter Height
const int ALTO_SPRITE = 82;

int main(int argc, _TCHAR* argv[])
{
	if (SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) != 0 )
	{
        fprintf(stderr,"Error al inicializar SDL: %s\n", SDL_GetError());
		return 1;
	} 

	 if ( TTF_Init() < 0 )
	 {
	         fprintf(stderr,"Error al inicializar SDL_ttf: %s\n", SDL_GetError());
		 return 1;
	 }

	atexit(SDL_Quit);

        //Main Screen Surface
	SDL_Surface* pantalla = SDL_SetVideoMode ( VENTANA_ANCHO, VENTANA_ALTO, 0, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_NOFRAME );
	
	
	if (pantalla == NULL)
	{
		fprintf(stderr,"No se puedo establecer el modo de video: %s\n", SDL_GetError());
		return 1;
	}


	//Sprite Surface
	SDL_Surface* sprite = IMG_Load("data/gfx/bolita.png");
	
	if (sprite == NULL)
	{
		fprintf(stderr,"No se pudo cargar %s: %s\n", "bolita.png", SDL_GetError());
		return 1;
	}

	SDL_SetColorKey( sprite, SDL_SRCCOLORKEY, SDL_MapRGB(sprite->format, 255, 0, 255 ) );

	//Font
	TTF_Font* fuente = TTF_OpenFont("data/fonts/ARIAL.TTF", 14);
	if (fuente == NULL)
	{
		fprintf(stderr,"No se pudo cargar %s: %s\n", "ARIAL.TTF", SDL_GetError());
		return 1;
	}

	//ForeColor
	SDL_Color fuenteColor = { 255, 255, 255 };

	//Surface for the mouse position information
	SDL_Surface* textoSupPosMouse = TTF_RenderText_Solid(fuente, "",  fuenteColor);

	//Surface for Sprite position information
	SDL_Surface* textoSupPosSprite = TTF_RenderText_Solid(fuente, "", fuenteColor);

	//Position for mouse coords information
	SDL_Rect textoUbicaPosMouse = { 0, 0, 0, 0 };

	//Position for sprite coords information
	SDL_Rect textoUbicaPosSprite = {0, 16, 0, 0};

	//Font style
	TTF_SetFontStyle( fuente, TTF_STYLE_ITALIC );

	SDL_WM_SetCaption( VENTANA_TITULO, 0 );

	//KeyPress
	bool TeclaPress[323] = {false} ;

	//Event
         SDL_Event evento;

	//Loop Flag
         bool blnEjecutar = true;

	//Main loop	while ( blnEjecutar )
	{
	

		SDL_FillRect( pantalla, NULL, SDL_MapRGB( pantalla->format, 0, 0, 0 ) );


		if ( SDL_PollEvent( &evento ) )
		{

			if ( evento.type == SDL_QUIT )
			{
				blnEjecutar = false;
			}

			if ( evento.type == SDL_KEYDOWN )
				TeclaPress[evento.key.keysym.sym] = true;


			if ( evento.type == SDL_KEYUP )
	            TeclaPress[evento.key.keysym.sym] = false;


			if ( evento.type == SDL_MOUSEMOTION )
			{

				sprintf(chrMousePos,"Mouse: %d , %d", evento.motion.x, evento.motion.y);
			}

		}					

		if( TeclaPress[SDLK_ESCAPE] )
			blnEjecutar = false;


		if( TeclaPress[SDLK_LEFT] )
		{
			if ( SprPosX <= 0 )
				SprPosX = 0;
			else
			{
				SprPosX -= 2;

				if ( MSs >= ( 1000 / FPS ) )
				{

					MSs = 0;
					

					if ( frame <= 0 )
						frame = 7;
					else
						frame--;
				
					frameX = ANCHO_SPRITE * frame;

				}
				else
		 			MSs += TiempoTrans;
			}
		}
	

		if( TeclaPress[SDLK_RIGHT] )
		{
			if ( ( SprPosX + ANCHO_SPRITE ) >= VENTANA_ANCHO )
				SprPosX = VENTANA_ANCHO - ANCHO_SPRITE;
			else
			{
				SprPosX += 2;

			if ( MSs >= ( 1000 / FPS ) )
			{
				MSs = 0;
				

				if ( frame >= 7 )
					frame = 0;
				else
					frame++;

				frameX = ANCHO_SPRITE * frame;
			}
			else
		 		MSs += TiempoTrans;
			}
		}

		if( TeclaPress[SDLK_UP] )
		{
			if ( SprPosY <= 0 )
				SprPosY = 0;
			else
				SprPosY -= 2;
		}


		if( TeclaPress[SDLK_DOWN] )
		{	if ( ( SprPosY + ALTO_SPRITE ) >= VENTANA_ALTO )
				SprPosY = VENTANA_ALTO - ALTO_SPRITE;
			else
				SprPosY += 2;
		}



		


		Tiempo = SDL_GetTicks();
		TiempoTrans = Tiempo - TiempoAnterior;
		TiempoAnterior = Tiempo;
	



		textoSupPosMouse = TTF_RenderText_Solid( fuente, chrMousePos,  fuenteColor );
			

		sprintf(chrSpritePos,"Sprite: %d , %d", SprPosX, SprPosY);

		textoSupPosSprite = TTF_RenderText_Solid( fuente, chrSpritePos,  fuenteColor );


		SDL_BlitSurface( textoSupPosMouse, NULL, pantalla, &textoUbicaPosMouse );


		SDL_BlitSurface( textoSupPosSprite, NULL, pantalla, &textoUbicaPosSprite );


		dibujaSprite(sprite,pantalla,frameX,0,SprPosX,SprPosY,ANCHO_SPRITE,ALTO_SPRITE);


		SDL_Flip( pantalla );

	}

And this is the "dibujaSprite" function. (drawSprite)
//Receivs Sprite Surface, Screen Surface, SpriteSurface X, Y, Screen Surface X, Y and the Width and Height of the sprite.
void dibujaSprite(SDL_Surface* spriteSup, SDL_Surface* pantallaSup,
                  int spriteX, int spriteY, int pantallaX, int pantallaY,
				  int ancho, int alto)
{
   SDL_Rect spriteRect;
   spriteRect.x = spriteX;
   spriteRect.y = spriteY;
   spriteRect.w = ancho;
   spriteRect.h = alto;

   //Screen Rect
   SDL_Rect pantallaRect;
   pantallaRect.x = pantallaX;
   pantallaRect.y = pantallaY;
   pantallaRect.w = ancho;
   pantallaRect.h = alto;

   SDL_BlitSurface(spriteSup, &spriteRect, pantallaSup, &pantallaRect);
}

Any Ideas what the problem would be? Is it in the code? Bye!" Thanx!

Share this post


Link to post
Share on other sites
Advertisement
Hi Juan!

Why don't you try the pre-compiled executable on your friend's computer and see what happens. Post back and then maybe we can try to have a look at your code.

Share this post


Link to post
Share on other sites
Quote:
SDL_FillRect( pantalla, NULL, SDL_MapRGB( pantalla->format, 0, 0, 0 ) );

This is what is causing your problem.

You see, what's happening is that over and over again, you're clearing the screen and then blitting the sprite to it. What happens when the time after the screen is cleared, before the sprite is drawn, is longer than the time after the sprite is drawn, before the screen is cleared again? You see the cleared screen most of the time, and the sprite only some of the time.

This problem is solved by using a buffering system. The simplest method is to create another SDL_Surface that is compatible with the screen surface, and do your clearing and drawing to it. Then, after you're finished with all the drawing, you do a direct blit from the buffer surface to the screen surface. You don't have to worry about clearing the screen surface, because the pixels in the buffer surface have already been cleared and drawn, and will copy over the old pixels in the screen surface.

One other thing to think about sometime down the road is timing. Each computer will try to run your code as fast as possible, and faster computers will therefore run it faster than slower computers. This means that on a slower computer your sprite might move 60 pixels per second when you press the arrow key, and on a faster computer it might move 600 pixels per second. Read up on the relevant articles here at GameDev for more information on how to solve this -- also, the SDL documentation contains a simple example of how to solve it.

Cheers,
Twilight Dragon

Share this post


Link to post
Share on other sites
Thanx a lot!

I'll try it...

So you sayI do the fillrect on the backbuffer, then draw the sprite on that backbuffer too and then draw that surface entirely on the main surface???

Is that ok??

Thanx!

Share this post


Link to post
Share on other sites
hey, I'm having a question..
What do you mean when you say

"create another SDL_Surface that is compatible with the screen surface"

What do ou mean
Make a SUrface with SetVideoMode exactly like the main surface?

Or how?

Example please???

Thanx a lot!

Share this post


Link to post
Share on other sites
Are the Cone3D tutorial getting you down? Do you have a case of the Cone3D SDL tutorial bug? Well, look no further, Aaron Cox's Tutorials are here!

I find the Cone3D tutorials horribly written. Their solutions for problems are discusting and they don't explain what you need to know, and why. Start fresh with a better tutorial site and you'll start to grasp the concepts of SDL much better.

Share this post


Link to post
Share on other sites
Quote:
Original post by Juanu
"create another SDL_Surface that is compatible with the screen surface"

Say SDL_Surface *screen is your screen surface, and SDL_Surface *todraw is the surface you are drawing, use

screen = SDL_DisplayFormat(todraw);

About the flickering, try using SDL_SWSURFACE|SDL_FULLSCREEN as your flags when you set up your screen.

Share this post


Link to post
Share on other sites
"About the flickering, try using SDL_SWSURFACE|SDL_FULLSCREEN as your flags when you set up your screen"


Shouldn't I use SDL_HWSURFACE? Since Memory video for games is faster???


Share this post


Link to post
Share on other sites
No you can leave out the fullscreen. I remembered that in the Cone3D sprite tutorial, people had flickering problems. The one I posted earlier was the first solution. The other one you can try:

InitImages();
DrawBG();
SDL_Flip(screen);
DrawBG();

In your case, DrawBG() would be (I think)

SDL_FillRect( pantalla, NULL, SDL_MapRGB( pantalla->format, 0, 0, 0 ) );

This is so that both your buffers have the background image.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!