2 Replies - 23583 Views - Last Post: 16 June 2009 - 05:59 AM Rate Topic: -----

#1 vAlexv   User is offline

  • New D.I.C Head
  • member icon

Reputation: 1
  • View blog
  • Posts: 24
  • Joined: 12-December 08

making sprite animation slower (SFML and C++)

Posted 15 June 2009 - 09:01 PM

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <sfml/Graphics.hpp>

enum KeyType
{
	UP,DOWN,RIGHT,LEFT,SPACE
};
typedef std::map<KeyType, bool> mapType;

void SetMap(mapType & type, const sf::RenderWindow & win)
{
	type[UP]	= win.GetInput().IsKeyDown(sf::Key::Up);
	type[DOWN]  = win.GetInput().IsKeyDown(sf::Key::Down);
	type[RIGHT] = win.GetInput().IsKeyDown(sf::Key::Right);
	type[LEFT]  = win.GetInput().IsKeyDown(sf::Key::Left);
	type[SPACE] = win.GetInput().IsKeyDown(sf::Key::Space);
}

const int ScreenWidth  = 600;
const int ScreenHeight = 500;
const int Speed		   = 300;

class Player
{
public:
	Player( const std::string & s) : frame(0)
	{
		static sf::Image image = sf::Image();
		image.LoadFromFile(s);
	
		sprite.SetImage(image);
		sprite.SetSubRect(	sf::IntRect(0,  61, 32, 127) );
		sprite.SetPosition(400,400);

		int x = 0;
		int y = 32;
		for(int i = 0; i < 6; ++i)
		{
						 //Sub rects of the sprite sheets
			 leftSprites.push_back(sf::IntRect(x, 61, y, 127));
			 rightSprites.push_back(sf::IntRect(x, 192, y, 255));
			 upSprites.push_back(sf::IntRect(x, 126, y, 192));
			 downSprites.push_back(sf::IntRect(x,0,y,62));

			 x += 32;
			 y += 32;
		}
	}
	void Move(const sf::RenderWindow & App)
	{
		WallCollision(App.GetFrameTime());
		SetMap(easierKey, App);

		float delta = App.GetFrameTime() * spriteSpeed;

		if(easierKey[LEFT])
		{
			sprite.SetSubRect(leftSprites[frame]);
			sprite.Move(-delta,0);
			++frame;
		}
		if(easierKey[RIGHT])
		{
			sprite.SetSubRect(rightSprites[frame]);
			sprite.Move(delta,0);
			++frame;
		}
		if(easierKey[UP])
		{
			sprite.SetSubRect(upSprites[frame]);
			sprite.Move(0,-delta);
			++frame;
		}
		if(easierKey[DOWN])
		{
			sprite.SetSubRect(downSprites[frame]);
			sprite.Move(0, delta);
			++frame;
		}
				//Return to first frame

		if(frame >= leftSprites.size() - 1)
			frame = 0;
	}
	void Show( sf::RenderWindow & App)
	{
		App.Draw(sprite); 
	}
private:
	void WallCollision(float delta)
	{
		const float x = sprite.GetPosition().x;
		const float y = sprite.GetPosition().y;

		static const float WidthMinus  = ScreenWidth  - sprite.GetSize().x;
		static const float HeightMinus = ScreenHeight - sprite.GetSize().y;

		if(x <= 0) 	sprite.Move(spriteSpeed * delta, 0);
		if(y <= 0)	sprite.Move(0, spriteSpeed * delta);

		if(y >= HeightMinus) sprite.Move(0, -spriteSpeed * delta);
		if(x >= WidthMinus)  sprite.Move(-spriteSpeed * delta, 0);
	}
private:
	sf::Sprite sprite;
	enum {spriteSpeed = 100};

	//Holds the sub rects of the sprites
	std::vector<sf::IntRect> leftSprites;
	std::vector<sf::IntRect> rightSprites;
	std::vector<sf::IntRect> upSprites;
	std::vector<sf::IntRect> downSprites;

	mapType easierKey;

	unsigned int frame;
};
class Background
{
public:
	Background(const std::string & s) 
	{
		static sf::Image image = sf::Image();
		image.LoadFromFile(s);
		sprite.SetImage(image);
		sprite.SetPosition(0,0);

		back.SetImage(image);
		back.SetPosition(-sprite.GetSize().x + 10,0);
	}
	void Move(const sf::RenderWindow & App)
	{
		const float delta = App.GetFrameTime();
		sprite.Move(backSpeed * delta, 0);
		back.Move(backSpeed * delta, 00);

		if(sprite.GetPosition().x >= ScreenWidth)
			sprite.SetPosition(-sprite.GetSize().x + 10, 0);
		if(back.GetPosition().x >= ScreenWidth)
			back.SetPosition(-sprite.GetSize().x + 10, 0);
	}
	void Show( sf::RenderWindow &app)
	{
		app.Draw(sprite);
		app.Draw(back); 
	}
private:
	sf::Sprite sprite;
	sf::Sprite back;
	enum{backSpeed = 250};
};

int main()
{
	sf::RenderWindow App(sf::VideoMode(ScreenWidth,ScreenHeight), "Main");
	
	Player player("sprites.png"); 
	Background background("fire.png");

	while(App.IsOpened())
	{
		sf::Event event;
		while(App.GetEvent(event))
		{
			if(event.Type == event.Closed)
				App.Close();	
			if(App.GetInput().IsKeyDown(sf::Key::Escape))
				App.Close();
		}

		//Sprite events
		player.Move(App);
		background.Move(App);

		App.Clear(sf::Color(100,100,100));

		//Sprite displays
		background.Show(App);
		player.Show(App);

		//Window draw
		App.Display();								
	}
}


The sprite animation is really fast, and it looks really weird, how can I fix it?
This is the sprite sheet I am using for now, if you want to test it
http://www.allacrost...ap_claudius.png

Thanks

This post has been edited by vAlexv: 15 June 2009 - 09:02 PM


Is This A Good Question/Topic? 0
  • +

Replies To: making sprite animation slower (SFML and C++)

#2 chuckb   User is offline

  • D.I.C Head

Reputation: 13
  • View blog
  • Posts: 211
  • Joined: 29-May 09

Re: making sprite animation slower (SFML and C++)

Posted 15 June 2009 - 09:53 PM

Hi,
Let's take this snippet of yours:

		if(easierKey[RIGHT])
		{
			sprite.SetSubRect(rightSprites[frame]);
			sprite.Move(delta,0);
			++frame;
		}


It seems that each time you press the right arrow key the sprite moves and the frame advances. Correct? The problem is that anytime you press the key, this code is called several times while the button is being pressed...which results in very fast animation. So, it's important for the code to recognize the first key press and ignore the other ones the follow immediately.

Here's the concept in code...needs tweaked...and isn't an elegant solution. I would actually separater updating of movement with rendering...but that's a different story.

static float keyTime = 0;
keyTime += delta;

if(easierKey[RIGHT] && keyTime > 0.2){
			sprite.SetSubRect(rightSprites[frame]);
			sprite.Move(keyTime,0);
			++frame;
			keyTime = 0;
}


So, this code is processed only once every 200 milliseconds. The frame will only advance once every 200 milliseconds. You can adjust the 0.2 for faster/slower behavior.

Regards,
Chuck
Was This Post Helpful? 1
  • +
  • -

#3 stayscrisp   User is offline

  • フカユ
  • member icon

Reputation: 1040
  • View blog
  • Posts: 4,325
  • Joined: 14-February 08

Re: making sprite animation slower (SFML and C++)

Posted 16 June 2009 - 05:59 AM

If you want to get a good speed for animation then you will have to use some kind of time based animation and movement.

You need to cap your frame rate so that if your project is played on a different computer it is still the same speed, this is very important.

Basically you need to create a timer and then use it to get the frame rate, if the frame rate is over a certain level then you cap it or make it wait between frames.
Was This Post Helpful? 1
  • +
  • -

Page 1 of 1