Problem animating sprite in SFML 2

Started by
0 comments, last by nox_pp 11 years, 6 months ago
Hello guys I am new to game programming, I never programmed a game in my life, I am starting small with C++ and sfml 2 creating a pong game, but, I ran into an issue, I was trying to deform the ball when it hits the borders, but I am failing to get the result I want, the animation is no seamless and don't know how to correct It. Can someone help.

Here is the code (you can get it too at : https://bitbucket.or...n/pong-pong/src)

header file

[source lang="cpp"]/*
* FILE : PongBall.hxx
* AUTHOR : ed3lgon
* CREATED : Oct 21, 2012
* MODIFIED : Undefined
* PURPOSE : Undefined
* DESCRIPTION : Undefined
*/

#ifndef PONGBALL_HXX_
#define PONGBALL_HXX_

#include <SFML/Graphics.hpp>

using namespace sf;

class PongBall
{
public:
PongBall(RenderWindow& pGameDisplay);
~PongBall();
void move(const Time& pElapsedTime);
void draw();
const Sprite& getSprite();

private:
static const float BALL_SPEED = 120.0f;
static const float BALL_DIAMETER = 50.0f;
int mImageIndex;
// reference to game window
RenderWindow& mGameDisplay;
Texture mBallSpriteSheet;
Sprite mBallSprite;
// will hold coordinates to images in the texture
IntRect mTextureRect[9];
enum Direction
{
NEGATIVE_X,
NEGATIVE_Y,
NEGATIVE_DIAGONAL1,
NEGATIVE_DIAGONAL_2,
POSITIVE_X,
POSITIVE_Y,
POSITIVE_DIAGONAL1,
POSITIVE_DIAGONAL2,
NONE,
};

enum AnimationStatus
{
START_ANIMATE,
END_ANIMATE,
DEFAULT_ANIMATE,
};
// indicates the direction the ball is facing, i.e. It is moving to.
Direction mDirection;
AnimationStatus mAnimtionStatus;
};

#endif /* PONGBALL_HXX_ */
[/source]

here is the implementation:
[source lang="cpp"]/*
* FILE : PongBall.cxx
* AUTHOR : ed3lgon
* CREATED : Oct 21, 2012
* MODIFIED : Undefined
* PURPOSE : Undefined
* DESCRIPTION : Undefined
*/

#include "PongBall.hxx"

#include <iostream>

PongBall::PongBall(RenderWindow& pGameDisplay) :
mImageIndex(0), mGameDisplay(pGameDisplay), mDirection(POSITIVE_X),
mAnimtionStatus(DEFAULT_ANIMATE)
{
// initialize horizontal images coordinates.
// this one is the default image, i.e. with no deformation.
mTextureRect[0].left = 0;
mTextureRect[0].top = 0;
mTextureRect[0].width = 51;
mTextureRect[0].height = 51;
// ball with minimum horizontal deformation.
mTextureRect[1].left = 51;
mTextureRect[1].top = 0;
mTextureRect[1].width = 49;
mTextureRect[1].height = 51;
// ball with medium horizontal deformation.
mTextureRect[2].left = 99;
mTextureRect[2].top = 0;
mTextureRect[2].width = 48;
mTextureRect[2].height = 51;
// the second most deformed ball.
mTextureRect[3].left = 147;
mTextureRect[3].top = 0;
mTextureRect[3].width = 46;
mTextureRect[3].height = 51;
// ball with max horizontal deformation.
mTextureRect[3].left = 197;
mTextureRect[3].top = 0;
mTextureRect[3].width = 42;
mTextureRect[3].height = 51;


// initialize vertical images coordinates.
// minimum vertical deformation.
mTextureRect[4].left = 0;
mTextureRect[4].top = 51;
mTextureRect[4].width = 51;
mTextureRect[4].height = 48;
// medium vertical deformation.
mTextureRect[5].left = 51;
mTextureRect[5].top = 51;
mTextureRect[5].width = 51;
mTextureRect[5].height = 47;
// maximum vertical deformation.
mTextureRect[6].left = 102;
mTextureRect[6].top = 51;
mTextureRect[6].width = 52;
mTextureRect[6].height = 45;
// maximum vertical deformation.
mTextureRect[6].left = 154;
mTextureRect[6].top = 51;
mTextureRect[6].width = 51;
mTextureRect[6].height = 43;


// load ball texture and set sprite texture.
mBallSpriteSheet.loadFromFile("res/gfx/ball_sheet.png");
mBallSprite.setTexture(mBallSpriteSheet);
mBallSprite.setTextureRect(mTextureRect[mImageIndex]);
// position ball at (100, 100)
mBallSprite.setPosition(500.0f, 300.0f);
}

PongBall::~PongBall()
{

}

void PongBall::move(const Time& pElapsedTime)
{
// get ball position on screen.
Vector2f ballPosition = mBallSprite.getPosition();
const float amount = BALL_SPEED * pElapsedTime.asSeconds();


// move the ball acording to the position It is facing
switch (mDirection)
{
// here I decrement ball's X cordinate and check if it has it the border.
case NEGATIVE_X:
ballPosition.x -= amount;
// if ball has touched the border invert direction
if (ballPosition.x < 1)
{
ballPosition.x = 0;

switch (mAnimtionStatus)
{
case START_ANIMATE:
++mImageIndex;
if (mImageIndex == 5)
{
mAnimtionStatus = END_ANIMATE;
}

break;

case END_ANIMATE:
--mImageIndex;
if (mImageIndex == 0)
{
mDirection = POSITIVE_X;
mAnimtionStatus = DEFAULT_ANIMATE;
}
break;

case DEFAULT_ANIMATE:
mAnimtionStatus = START_ANIMATE;
break;

default:
break;
}
}
break;

case NEGATIVE_Y:
ballPosition.y -= amount;
if (ballPosition.y < 0)
{
ballPosition.y += amount;
mDirection = POSITIVE_Y;
}
break;

case NEGATIVE_DIAGONAL1:

break;

case NEGATIVE_DIAGONAL_2:

break;

case POSITIVE_X:
ballPosition.x += amount;
// if ball has touched the right border
if (ballPosition.x > (1024 - BALL_DIAMETER))
{
ballPosition.x -= amount;
switch (mAnimtionStatus)
{
case START_ANIMATE:
mImageIndex++;
if (mImageIndex == 5)
{
mAnimtionStatus = END_ANIMATE;
}

break;

case END_ANIMATE:
mImageIndex--;
if (mImageIndex == 0)
{
mDirection = NEGATIVE_X;
mAnimtionStatus = DEFAULT_ANIMATE;
}
break;

case DEFAULT_ANIMATE:
mAnimtionStatus = START_ANIMATE;
break;

default:
break;
}
}
break;

case POSITIVE_Y:
ballPosition.y += amount;
if (ballPosition.y > (600 - BALL_DIAMETER))
{
ballPosition.y -= amount;
mDirection = NEGATIVE_Y;
}
break;

case POSITIVE_DIAGONAL1:

break;

case POSITIVE_DIAGONAL2:

break;

default:
break;
}

// update sprite rect.
mBallSprite.setTextureRect(mTextureRect[mImageIndex]);
// update sprite position
mBallSprite.setPosition(ballPosition);
}

void PongBall::draw()
{
mGameDisplay.draw(mBallSprite);
}
[/source]
Advertisement
You're controlling the speed of the ball, but you aren't controlling the speed of the animation. In the same way that you calculate "amount" in PongBall::move, you need to calculate what frame of the animation you should be on based upon what fps you would like your animation to play at. Only increment mImageIndex when you've accumulated enough time for a frame.

Something like this, following the pattern of your code:



mAnimationAccum += ANIMATION_SPEED * pElapsedTime.AsSeconds();

if(mAnimationAccum >= 1){
mAnimationAccum = 0;
++mImageIndex;
}


Say ANIMATION_SPEED is 30, for 30 fps. Then everytime mAnimationAccum == 1, 1/30 of a second has passed, so we increment the frame we're on and reset the accumulator. You'll probably want ANIMATION_SPEED to be 5-10 fps, but I suppose it depends on how fast the ball is moving on screen.

Between Scylla and Charybdis: First Look <-- The game I'm working on

Object-Oriented Programming Sucks <-- The kind of thing I say

This topic is closed to new replies.

Advertisement