Sign in to follow this  
Lillemanden

Sprite.Draw2D()

Recommended Posts

Hey. I'm just starting on C# and DirectX, so I tought I would try and make a small 2D game. And Sprite seems just right for that. I have a little problem though. When ever I use Sprite.Draw2d() and rotate the sprite, it rotates it around 0,0. Which is kinda useless to me. I've been searching the web, and it seems it's either a bug or a new way of handling rotation, introduced in the 2004 summer release. Either way I would like to know if there's a work-around for this? I guess I could move to 3D and just forget about the z-plan. But I would very much like to keep it as simpel as posible.

Share this post


Link to post
Share on other sites
I'm at the same place, just starting out with Managed DirectX, although I've been in C# and VB.NET for some time. But the Game design stuff is new to me.

I decided to try to do a 2D engine first, and then do a 3D. From what I've been able glean so far for a 2D engine is that most implementations use an image file for like the player's sprite that has multiple images on it (one facing N, one facing E, ....., one walking, one standing, etc, etc.). Based on the key that's pressed you load the corresponding image (You could so this to even if the player didn't move, but you wanted him to change the facing direction based on some other event).

AS I am new to this someone please correct anthing I may have misinterpreted.

Thanks,
Dave

Share this post


Link to post
Share on other sites
Unless you are doing a pure top-down view in your 2-d game, don't touch the rotation functions! Otherwise, things just plain won't look right at all.
I find its better to render each image at each direction that it's facing, and then in my code decide which frame to display based on direction, time and action. However, if your individual sprites are very large, this will start consuming a ton of memory.

Share this post


Link to post
Share on other sites
Yes, I could do that. And I'm gonna do it for most of the stuff in the game (most objects), and some arn't even gonna be rotated (I'm planning to use tiles for the ground). But players and some objects are gonne have to be rotated because they can be rotated to any angle. And it is a top-down-view game.

Share this post


Link to post
Share on other sites
I don't use C# or Managed DirectX, so I'm not sure if this will be of any help at all, but in C++ / DirectX you use D3DXMatrixTransformation2D which accepts a centre point for the rotation parameter. Here's a snippet:


D3DXVECTOR2 vCentre2D = D3DXVECTOR2(16.0f, 16.0f);
D3DXVECTOR2 vPosition2D = D3DXVECTOR2((float)(iPlayerX - 16.0f), (float)(iPlayerY - 16.0f));

D3DXVECTOR2 vPlayer;
D3DXVec2Add(&vPlayer, &vPosition2D, &vCentre2D);

D3DXVECTOR2 vDirection;
D3DXVec2Subtract(&vDirection, &vMouse, &vPlayer);

D3DXVECTOR2 vUp = D3DXVECTOR2(0.0f, 1.0f);
D3DXVECTOR2 vNormalized;

D3DXVec2Normalize(&vNormalized, &vDirection);

// These are actually radians not degrees.
fDegrees = atan2(vNormalized.x, -vNormalized.y);

D3DXMATRIX matRotation;
D3DXMatrixTransformation2D(&matRotation, NULL, NULL, NULL, &vCentre2D, fDegrees, &vPosition2D);

// Clear, Begin, etc. goes here

pD3DDevice->SetTransform(D3DTS_WORLD, &matRotation);
Player.Render(pD3DDevice);

// Present / End goes here



Hopefully that'll give you some ideas.

Share this post


Link to post
Share on other sites
I'm not familiar with the Sprite class, but if it is possible, perhaps you could move the sprite to that it's at 0,0 and then do the rotation. Then after the sprite has been rotated, move it back to its original position. I believe that's often how it happens in 3D.

Share this post


Link to post
Share on other sites
Quote:
Original post by GroZZleR
I don't use C# or Managed DirectX, so I'm not sure if this will be of any help at all, but in C++ / DirectX you use D3DXMatrixTransformation2D which accepts a centre point for the rotation parameter. Here's a snippet:

*** Source Snippet Removed ***

Hopefully that'll give you some ideas.


Thanks, but I was hoping I could use the Sprite class, but if I can't I will do something like your example.

Quote:
Original post by MonkeyCookie
I'm not familiar with the Sprite class, but if it is possible, perhaps you could move the sprite to that it's at 0,0 and then do the rotation. Then after the sprite has been rotated, move it back to its original position. I believe that's often how it happens in 3D.


I can't do that because you just have one sprite-object that you use to draw the textures. So you set the texture, position, rotation ceter, rotation in the same call (Draw2D()). But thanks anyway.

Share this post


Link to post
Share on other sites
Well, I'm using the C++ .net for my applications, so bear with me if things are different...

You should have two variables for rotation - Rotate_X and Rotate_Y. I send them to my Sprite interface for the rotation parameters of the Draw method.

Here's the deal. You have a sprite( a bitmap ) that is 100 x 100 in size. So the middle of this sprite will be 50 x 50. And thus...

Rotate_X = 50;
Rotate_Y = 50;

...when you give that to the Draw method, it should rotate by the center of the sprite. Easy, no?





Share this post


Link to post
Share on other sites
If you are using the Transform to do rotation you should probably use it to do your translations aswell, if you want to have any control over it that is.

Generate your transform matrix using a method that handles rotation around the center correctly correctly and then transform it to the correct location:

1. Rotation matrix * Translation Matrix. (NOT: Translation Matrix * Rotation matrix)

2. Use an Affine transform matrix that allows you to specify a center point four your rotation. (Matrix.AffineTransformation2D)

Recreate this this matrix for each call to Draw2D and specify a constant point (0,0) or the center of your sprite instead of its location.

If you use the Transform property of sprite it should apply to each call to Draw2D individually within the Begin/End block.

If you use SetWorldViewLH/RH or SpriteFlags.ObjectSpace to do your transform the transform will not be applied until you call End or flush and applied to every sprite drawn before then.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anri
Well, I'm using the C++ .net for my applications, so bear with me if things are different...

You should have two variables for rotation - Rotate_X and Rotate_Y. I send them to my Sprite interface for the rotation parameters of the Draw method.

Here's the deal. You have a sprite( a bitmap ) that is 100 x 100 in size. So the middle of this sprite will be 50 x 50. And thus...

Rotate_X = 50;
Rotate_Y = 50;

...when you give that to the Draw method, it should rotate by the center of the sprite. Easy, no?

That's how you would think it work, but I doesn't. Besides I'm not that stupid ;) That was what I did first, but it still rotate the sprite around (0,0), if I set the rotatecenter to (10,10) it just moves the sprite 10x10 pixels closer to (0,0).
Quote:
Original post by turnpast
If you are using the Transform to do rotation you should probably use it to do your translations aswell, if you want to have any control over it that is.

Generate your transform matrix using a method that handles rotation around the center correctly correctly and then transform it to the correct location:

1. Rotation matrix * Translation Matrix. (NOT: Translation Matrix * Rotation matrix)

2. Use an Affine transform matrix that allows you to specify a center point four your rotation. (Matrix.AffineTransformation2D)

Recreate this this matrix for each call to Draw2D and specify a constant point (0,0) or the center of your sprite instead of its location.

If you use the Transform property of sprite it should apply to each call to Draw2D individually within the Begin/End block.

If you use SetWorldViewLH/RH or SpriteFlags.ObjectSpace to do your transform the transform will not be applied until you call End or flush and applied to every sprite drawn before then.

Looks like you got my solution, but as I said I'm a newbie, so just gonna take me some time to try what you just wrote. If you could give me a code-example it would be greatly apriciated.

Share this post


Link to post
Share on other sites
Something like this ought to work.


//init
struct GameThing {
Texture t;
Vector2 p;
float r;
}
GameThing[] things = ...
Sprite s = new Sprite();

//render
s.Begin();
foreach(GameThing g in things){
s.Transform = Matrix.AffineTransformation2D(
1.0, new Vector2(0,0),g.r,g.p);
s.Draw2d(g.t,new Vector2(0,0),0,new Vector2(0,0),someColor);
}
s.End();


Share this post


Link to post
Share on other sites
Quote:
Original post by turnpast
Something like this ought to work.

*** Source Snippet Removed ***


That didn't work for me, but you got me on the trail.
I have to use the Sprite.Draw() method instead. So I have: sprite.Draw(texture, Vector3.Empty, Vector3.Empty, Color.White.ToArgb()) instead.
Thanks for the help. You really helped me out ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by Anri
Re: Lillemanden.

Well, it works in the C++ SDK. Its rotating right in front of me right now...

I thought C# was supposed to be "even easier than C++!"? Just goes to show!

Yeah, well I'm not using C#, I'm using Microsoft C# ;).
But seriusly, it's proberly a bug in the Managed DirectX SDK.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this