SDL make an movable Image

I'm trying to load an image and move it with the arrow keys on the screen.
I'm sure its only a little error but I just can't find it.
To be exact it just renders nothing on it (have also tried to make the background white but it wont work)

main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <SDL/SDL.h>
#include "SDL/SDL_image.h"
#include <string>
#include "character.h"
using namespace std;

SDL_Surface *optimage(string filename) 
{ 
	SDL_Surface* loadedImage=NULL; 
	SDL_Surface* optimizedImage;
	optimizedImage=NULL; 
	loadedImage=IMG_Load(filename.c_str()); 
	
	if(loadedImage!=NULL ) 
	{ 
		optimizedImage=SDL_DisplayFormat(loadedImage); 
		SDL_FreeSurface(loadedImage);
	} 
	return optimizedImage; 
}

int main(int argc, char** argv)
{
	SDL_Surface* screen;
	screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
	SDL_Event event;
	Uint32 start;
	bool running=true;
	bool arr[4]={0,0,0,0};
	character player(optimage("16sprite.png"),20,20,128,192,1,1);
	while(running)
	{
		start=SDL_GetTicks();
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
				{
					case SDL_QUIT:
						running=false;
						break;
						
					case SDL_KEYDOWN:
					switch(event.key.keysym.sym)
					{
						case SDLK_UP:
							arr[0]=1;
							break;
						case SDLK_LEFT:
							arr[1]=1;
							break;
						case SDLK_DOWN:
							arr[2]=1;
							break;
						case SDLK_RIGHT:
							arr[3]=1;
							break;
					}
					break;
					
					case SDL_KEYUP:
					switch(event.key.keysym.sym)
					{
						case SDLK_UP:
							arr[0]=0;
							break;
						case SDLK_LEFT:
							arr[1]=0;
							break;
						case SDLK_DOWN:
							arr[2]=0;
							break;
						case SDLK_RIGHT:
							arr[3]=0;
							break;
					}
					break;
				}
		if(arr[0])
			player.moveUp();
		if(arr[1])
			player.moveLeft();
		if(arr[2])
			player.moveDown();
		if(arr[3])
			player.moveRight();
		
		SDL_FillRect(screen,&screen->clip_rect,SDL_MapRGB(screen->format,0xff,0xff,0xff));
		player.show();

		if(1000/30>SDL_GetTicks()-start)
			SDL_Delay(1000/30-(SDL_GetTicks()-start));
		}
	}
	SDL_Quit();
}


character.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "character.h"
#include <SDL/SDL.h>

character::character(SDL_Surface* img,int x,int y,int w, int h,int xVel,int yVel)
{
	sprite=sprite;
	box.x=x;
	box.y=y;
	box.w=w;
	box.h=h;
	xVel=xvel;
	yVel=yvel;
}

character::~character()
{
	SDL_FreeSurface(sprite);
}

void character::show()
{
	SDL_BlitSurface(sprite,NULL, SDL_GetVideoSurface(),&box);
}

void character::moveUp()
{
	box.y-=yvel;
}

void character::moveDown()
{
	box.y+=yvel;
}

void character::moveLeft()
{
	box.x-=xvel;
}

void character::moveRight()
{
	box.x+=xvel;
}

bool character::collision(SDL_Rect* col1,SDL_Rect* col2)
{
	if(col1->y >= col2->y + col2->h)
		return 0;
	if(col1->x >= col2->x + col2->w)
		return 0;
	if(col1->y + col1->h <= col2->y)
		return 0;
	if(col1->x + col1->w <= col2->x)
		return 0;
	return 1;
}


character.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <SDL/SDL.h>
#ifndef CHARACTER_H
#define CHARACTER_H

class character
{
	int x,y,xvel,yvel;
	SDL_Surface* sprite;
	SDL_Rect box;
	bool collision(SDL_Rect* col1,SDL_Rect* col2);
	
	public:
	character(SDL_Surface* sprite,int x,int y,int w, int h,int xVel,int yVel);
	~character();
	void show();
	void moveUp();
	void moveDown();
	void moveLeft();
	void moveRight();
};

#endif 
I may be wrong but after skimming it looks like your Render for the player is inside the Events loop. Shouldn't it be outside? (It should render whether there is an event or not, no?)
thanks.
I moved it out of it but it still does nothing....
main.cpp now looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <string>
#include "character.h"
using namespace std;

SDL_Surface *optimage(string filename) 
{ 
	SDL_Surface* loadedImage=NULL; 
	SDL_Surface* optimizedImage;
	optimizedImage=NULL; 
	loadedImage=IMG_Load(filename.c_str()); 
	
	if(loadedImage!=NULL ) 
	{ 
		optimizedImage=SDL_DisplayFormat(loadedImage); 
		SDL_FreeSurface(loadedImage);
	} 
	return optimizedImage; 
}

int main(int argc, char** argv)
{
	SDL_Surface* screen;
	screen=SDL_SetVideoMode(640,480,32,SDL_SWSURFACE);
	SDL_Event event;
	Uint32 start;
	bool running=true;
	bool arr[4]={0,0,0,0};
	character player(optimage("16sprite.png"),20,20,128,192,1,1);
	while(running)
	{
		start=SDL_GetTicks();
		while(SDL_PollEvent(&event))
		{
			switch(event.type)
				{
					case SDL_QUIT:
						running=false;
						break;
						
					case SDL_KEYDOWN:
					switch(event.key.keysym.sym)
					{
						case SDLK_UP:
							arr[0]=1;
							break;
						case SDLK_LEFT:
							arr[1]=1;
							break;
						case SDLK_DOWN:
							arr[2]=1;
							break;
						case SDLK_RIGHT:
							arr[3]=1;
							break;
					}
					break;
					
					case SDL_KEYUP:
					switch(event.key.keysym.sym)
					{
						case SDLK_UP:
							arr[0]=0;
							break;
						case SDLK_LEFT:
							arr[1]=0;
							break;
						case SDLK_DOWN:
							arr[2]=0;
							break;
						case SDLK_RIGHT:
							arr[3]=0;
							break;
					}
					break;
				}
		}
		if(arr[0])
			player.moveUp();
		if(arr[1])
			player.moveLeft();
		if(arr[2])
			player.moveDown();
		if(arr[3])
			player.moveRight();
		
		SDL_FillRect(screen,&screen->clip_rect,SDL_MapRGB(screen->format,0xff,0xff,0xff));
		player.show();

		if(1000/30>SDL_GetTicks()-start)
			SDL_Delay(1000/30-(SDL_GetTicks()-start));
	}
	SDL_Quit();
}
I don't see a call to SDL_Flip, so basically, you are not updating the screen.
If I was home I'd run it real quick, but I'd try and blit the surface without the Events code first. Are you able to just blit the entire image (without specific rect) to the screen? like by just calling SDL_BlitSurface
...well totaly forgotten to SDL_Flip.. ok now the background is white but it still does not show the image I still dont understand the:
 
SDL_BlitSurface(sprite,NULL, SDL_GetVideoSurface(),&box);

completely, how does it know which members of box are giving the position....
Well, I'm not actually sure what that is doing either, but to blit images to the screen I would set up a screen surface like this instead:

SDL_Surface* SCREEN;
SCREEN = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE );

then blit like:
SDL_BlitSurface(sprite, NULL, SCREEN, NULL);
SDL_Surface* SCREEN;
SCREEN = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE );

lines 24 and 25 of my main.cpp

as much as I understand it
SDL_BlitSurface(source,part of source(used later for the animation),destination surface,position on destination in form of an SDL_Rect object)

description of SDL_GetVideoSurface() from an SDL Wiki:
This function returns a pointer to the current display surface. If SDL is doing format conversion on the display surface, this function returns the publicly visible surface, not the real video surface.

Which means for me its comleatly the same as if I were writing screen but i cant write screen in character.cpp because simply does not exists there either cant I just call it in main because the member sprite is private.

I think something is wrong with getting the image into the character object (but i had also tried an much simpler image loading function with the same effect)
thanks^^
Last edited on
You may be right, but can you try this?

SDL_Surface* temp = optimage("16sprite.png");
// inside while(running)
SDL_BlitSurface(temp, NULL, screen, NULL);

If that's not working (or if it does work, actually), maybe that'll help narrow it down




(make sure it's after the fillrect/clearscreen of course)
Last edited on
Wait a second, I think I see the problem

1
2
3
4
5
6
7
8
9
10
character::character(SDL_Surface* img,int x,int y,int w, int h,int xVel,int yVel)
{
	sprite=sprite;
	box.x=x;
	box.y=y;
	box.w=w;
	box.h=h;
	xVel=xvel;
	yVel=yvel;
}


shouldn't that be "sprite=img;"
That work's as it should.

I found something in an tutorial for an pong game but I don't get the logic behind it:
1
2
3
4
5
6
7
8
9
10
11
void paddle::moveUp()
{
        if(box.y>0)
                box.y-=yvel;
}
 
void paddle::moveDown()
{
        if(box.y+box.h<SDL_GetVideoSurface()->clip_rect.h)
                box.y+=yvel;
}


Its irritating to see SDL_GetVideoSurface() only called in one of them, oh wait thats just to get the window height and length, right?
Last edited on
The reason it's called in only one is this:
"0" will always be the left-most of the screen (and the top-most), regardless of the screen's width and height. When finding (or checking against) the right side or the bottom, however, you'll need to know the width and height, which is why they're needing to call GetVideoSurface (to get the screen as you said) and then get its Height.

Also I ninja'd a post above yours - see if that fixes your problem :)
Yep I know.

Please hit me with something for my stupidity.
thank you it works as it should. ^~^
Topic archived. No new replies allowed.