Sprite rotation woes

Started by
16 comments, last by Interminable 12 years, 4 months ago
this is the code from a method i use to draw my sprites:


D3DXMATRIX matRotate;
D3DXVECTOR2 center( Center.X , Center.Y );
D3DXVECTOR2 position( Position.X , Position.Y );
D3DXVECTOR2 scale( 1, 1 );
D3DXMatrixTransformation2D( &matRotate, NULL, NULL, &scale, &center, 0, &position);

PV_SpriteRenderer->SetTransform( &matRotate );

PV_SpriteRenderer->Draw( PV_Texture, pSrcRect, NULL, NULL, D3DCOLOR_XRGB( 255, 255, 255 ) );

D3DXMatrixRotationZ( &matRotate, 0 );
PV_SpriteRenderer->SetTransform( &matRotate );


does this help ?

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.

Advertisement

this is the code from a method i use to draw my sprites:


D3DXMATRIX matRotate;
D3DXVECTOR2 center( Center.X , Center.Y );
D3DXVECTOR2 position( Position.X , Position.Y );
D3DXVECTOR2 scale( 1, 1 );
D3DXMatrixTransformation2D( &matRotate, NULL, NULL, &scale, &center, 0, &position);

PV_SpriteRenderer->SetTransform( &matRotate );

PV_SpriteRenderer->Draw( PV_Texture, pSrcRect, NULL, NULL, D3DCOLOR_XRGB( 255, 255, 255 ) );

D3DXMatrixRotationZ( &matRotate, 0 );
PV_SpriteRenderer->SetTransform( &matRotate );


does this help ?


Unfortunately not. The code achieves what I already have. Everything is drawn in the right position, the sprite appears rotated, the walls appear the right way up, BUT the axis for the world seem to be rotated in some way. When I hold right to move right, the sprite moves diagonally towards the bottom left if I have rotated a bit clockwise.

There has to be a simple answer to this, there must be something obvious I'm doing wrong here. Is how I am doing my movement wrong? I have my sprite store in a D3DXVECTOR3, it's x and y coordinates (z is there in case I wanted to do layers or some such, but it's just 0, this is why I do player01.coordinates.x, etc). When I hold right, I increment that value by a speed variable. I then draw my sprite using this:

g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

What AM I doing wrong? Should I be using something other than ID3DXSprite to draw my sprites? Is there another way? Do I need to find out how to write some new different way of drawing images to the screen in a way that doesn't transform their axis?

Do I need to find out how to write some new different way of drawing images to the screen

you will end up building a "customized" version of ID3DXSprite.


drawing images to the screen in a way that doesn't transform their axis?


can you post screenshots ?


Unfortunately not. The code achieves what I already have. Everything is drawn in the right position, the sprite appears rotated, the walls appear the right way up, BUT the axis for the world seem to be rotated in some way. When I hold right to move right, the sprite moves diagonally towards the bottom left if I have rotated a bit clockwise.

There has to be a simple answer to this, there must be something obvious I'm doing wrong here. Is how I am doing my movement wrong? I have my sprite store in a D3DXVECTOR3, it's x and y coordinates (z is there in case I wanted to do layers or some such, but it's just 0, this is why I do player01.coordinates.x, etc). When I hold right, I increment that value by a speed variable. I then draw my sprite using this:

g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);


the code fragment you posted looks alright.
can you post more complete code that shows how you "move" your sprite ?

because if i take a stab at this in the dark( without looking at your player movement code ) i would say you need to use somethin like this:

yPosition += cos(RotationInDegrees) * speed;
xPosition += sin(RotationInDegrees) * speed;

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.


the code fragment you posted looks alright.
can you post more complete code that shows how you "move" your sprite ?

because if i take a stab at this in the dark( without looking at your player movement code ) i would say you need to use somethin like this:

yPosition += cos(RotationInDegrees) * speed;
xPosition += sin(RotationInDegrees) * speed;



So the answer to my question is that I can't stop it from transforming the axis, I have to compensate for it when moving after rotation?

Here is the code for movement and collision detection:



VOID UpdateSpritePosition(LPDIRECT3DTEXTURE9 texture, float xSpeedInput, float ySpeedInput)
{
D3DSURFACE_DESC spriteDesc;
D3DSURFACE_DESC wallDesc;
int spriteWidth = 0;
int spriteHeight = 0;

int wallWidth = 0;
int wallHeight = 0;

texture->GetLevelDesc(0,&spriteDesc);
spriteWidth = spriteDesc.Width;
spriteHeight = spriteDesc.Height;
float xDistance = 0;
float yDistance = 0;

if(!walls.empty())
{
for(unsigned int i = 0;i<=walls.size()-1;i++)
{
walls.texture->GetLevelDesc(0,&wallDesc);
wallWidth = wallDesc.Width;
wallHeight = wallDesc.Height;
bool testCorners = false;

if(player01.coordinates.x == walls.coordinates.x+wallWidth &&
player01.coordinates.y == walls.coordinates.y+wallHeight)
{
testCorners = true;
}

else if(player01.coordinates.x+spriteWidth == walls.coordinates.x &&
player01.coordinates.y == walls.coordinates.y+wallHeight)
{
testCorners = true;
}

else if(player01.coordinates.x + spriteWidth == walls.coordinates.x &&
player01.coordinates.y + spriteHeight == walls.coordinates.y)
{
testCorners = true;
}

else if(player01.coordinates.x == walls.coordinates.x + wallWidth &&
player01.coordinates.y +spriteHeight == walls.coordinates.y)
{
testCorners = true;
}

if(testCorners == false)
{
if((player01.coordinates.x+spriteWidth) <= walls.coordinates.x && (player01.coordinates.y+spriteHeight) >= walls.coordinates.y && player01.coordinates.y <= (walls.coordinates.y+wallHeight))
{
if((player01.coordinates.x + spriteWidth + xSpeedInput) >= walls.coordinates.x)
{
xDistance = walls.coordinates.x - (player01.coordinates.x + spriteWidth);
xSpeedInput = xDistance;
}
}
else if(player01.coordinates.x >= (walls.coordinates.x + wallWidth) && player01.coordinates.y <= (walls.coordinates.y+wallHeight) && (player01.coordinates.y+spriteHeight) >= walls.coordinates.y)
{
if((player01.coordinates.x + xSpeedInput) <= (walls.coordinates.x + wallWidth))
{
xDistance = (walls.coordinates.x + wallWidth) - player01.coordinates.x;
xSpeedInput = xDistance;
}
}

if((player01.coordinates.y+spriteWidth) <= walls.coordinates.y && (player01.coordinates.x+spriteWidth) >= walls.coordinates.x && player01.coordinates.x <= (walls.coordinates.x+wallWidth)) {
if((player01.coordinates.y + spriteHeight + ySpeedInput) >= walls.coordinates.y)
{
yDistance = walls.coordinates.y - (player01.coordinates.y + spriteHeight);
ySpeedInput = yDistance;
}
}

else if(player01.coordinates.y >= (walls.coordinates.y + wallHeight) && player01.coordinates.x <= (walls.coordinates.x+wallWidth) && (player01.coordinates.x+spriteWidth) >= walls.coordinates.x)
{
if((player01.coordinates.y + ySpeedInput) <= (walls.coordinates.y + wallHeight))
{
yDistance = (walls.coordinates.y + wallHeight) - player01.coordinates.y;
ySpeedInput = yDistance;
}
}
}
}
}

if(PacmanMovementModeEnabled)
{
player01.coordinates.x += xSpeedInput;
player01.xSpeed = xSpeedInput;
player01.coordinates.y += ySpeedInput;
player01.ySpeed = ySpeedInput;
player01.PacmanSpeed();
}
else
{
player01.coordinates.x += xSpeedInput;
player01.coordinates.y += ySpeedInput;
}
}

[quote name='ryan20fun' timestamp='1323455079' post='4892269']
the code fragment you posted looks alright.
can you post more complete code that shows how you "move" your sprite ?

because if i take a stab at this in the dark( without looking at your player movement code ) i would say you need to use somethin like this:

yPosition += cos(RotationInDegrees) * speed;
xPosition += sin(RotationInDegrees) * speed;



So the answer to my question is that I can't stop it from transforming the axis, I have to compensate for it when moving after rotation?
[/quote]

no, that is supposed to move the player in a relative forward / backward direction.


Here is the code for movement and collision detection:



VOID UpdateSpritePosition(LPDIRECT3DTEXTURE9 texture, float xSpeedInput, float ySpeedInput)
{
D3DSURFACE_DESC spriteDesc;
D3DSURFACE_DESC wallDesc;
int spriteWidth = 0;
int spriteHeight = 0;

int wallWidth = 0;
int wallHeight = 0;

texture->GetLevelDesc(0,&spriteDesc);
spriteWidth = spriteDesc.Width;
spriteHeight = spriteDesc.Height;
float xDistance = 0;
float yDistance = 0;

if(!walls.empty())
{
for(unsigned int i = 0;i<=walls.size()-1;i++)
{
walls.texture->GetLevelDesc(0,&wallDesc);
wallWidth = wallDesc.Width;
wallHeight = wallDesc.Height;
bool testCorners = false;

if(player01.coordinates.x == walls.coordinates.x+wallWidth &&
player01.coordinates.y == walls.coordinates.y+wallHeight)
{
testCorners = true;
}

else if(player01.coordinates.x+spriteWidth == walls.coordinates.x &&
player01.coordinates.y == walls.coordinates.y+wallHeight)
{
testCorners = true;
}

else if(player01.coordinates.x + spriteWidth == walls.coordinates.x &&
player01.coordinates.y + spriteHeight == walls.coordinates.y)
{
testCorners = true;
}

else if(player01.coordinates.x == walls.coordinates.x + wallWidth &&
player01.coordinates.y +spriteHeight == walls.coordinates.y)
{
testCorners = true;
}

if(testCorners == false)
{
if((player01.coordinates.x+spriteWidth) <= walls.coordinates.x && (player01.coordinates.y+spriteHeight) >= walls.coordinates.y && player01.coordinates.y <= (walls.coordinates.y+wallHeight))
{
if((player01.coordinates.x + spriteWidth + xSpeedInput) >= walls.coordinates.x)
{
xDistance = walls.coordinates.x - (player01.coordinates.x + spriteWidth);
xSpeedInput = xDistance;
}
}
else if(player01.coordinates.x >= (walls.coordinates.x + wallWidth) && player01.coordinates.y <= (walls.coordinates.y+wallHeight) && (player01.coordinates.y+spriteHeight) >= walls.coordinates.y)
{
if((player01.coordinates.x + xSpeedInput) <= (walls.coordinates.x + wallWidth))
{
xDistance = (walls.coordinates.x + wallWidth) - player01.coordinates.x;
xSpeedInput = xDistance;
}
}

if((player01.coordinates.y+spriteWidth) <= walls.coordinates.y && (player01.coordinates.x+spriteWidth) >= walls.coordinates.x && player01.coordinates.x <= (walls.coordinates.x+wallWidth)) {
if((player01.coordinates.y + spriteHeight + ySpeedInput) >= walls.coordinates.y)
{
yDistance = walls.coordinates.y - (player01.coordinates.y + spriteHeight);
ySpeedInput = yDistance;
}
}

else if(player01.coordinates.y >= (walls.coordinates.y + wallHeight) && player01.coordinates.x <= (walls.coordinates.x+wallWidth) && (player01.coordinates.x+spriteWidth) >= walls.coordinates.x)
{
if((player01.coordinates.y + ySpeedInput) <= (walls.coordinates.y + wallHeight))
{
yDistance = (walls.coordinates.y + wallHeight) - player01.coordinates.y;
ySpeedInput = yDistance;
}
}
}
}
}

if(PacmanMovementModeEnabled)
{
player01.coordinates.x += xSpeedInput;
player01.xSpeed = xSpeedInput;
player01.coordinates.y += ySpeedInput;
player01.ySpeed = ySpeedInput;
player01.PacmanSpeed();
}
else
{
player01.coordinates.x += xSpeedInput;
player01.coordinates.y += ySpeedInput;
}
}


it looks okey.

the sprite rendering code, how much of it did you try ?
did you try all of it ?

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.


the sprite rendering code, how much of it did you try ?
did you try all of it ?


I did alter it slightly based on variables I already had, etc.


g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

if(!walls.empty())
{
for(unsigned int i=0;i<=walls.size()-1;i++)
{
if(g_pD3DXSprite && walls.texture)
{
D3DXMatrixRotationZ(&walls.matrixRotation, 0.0);
g_pD3DXSprite->SetTransform(&walls.matrixRotation);
g_pD3DXSprite->Draw(walls.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &walls.coordinates, 0xffffffff);
}
}
}
g_pD3DXSprite->End();


[quote name='ryan20fun' timestamp='1323495209' post='4892439']
the sprite rendering code, how much of it did you try ?
did you try all of it ?


I did alter it slightly based on variables I already had, etc.


g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

if(!walls.empty())
{
for(unsigned int i=0;i<=walls.size()-1;i++)
{
if(g_pD3DXSprite && walls.texture)
{
D3DXMatrixRotationZ(&walls.matrixRotation, 0.0);
g_pD3DXSprite->SetTransform(&walls.matrixRotation);
g_pD3DXSprite->Draw(walls.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &walls.coordinates, 0xffffffff);
}
}
}
g_pD3DXSprite->End();


[/quote]

on a hunch, can you try this instead ?

g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
g_pD3DXSprite->Draw(player01.returnTexture(), NULL, NULL, NULL, 0xffffffff);

if(!walls.empty())
{
for(unsigned int i=0;i<=walls.size()-1;i++)
{
if(g_pD3DXSprite && walls.texture)
{
D3DXMatrixTransformation2D(&walls.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(walls.coordinates.x, walls.coordinates.y));
g_pD3DXSprite->SetTransform(&walls.matrixRotation);
g_pD3DXSprite->Draw(walls.returnTexture(), NULL, NULL, NULL, 0xffffffff);
}
}
}
g_pD3DXSprite->End();

Never say Never, Because Never comes too soon. - ryan20fun

Disclaimer: Each post of mine is intended as an attempt of helping and/or bringing some meaningfull insight to the topic at hand. Due to my nature, my good intentions will not always be plainly visible. I apologise in advance and assure you I mean no harm and do not intend to insult anyone.


[quote name='Interminable' timestamp='1323511009' post='4892472']
[quote name='ryan20fun' timestamp='1323495209' post='4892439']
the sprite rendering code, how much of it did you try ?
did you try all of it ?


I did alter it slightly based on variables I already had, etc.


g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
g_pD3DXSprite->Draw(player01.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &player01.coordinates, 0xffffffff);

if(!walls.empty())
{
for(unsigned int i=0;i<=walls.size()-1;i++)
{
if(g_pD3DXSprite && walls.texture)
{
D3DXMatrixRotationZ(&walls.matrixRotation, 0.0);
g_pD3DXSprite->SetTransform(&walls.matrixRotation);
g_pD3DXSprite->Draw(walls.returnTexture(), NULL, &D3DXVECTOR3(0,0,0), &walls.coordinates, 0xffffffff);
}
}
}
g_pD3DXSprite->End();


[/quote]

on a hunch, can you try this instead ?

g_pD3DXSprite->Begin(D3DXSPRITE_ALPHABLEND);
D3DXVECTOR2 scale(1,1);
D3DXMatrixTransformation2D(&player01.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(player01.coordinates.x, player01.coordinates.y));
g_pD3DXSprite->SetTransform(&player01.matrixRotation);
g_pD3DXSprite->Draw(player01.returnTexture(), NULL, NULL, NULL, 0xffffffff);

if(!walls.empty())
{
for(unsigned int i=0;i<=walls.size()-1;i++)
{
if(g_pD3DXSprite && walls.texture)
{
D3DXMatrixTransformation2D(&walls.matrixRotation, NULL, NULL, &scale, &D3DXVECTOR2(0,0), 0.5, &D3DXVECTOR2(walls.coordinates.x, walls.coordinates.y));
g_pD3DXSprite->SetTransform(&walls.matrixRotation);
g_pD3DXSprite->Draw(walls.returnTexture(), NULL, NULL, NULL, 0xffffffff);
}
}
}
g_pD3DXSprite->End();

[/quote]

I had to alter the advice in your example slightly (I don't want to rotate my walls, an obvious copy-paste from the first D3DXMatrixTransformation2D() line, but that's no big problem :P ), and I had to remove the bold BBcode tags as they don't work inside code tags but....it worked! :D

My collision detection seems to be a little off due to the rotation center not being the center, but I'll fix that, but it does now at least move in the right direction when rotated!

Many thanks for helping me with this, although I am curious as to why this issue occurred. It seems to be caused exclusively by setting the coordinates to draw the sprite in the ID3DXDraw() function, rather than leaving it all up to the ID3DXSprite object. As I am daft, I for some reason didn't make the connection that as I was applying the matrices with the coordinates of the sprite to the ID3DXSprite object, I was providing it with coordinates to draw it already. Still, I don't quite understand the behaviour that resulted...

This topic is closed to new replies.

Advertisement