Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Muffin

SDL - Moving character?

This topic is 5242 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

I''m new at SDL. And today I was playing around, trying to build an map code. I looked up some info on SDL''s homesite and read some topics in this forum. Then I started making my fist SDL code. It''s a scrolling styled game map like Zelda. Getting the map together was pretty easy. But make the character move was harder. I don''t know if this is a good code. But it''s my first. So i wounder what i would change and how to make the character move nicer. Now the character moves like an black box. But the character snakes, what i meen is that the black box is still left printed when i move to another square of the screen. I don''t know how to fix it. Ant the character''s moving speed is to fast i think. So Whats the best way of get my character to move nice and easy on the screen?
#include <stdlib.h>
#include <SDL/SDL.h>

const int MAPHEIGHT = 44;
const int MAPWIDTH = 44;
const int SQUAREVIEW = 15;
int SQUAREVIEWX = 0;
int SQUAREVIEWY = 0;
const int TILESIZE = 32;

class Character
{
public:
	int GetX();
	int GetY();
	void SetCharacterPosition(int X, int Y);
private:
	int pX;
	int	pY;
};

enum Tiles{GRASS, WALL};

char map[MAPWIDTH][MAPHEIGHT] = {
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};

	SDL_Surface *screen, *player, *grass, *wall;
    SDL_Event event;
	Uint8 *keys;
    bool done = false;

int Character::GetX()
{
return pX;
}

int Character::GetY()
{
return pY;
}

void VideoOptions()
{
    if(SDL_Init(SDL_INIT_VIDEO) == -1)
    {
        printf("Can''t init SDL:  %s\n", SDL_GetError());
        exit(1);
    }
    atexit(SDL_Quit); 
    screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE | SDL_DOUBLEBUF);
    if(screen == NULL)
    {
        printf("Can''t set video mode: %s\n", SDL_GetError());
        exit(1);
    }

grass = SDL_LoadBMP("grass.bmp");
wall = SDL_LoadBMP("wall.bmp");
}

void Character::SetCharacterPosition(int Y, int X)
{
pX = X;
pY = Y;
}

void DrawMap(const int svY, const int svX)
{
		for(int y = svY; y < svY + SQUAREVIEW; y++)
	{ 
		for(int x = svX; x < svX + SQUAREVIEW; x++)
			{
			if(map[y][x] == GRASS)
				{
					SDL_Rect srcRect;
					srcRect.w = TILESIZE;
					srcRect.h = TILESIZE;

					SDL_Rect dstRect;
					dstRect.x = (x - svX) * TILESIZE;
					dstRect.y = (y - svY) * TILESIZE;
					srcRect.w = TILESIZE;
					srcRect.h = TILESIZE;

					SDL_BlitSurface(grass, NULL, screen, &dstRect);
				}
				else if(map[y][x] == WALL)
				{
					SDL_Rect srcRect;
					srcRect.w = TILESIZE;
					srcRect.h = TILESIZE;

					SDL_Rect dstRect;
					dstRect.x = (x - svX) * TILESIZE;
					dstRect.y = (y - svY) * TILESIZE;
					srcRect.w = TILESIZE;
					srcRect.h = TILESIZE;

					SDL_BlitSurface(wall, NULL, screen, &dstRect);
				}
			}
		}
}

void DrawPlayer(int Y, int X)
{
					player = SDL_LoadBMP("player.bmp");
					SDL_Rect srcRect;
					srcRect.w = TILESIZE;
					srcRect.h = TILESIZE;

					SDL_Rect dstRect;
					dstRect.x = (X - SQUAREVIEWX) * TILESIZE;
					dstRect.y = (Y - SQUAREVIEWY) * TILESIZE;
					srcRect.w = TILESIZE;
					srcRect.h = TILESIZE;

					SDL_BlitSurface(player, NULL, screen, &dstRect);
					SDL_Flip(screen);
}

int main(int argc, char *argv[])
{
	Character Player;
	char GamePaused = ''n'';

	VideoOptions();
	DrawMap(0, 0);
	Player.SetCharacterPosition(2, 2);

	while(!done)
    {
		while(SDL_PollEvent(&event))
        {
            switch(event.type)
            {
                case SDL_QUIT:
                done = true;
                break;
            }
		}
		keys = SDL_GetKeyState(NULL);
		if(keys[SDLK_ESCAPE])
		{
			break;
		}
		if(keys[SDLK_UP])
		{
			if(Player.GetY()-1 >= 0)
			{
				if(map[Player.GetY()-1][Player.GetX()] != WALL)
				{
					Player.SetCharacterPosition(Player.GetY()-1, Player.GetX());
					if(Player.GetY() < SQUAREVIEWY)
					{
						SQUAREVIEWY -= 15;
						DrawMap(SQUAREVIEWY, SQUAREVIEWX);
					}
				}
			}
		}
		if(keys[SDLK_DOWN])
		{
			if(Player.GetY()+1 <= MAPHEIGHT)
			{
				if(map[Player.GetY()+1][Player.GetX()] != WALL)
				{
					Player.SetCharacterPosition(Player.GetY()+1, Player.GetX());
					if(Player.GetY() > (SQUAREVIEWY + 14))
					{
						SQUAREVIEWY += 15;
						DrawMap(SQUAREVIEWY, SQUAREVIEWX);
					}
				}
			}
		}
		if(keys[SDLK_RIGHT])
		{
			if(Player.GetX()+1 <= MAPWIDTH)
			{
				if(map[Player.GetY()][Player.GetX()+1] != WALL)
				{
					Player.SetCharacterPosition(Player.GetY(), Player.GetX()+1);
					if(Player.GetX() > (SQUAREVIEWX + 14))
					{
						SQUAREVIEWX += 15;
						DrawMap(SQUAREVIEWY, SQUAREVIEWX);
					}
				}
			}
		}
		if(keys[SDLK_LEFT])
		{
			if(Player.GetX()-1 >= 0)
			{
				if(map[Player.GetY()][Player.GetX()-1] != WALL)
				{
					Player.SetCharacterPosition(Player.GetY(), Player.GetX()-1);
					if(Player.GetX() < SQUAREVIEWX)
					{
						SQUAREVIEWX -= 15;
						DrawMap(SQUAREVIEWY, SQUAREVIEWX);
					}
				}
			}
		}
		DrawPlayer(Player.GetY(), Player.GetX());
		
    }

    return 0;
}  

Share this post


Link to post
Share on other sites
Advertisement
I didn''t read through your code, but I used to have the same problem. Before you draw the player, redraw the background.

I''m guessing you have something like:

loop {
getplayerinput();
drawplayer();
SDL_Flip(screen);
}

It should be like:

loop {
getplayerinput();
drawbg();
drawplayer();
SDL_Flip(screen);
}

If that''s not the problem, I''m sorry. :[

Share this post


Link to post
Share on other sites
So you're getting a black box around your character? To solve that you need to look into colour keys. Basically a colour key defines a certain colour that isn't drawn. A popular colour to use for this is pink (255, 0, 255)(RGB). If you used pink as a colour key you would put pink wherever you want your background to show through your character sprite. Setting colourkeys is done throuhg the SDL_SetColourKey function. You can use it like this


SDL_SetColorKey(surface, SRC_COLORKEY, SDL_MapRGB(surface->format, 255, 0, 255);


That would set a colour key of 255,0,255.

You also have to draw your map every frame instead of just when it's moved and as you're using double buffering call SDL_Flip(screen) at the end of your main loop (instead of at the end of your character draw function).

Now a couple of comments on your code. You appear to be loading your player sprite every time you draw it. This is not a good idea, you should do what you did with your wall and grass sprites. Load them up in a seperate init function called at the beginning of the program.

Why not put a draw function in with your character class instead of providing a DrawPlayer function? You could also store the player sprite in the character class and give it an init function.

As for moving more slowly, the best way is to do it via time based movement. SDL_GetTicks is what you need here. Basically you have to base how far the player moves on the time elapsed since you last moved it. Why don't you have a go at implementing it yourself and if you get stuck post back in this thread?

[edited by - Monder on April 10, 2004 5:55:21 PM]

[edited by - Monder on April 10, 2004 5:58:30 PM]

Share this post


Link to post
Share on other sites
For the black box, look into "Color Keying"; that should solve the problem.

Unless your game is very graphic intensive or intended for pretty low-end hardware, you can probably get away with redrawing the entire screen. So redraw your map every frame and then your sprite.

I do this with my current project and, on a PIII 650 with an ATI RAGE 128, I get upwards of 50 FPS. For a 2D game, this is more than enough.

Edit: On the AMD 1.2s at college, I hit up to 100 FPS. I'd say that's pretty decent. My old man's PII 233 can run it at a palty 15-20 FPS. Still fast enough to be playable.

[edited by - RuneLancer on April 10, 2004 6:18:52 PM]

Share this post


Link to post
Share on other sites
Hmm, i cant get the ColorKey thing to work. Monder: When i used your code. It said ''SRC_COLORKEY'' : undeclared identifier. SO i Tried the version on libsdl.org and now it looks like this.

bgcolor = SDL_MapRGB(screen->format, 255, 0, 255);
grass = SDL_LoadBMP("grass.bmp");
wall = SDL_LoadBMP("wall.bmp");
player = SDL_LoadBMP("player.bmp");
SDL_SetColorKey(player, SDL_SRCCOLORKEY | SDL_RLEACCEL, bgcolor);

I dont get any errors now. But the code doesn''t make my players pink arrays transparent.

ANd the moving speed code workt fine. But it came to my mind that i maby couldn''t use it to run faster and so on. For if i have enemies on my screen. THey are walking. THen i press for exempel Left shift. I start to run whit this code

if(keys[SDLK_LSHIFT])
{
Player.SetCharacterSpeed(30);
}
else
{
Player.SetCharacterSpeed(50);
}
SDL_Delay(Player.GetSpeed());
DrawMap(SQUAREVIEWY, SQUAREVIEWX);
DrawPlayer(Player.GetY(), Player.GetX());

Then the enemies and every thing on the screen will go faster i think. So is it another way of make my character run an walk, maby i used the code in an different way then you tried to explain to me Monder? I will maby try to get the drawplayer function into my Character class later today. Thanks for all help thou.

Share this post


Link to post
Share on other sites
I've made the transparent code work after a while. I had the wrong idee of it but after a few tests i made it work fine.

[edited by - Muffin on April 11, 2004 10:22:37 AM]

Share this post


Link to post
Share on other sites
Why are you using the player's speed to control the enemies' speed? Just give them a different "SetCharacterSpeed."

Edit: My bad. I read that sample code wrong.

Don't use SDL_Delay. That's not what he meant by time-based movement. Here's an example... You want, over the course of a second, for your character to move across 5 tiles in your gameworld. Let's say that, for convinience's sake, it takes 1 second to render a frame.

The obvious course of action would be to move the character 1 (second) * 5 (tiles); 5 tiles ahead every frame.

Let's suppose it "only" takes 500 ms to complete a frame on your buddy's PC. Oops... Now your character has crossed 10 tiles in a second because the game executes faster.

Well, there's an easy algorithm to fix this. See the above formula? Let's apply it again. 0.5 (seconds) * 5 (tiles); 2.5 tiles ahead every frame. Hey, now you still cross 5 tiles every second, but your game also runs much smoother!

See what time-based moevement is all about? You have to move your sprites based on how much time it takes to render a frame.

[edited by - RuneLancer on April 11, 2004 11:09:14 AM]

Share this post


Link to post
Share on other sites
quote:
Posted - 11 April 2004 3:30:54 AM
Hmm, i cant get the ColorKey thing to work. Monder: When i used your code. It said ''SRC_COLORKEY'' : undeclared identifier


Whoops sorry about that I meant SDL_SRCCOLORKEY, the problem in your code is that your using the screen->format to map an RGB triplet insetead of the player->format, though you probably work that out as you say you''ve fixed it.

Share this post


Link to post
Share on other sites
I've tried alot of things today. But i couldn't make the player movement work nicely. I ended up with this code.


DWORD t;
t = timeGetTime();
unsigned long diff = 0;
while(!done)
{
while(SDL_PollEvent(&event))
{
.................................. and so on .....

if(keys[SDLK_RIGHT])
{
if(Player.GetX()+1 <= (MAPWIDTH - 1))
{ Player.SetCharacterPosition(Player.GetY(), Player.GetX()+(1 * diff));
if(Player.GetX() > (SQUAREVIEWX + 14))
{
SQUAREVIEWX += 15;
}
}
}
DrawMap(SQUAREVIEWY, SQUAREVIEWX);
diff = (timeGetTime()-t);
t = timeGetTime();
DrawPlayer(Player.GetY(), Player.GetX());
SDL_Flip(screen);


Now the player just jump away from the screen when i press the Right button. So what am i doing wrong?

[edited by - Muffin on April 12, 2004 7:24:25 AM]

Share this post


Link to post
Share on other sites
I have tested some codes from this forum and from the Articels. But i cant get it to work. I realy need some ones help.

Share this post


Link to post
Share on other sites

  • 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!