XNA - About the relation between world space and the screen space

醉酒当歌 提交于 2019-12-06 11:28:50

Screen space is presumably the same thing as Client Space. Client space goes from (0,0) in the top left corner to (width, height) in the bottom right. "Up" is Y-.

Projection space goes from (-1,-1) in the bottom-left corner to (1,1) in the top-right. This is what the GPU uses for its final rendering. SpriteBatch handles this for you (by contrast: BasicEffect requires you to provide a projection matrix).

World space is whatever you want it to be. This is the coordinate system that your gameplay takes place in. In your example it seems that this is the same as Client space.

Traditionally, when doing this sort of thing, you have an object defined in its own space. In your example the rock and ship rectangles are hard coded into the function TransformRectangle as the initial values of the variables topLeft through bottomRight.

You then have a World matrix for each object. This moves that object from its own space into its position in World space. In your example this is shipTransform and rockTransform. A World transform is also done inside SpriteBatch.Draw, based on the arguments you pass in (using the texture itself as the initial object).

Then you have a View matrix - which you can think of as your camera. You example doesn't have one of these. But if you wanted, for example, to pan the view around to follow the player, you would use a translation matrix here, created from the player's position (and pass it to SpriteBatch.Begin).

And finally you have a Projection matrix that converts your World space into Projection space so that the GPU can render your scene.

Now a possible problem here is that SpriteBatch internally defines a projection matrix that converts a Client space to Projection space (so it basically "assumes" World space is Client space). Not a problem in your example because the two spaces are the same.

If your World space is not the same thing as Client space, and you want to use SpriteBatch, you must create an additional matrix to convert from World space to Client space and insert it between the View and Project matrices (ie: multiply it with View and pass it into SpriteBatch.Begin).

If your World space defines which way is "up" (or "right", for that matter) differently to SpriteBatch, then you must keep in mind that the original object used by SpriteBatch.Draw defines "up" to be Y-.

I don't believe it was space relationships that caused what you saw (in your first edition of your question). The matrix is ambidextrous in that regard to what space it is in. If you feed it screen space values, it returns screen space values. So the relationship (screen/world) is not relevant and not existent.

For instance, if you wanted to orbit your ship around the centerpoint of the 2d screen using a matrix:

Vector2 screenCenter = new Vec2(width/2, h/2);// abbreviated
Vector2 shipPosition = screenCenter;
shipPosition.X += 25;//offset ship from center slightly

shipPosition = Vector2.Transform(shipPosition, Matrix.CreateTranslation(-screenCenter));
shipPosition = Vector2.Transform(shipPosition , Matrix.CreateRotationZ(someRadians));
shipPosition = Vector2.Transform(shipPosition , Matrix.CreateTranslation(screenCenter));


//although the above would typically be written as:
shipPosition = Vector2.Transform(shipPosition - screenCenter, Matrix.CreateRotationZ(someAngle)) + screenCenter;

Notice, all the values are screenspace values only. No world/screen space relationship mattered. So that is how to rotate a point around another point in 2d screenspace using matrices. For 3d it would be the exact code but with a Z component (vector3) and use 3d world space.

Your comboMatrix (from earlier code) and in your new code snippet the transform() may be tripping you up some. When multiplying matrices together, its like adding one rotation to another. So your comboMatrix was like 3 + 5 +(-3) ... all you really did was the equivalent of 5. All your comboMatrix did was the equivelent of rotZ... it did no translations. and your Transform() is similar. When I applied the three matrices to shipPosition above, I made sure each Matrix was applied to shipPosition befor moving onto the next operation. Sometimes you can concatenate matrices before applying, but in your case, not.

Does this help or have I still missed your question?

In TestMatrix():

shipPosition = Vector2.Transform(shipPosition, rotZ);

should be

shipPosition = Vector2.Transform(shipPosition, comboMatrix);

The concept of: -translation, rotation, +translation. is a mechanism to cause something to rotate or spin in place. But you are applying it to a point (a vector2). There is little use having a point spin in place. What I believe you really want is for the ship sprite to rotate in place. This is typically done by altering the shipRotation variable which is a float describing the amount of angular difference (from 0) that you want the sprite to be rotated.

For some reason you confused the rotation of a point (shipPosition) for the rotation of the ship object...

In 2d, although the math in matrices works as well as it does in 3d, the spritebatch.Draw() method uses a single float to describe rotation and that does not directly relate to the rotation data generated by a Matrix.

The funny thing is, it is good to use Matrices in 2d to transform points and many people don't understand that. Here, you are trying to understand it but really want it to act on an object other than a point. So, don't give up on Matrices. But simply change the rotation value inside the Draw call to rotate the sprite in place.

Now if I've miss interpreted your goal, pleas let me know and I'll try to help further.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!