sdl , flickering bmp

Started by
17 comments, last by knarjons 19 years, 2 months ago
Hello. I have done a game, PONG, two paddles and a ball. One of the first games i came in contact with as a child. Im new to sdl and there is a problem when the ball gets close to the paddle, the paddle start to flicker and it doesnt stop until the ball has bounced away a bit from the paddle. the code:

//******************INCLUDES*****************************
#include <SDL.h>

#include <iostream>
using namespace std;

#include "font.h"


//*******************STRUKTURER**************************

struct sprite //håller info för rörliga bilder
{
	int x; // innehåller x-koord för sprite
	int y; //innehåller y-koord för sprite
	int xvel; //anger hur många pixels bild flyttar i x-led
	int yvel; //anger hur många pixels bild flyttar i y-led
	int width; // bredd på sprite
	int height; //höjd på sprite
};


//******************GLOBALER*****************************
SDLFont *font1;        // 2 fonts
SDLFont *font2;

int p1score=0, p2score=0;


//En SDL_Surface per bild
SDL_Surface *screen, *backg, *Ball, *pl1paddle, *pl2paddle; 


//Varje bilds info frå struct sprite
sprite ball, paddle1, paddle2;

//*******************Funktioner***************************

//Ladda in en bild o ändra till format som SDL använder
SDL_Surface * ImageLoad(char *file)
{
	SDL_Surface *temp1, *temp2;
	temp1=SDL_LoadBMP(file);
	temp2=SDL_DisplayFormat(temp1);
	SDL_FreeSurface(temp1);
	return temp2;
}


//Visa en bild
void DrawIMG(SDL_Surface *img, int x, int y)
{
	SDL_Rect dest; //Definierar en rektangulär yta
	dest.x = x;
	dest.y = y;
	SDL_BlitSurface(img, NULL, screen, &dest);
}


//Visa en bit av en bild, för att inte ska bli spår när vi flyttar
void DrawIMG(SDL_Surface *img, int x, int y, int w, int h, int x2, int y2)
{
	SDL_Rect dest;
	dest.x = x;
	dest.y = y;
	SDL_Rect dest2;
	dest2.x = x2;
	dest2.y = y2;
	dest2.w = w;
	dest2.h = h;
	SDL_BlitSurface(img, &dest2, screen, &dest);
}


//Visar en bild o tar bort det gamla som inte ska visas
void draw(SDL_Surface *surf, int x, int y, int width, int height)
{
	DrawIMG(backg, x-20, y-20, width+80, height+80, x-20, y-20);
	DrawIMG(surf, x, y);
	
	SDL_Flip(screen); // Från minnet till skärmen
}


//Visa ställning
void DrawScore(int pl1score, int pl2score)
{
	drawString(screen, font2,30, 20, "SCORE:  %d", pl1score);
	drawString(screen, font2,620, 20, "SCORE:  %d", pl2score);
	
}

// Visa allt som ska visas
void DrawAll()
{
	
	draw(Ball, ball.x, ball.y, ball.width, ball.height);
	draw(pl1paddle, paddle1.x, paddle1.y, paddle1.width, paddle1.height);
	draw(pl2paddle, paddle2.x, paddle2.y, paddle2.width, paddle2.height);
	DrawScore(p1score, p2score);
}

//Sätt upp alla startvärden
void restart()
{
	DrawIMG(backg, 0, 0);
	ball.x=395;
	ball.y=295;
	ball.yvel=3; 
	ball.xvel=10;
	ball.width=10;
	ball.height=10;

	paddle1.x=40;
	paddle1.y=260;
	paddle1.xvel=0;
	paddle1.yvel=0;
	paddle1.width=10;
	paddle1.height=80;

	paddle2.x=760;
	paddle2.y=260;
	paddle2.xvel=0;
	paddle2.yvel=0;
	paddle2.width=10;
	paddle2.height=80;
}

void newgame()
{
	p1score=0;
	p2score=0;

	restart();
}

//Kolla om kollision, utför i såfall lämlig åtgärd;
void checkforcollision()
{
	//Boll och vägg (eller tak golv)
	if(ball.y<=0) // taket
	{
		ball.yvel=-ball.yvel; // ändra riktning på bollen
	}
	if(ball.y+ball.height>=600) //golvet
	{
		ball.yvel=-ball.yvel; // ändra riktning
	}

	//spelare 1 o vägg (tak golv)
	if(paddle1.y<=0)
	{
		paddle1.y=0;
	}
	if(paddle1.y>=paddle1.height+600)
	{
		paddle1.y=600-paddle1.height;
	}

	//spelare 2 o vägg
	if(paddle2.y<=0)
	{
		paddle2.y=0;
	}
	if(paddle2.y>=paddle2.height+600)
	{
		paddle2.y=600-paddle2.height;
	}

	//boll o spelare 1
	if(ball.x<=paddle1.x+paddle1.width &&ball.y<=paddle1.y+paddle1.height &&ball.y>=paddle1.y)
	{
		ball.xvel=-ball.xvel;//byt rikting x-led
		ball.xvel++; //öka hastighet
		ball.yvel++;
	}

	//boll o spelare 2
	if(ball.x+ball.width>=paddle2.x && ball.y>= paddle2.y&&ball.y<=paddle2.y+paddle2.height)
	{
		ball.xvel=-ball.xvel;//byt rikting x-led
		ball.xvel--; //öka hastighet
		ball.yvel--;
	}


	//Kolla om spelare 1 vinner
	if(ball.x>=800-ball.width)
	{
		p1score++;
		if(p1score==10)
		{
			int i=0;
			while(i!=500)
			{
				drawString(screen, font2,350, 220, "Spelare 1 VANN");
				SDL_Flip(screen);
				i++;
			}
			newgame();
		}
		SDL_Delay(500);
		restart();
	}

	//Kolla om spelare 2 vinner
	if(ball.x<=0)
	{
		p2score++;
		if(p2score==10)
		{
			int i=0;
			while(i!=500)
			{
				drawString(screen, font2,350, 220, "Spelare 2 VANN");
				SDL_Flip(screen);
				i++;
			}
			newgame();
		}
		SDL_Delay(500);
		restart();
	}
}

//flytta bollen
void updateball()
{
	ball.x+=ball.xvel;
	ball.y+=ball.yvel;
}



//************************MAIN*******************************

int main(int argc, char *argv[])
{

	//Standard initiering sdl 
	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO)<0)
	{
		exit(1);
	}
	atexit(SDL_Quit);

	screen=SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE|SDL_HWPALETTE);
	if(screen==NULL)
	{
		exit(1);
	}

	font1=initFont("data/font1");
	font2=initFont("data/font2");

	//Variabler
	backg=ImageLoad("bakgrund.bmp");
	Ball=ImageLoad("boll.bmp");
	pl1paddle=ImageLoad("paddel.bmp");
	pl2paddle=ImageLoad("paddel.bmp");

	ball.x=395;
	ball.y=295;
	ball.xvel=10;
	ball.yvel=3;
	ball.width=10;
	ball.height=10;

	paddle1.x=40;
	paddle1.y=260;
	paddle1.xvel=0;
	paddle1.yvel=0;
	paddle1.width=10;
	paddle1.height=80;

	paddle2.x=760;
	paddle2.y=260;
	paddle2.xvel=0;
	paddle2.yvel=0;
	paddle2.width=10;
	paddle2.height=80;

SDL_WM_SetCaption("Rickes bollspel","Rickes bollspel");
SDL_ShowCursor(0);


//*****************SPEL-LOOP***************************
DrawIMG(backg, 0, 0);
while(1)
{
	DrawAll();
	updateball();
	checkforcollision();

	SDL_Event event;
	Uint8 *keys;

	while(SDL_PollEvent(&event))
	{
		if(event.type==SDL_QUIT)
		{
			return 0;
		}

		if(event.type == SDL_KEYDOWN)
		{
			if(event.key.keysym.sym==SDLK_ESCAPE)
			{
				return 0;
			}
		}
	}

	keys=SDL_GetKeyState(NULL);
	if(keys[SDLK_UP])
	{
		paddle2.y -=6;
	}
	if(keys[SDLK_DOWN])
	{
		paddle2.y +=6;
	}

	if(keys[SDLK_a])
	{
		paddle1.y -=6;
	}

	if(keys[SDLK_z])
	{
		paddle1.y +=6;
	}
}
return 0;
}
Advertisement
One thing I would stringly suggest - take the SDL_Flip(screen) out of the Draw() function and put it at the end of the DrawAll() function. You don't want to flip the screen every time you draw an object.
what a different that made, i will have to slow down the speed now. The flickering stopped also. But another thing came up, when the ball are close to the paddle it dissapears for a little moment and shows again when it has bounced and are going away from the paddle, The ball is invisible when it bounce.
maybe you could try to change in void DrawAll() so that you draw you ball last, and not the paddles. And maybe you should mask your imagaes. Svensk?

/Whizz


well, now the paddle dissaperad instead, i dont really know what you meen by mask? Yes Swedish, sorry for my comments,
Quote:Original post by Dave Hunt
One thing I would stringly suggest - take the SDL_Flip(screen) out of the Draw() function and put it at the end of the DrawAll() function. You don't want to flip the screen every time you draw an object.


Seconded, you only want to flip the screen buffers when you've finished drawing everything for that particular frame, doing a buffer flip only once will also improve your framerate if SDL is tied to refresh rate for updating the screen.
okej, thanks for the advice, but i still have the problem with the dissapearing ball near the paddle.
I think
void draw(SDL_Surface *surf, int x, int y, int width, int height){	DrawIMG(backg, x-20, y-20, width+80, height+80, x-20, y-20);	DrawIMG(surf, x, y);	SDL_Flip(screen); // Från minnet till skärmen}

this function is supposed to re-draw the part of the background "damaged" by the sprite, then draw the sprite. The problem is, you draw the ball, then clear an area around the paddle before drawing the paddle. If the ball is in the space around the paddle that gets cleared, it will seem to disappear as it gets close to the paddle because it is getting drawn over.

To avoid this, you can clear all the sprites at once at their current location (ie. re-draw the piece of background they cover), then update all the sprites at once, then draw them all at once at their new location.

I suck at explaining things, so I hope that was OK [wink]
the rug - funpowered.com
and use the source tag
How do I use source tag?? I tried without space,

This topic is closed to new replies.

Advertisement