drawing animated sprites in directx

I'm making a game in directx and I've discovered that my draw function is wrong when the sprites are rotated, when drawn with a rotation value of 0 they are drawn as expected, but when rotated, the frame number changes the position at which the entity is drawn.

The draw function is shown below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void CSprite::Draw(LPD3DXSPRITE sprite, D3DXVECTOR2* pos, float rotation, float scale, int row, int column)
{
	D3DXMATRIX mat;
	D3DXVECTOR2 drawScale(scale,scale);

	m_centre = D3DXVECTOR2((column-1)*m_frameWidth + (float)m_frameWidth/2, (row-1)*m_frameHeight + (float)m_frameHeight/2);
	D3DXMatrixTransformation2D(&mat,NULL,0.0,&drawScale,&m_centre,rotation,pos);
	sprite->SetTransform(&mat);
	
	RECT rct;

	rct.left = (column-1)*m_frameWidth;
	rct.right= column*m_frameWidth;
	rct.top=(row-1)*m_frameHeight;
	rct.bottom=row*m_frameHeight;	

	sprite->Begin(D3DXSPRITE_ALPHABLEND);
	sprite->Draw(m_texture, &rct, NULL, NULL, 0xFFFFFFFF);
	sprite->End();
}


you must supply the D3DXMatrixTransformation2D function with a centre by which the sprite should be rotated, this may be the cause of the problem but I'm not sure where I've went wrong. The row and column of the frame in the texture to be drawn is also passed into the draw function and this is how the animation is carried out, the frame number is changed in the player update function.

1
2
3
4
5
6
7
8
9
void CPlayer::Update(long timeElapsed)
{
	if (m_frameNum >= m_frameList[m_state]) // if the current frame is the last frame on the current line
	{
		m_frameNum = 1;
	}
	else
		m_frameNum++;
}


been racking my brains over this, help would be greatly appreciated.
Thanks.
Hey, that's a pretty neat feature. On OpenGL you'd transform the vertices of a rectangle with a texture mapped to it yourself.
Anyway, I don't think you're setting the right center of rotation. What are row and column supposed to be?
this depends on which frame of animation the entity is at, and what 'state' the entity is in. The first row of textures, for all entities, contain frames for that entity's resting animation, the second line, the walking animation, and the third, the jumping animation. The 'state' is defined by an enum, so resting = 0, walking = 1 and jumping = 2, then when calling the draw function sends in the following parameters

 
Draw(m_sprite, m_pos, m_rotation, m_scale, m_currentFrame, m_state+1)


the state decides the row and the currentFrame decides the column used to select the frame in the texture. It is m_state+1 because resting (0) uses the frames on row 1 and walking (1) uses row 2 and so on.

The centre to rotate around, I believe, should be the centre of the current frame, which is what I try to calculate here

 
m_centre = D3DXVECTOR2((column-1)*m_frameWidth + (float)m_frameWidth/2, (row-1)*m_frameHeight + (float)m_frameHeight/2);
I believe the center is relative to the polygon the texture is mapped to, not to the texture itself. If that's the case, simply (w/2;h/2) should be the right coordinate.
If it is relative to the polygon it is mapped to then does that mean I would need to factor scale into the calculation of centre? So for instance in a 64 by 64 texture with a scale of 1 the centre would be (32,32) but if the scale was 2 would the centre be (64,64)?
Only if you actually changed the size of the polygon.
Thanks a lot helios that works just fine now =)
and btw 7366 posts! =O ur a bit of a pro eh.
Topic archived. No new replies allowed.