Render isometric text in 2D - c#

How can I render text in the form of an isometric projection? I understand the principle but I'm not sure how to actually transform a SpriteFont programmatically to do this.
Example of what I mean:
I'm not even sure what I should be searching for. It seems I could accomplish this by using an isometric projection matrix and a 3D mesh font, but that seems overcomplicated considering I'm working in 2D.
Any ideas?

SpriteBatch.Begin takes a Matrix parameter, transforming the sprites you draw (including SpriteFont) onto whichever plane you desire.
Unfortunately Matrix does not provide Create* methods for creating skew matrices. But it is simple enough to create such a matrix by hand. The following piece of code is tested and is pretty close to what you want:
Matrix skew = Matrix.Identity;
skew.M12 = (float)Math.Tan(MathHelper.ToRadians(36.87f));
Matrix rotate = Matrix.CreateRotationZ(MathHelper.ToRadians(270+26.565f));
sb.Begin(SpriteSortMode.Deferred, null, null, null, null, null, skew * rotate);
// ... draw your sprites here ...
sb.End();
The only difference to your diagram is that Y and Y' point in the opposite direction, because XNA's SpriteBatch works in "client" coordinates ((0,0) at top left, and Y+ is down).

You can use a matrix transformation together with a sprite batch to achieve this. You can read more about matrix translation here.

Related

Drawing a specific region of a 3D scene to a larger canvas/viewport

I have a 3D scene of which I want to draw a specific region onto a larger canvas/viewport (think like a magnifying glass).
Something like the following image:
I want to maintain any perspective effects, simply moving my camera to the specified region wouldn't give that effect.
I gathered from http://www.mvps.org/DirectX/articles/tilerender/index.htm that it's possible to do some trickery with the Projection Matrix but I couldn't figure out the math behind getting a more specific subsection/region than what is described in that article.
If we assume the coordinates described in the article, x0y0 would be the exact center of the scene, x-1y1 would be the top-left and x1y-1 would be the bottom-right of the scene.
I would, for example, want to render the region ranging from x-0.75y0.75 to x-0.25y0.25.
I have a Projection matrix and a View matrix separately available. I am using the SharpDX library and my Projection matrix is Right-Handed(which seems the flip the y-coordinates described above).
How do I calculate the Scale/Translation matrices that I need to multiply my Projection matrix with? Or, alternatively, what other ways are there to tackle this issue?
Psuedo-code would be something like this:
public Matrix GetProjectionRegion(float topLeftX, float topLeftY, float bottomRightX, float bottomRightY)
{
var magicMatrix = Matrix.Identity;;
//some magic
return magicMatrix;
}
ProjectionMatrix *= GetProjectionRegion(-0.75f, 0.75f, -0.25f, 0.25f);
EDIT:
I am currently creating my Projection matrix using one of two methods:
ProjectionMatrix = Matrix.PerspectiveFovRH(FOV, Width / Height, NearPlane, FarPlane);
or
ProjectionMatrix = Matrix.OrthoOffCenterRH(_topLeft.X, _bottomRight.X, _topLeft.Y, _bottomRight.Y, NearPlane, FarPlane);
Nearplane is 75 farplane is 5000000; Width/Height/_topLeft/_topRight are all pixel formats as far as I remember.
The matrices are used Row-Major.
If you really want to do a very basic mechanism for zooming in, you could cheat with your camera matrix, that is the "World" in your world view projection matrix.
The zoom could be tackled through proximity to the location. Nothing more. BUT, if you are determined, you could also scale that World matrix also, which would then enlarge all objects, therefore effectively zoom.

How to scale a sprite(2D) using a matrix

I have a 2D tower defense game I'm making and I want my sprites to scale to the screen size. So someone suggested using a matrix. So I tried to use one but I don't really know how to use it and how it works. So, how would I create a matrix and use it to scale 2D sprites in monogame. Thank you!
you can scale SpriteBatch using matrix, could be used to zoom in/out to affect whole screen.
ScalingFactor = new Vector3(widthScaling, heightScaling, 1);
Scale = Matrix.CreateScale(ScalingFactor);
spriteBatch.Begin(SpriteSortMode.Immediate, null, null, null, null,null, Scale);

Get the bounds of the plane visible at a specific z coordinate

Using OpenTK, I've created a window (800x600) with a vertical FOV of 90°.
I want to make a 2D game with a background image that fits on the whole screen.
What I want is the plane at a variable z coordinate as a RectangleF.
Currently my code is:
var y = (float)(Math.Tan(Math.PI / 4) * z);
return new RectangleF(aspectRatio * -y, -y, 2 * aspectRatio * y, 2 * y);
The rectangle calculated by this is always a little to small, this effect seems to decrease with z increasing.
Hoping someone will find my mistake.
I want to make a 2D game with a background image that fits on the whole screen.
Then don't bother with perspective calculations. Just switch to an orthographic projection for drawing the background, disabling depth writes. Then switch to a perspective projection for the rest.
OpenGL is not a scene graph, it's a statefull drawing API. Make use of that fact.
To make a 2D game using OpenGL, you should use an orthographic projection, like this tutorial shows.
Then its simple to fill the screen with whatever image you want because you aren't dealing with perspective.
However, IF you were to insist on doing things the way you say, then you'd have to gluProject the 4 corners of your screen using the current modelview matrix and then draw a quad in 3D space with those corners. Even with this method, it is likely that the quad might not cover the entire screen sometimes due to floating point errors.

How to rotate a bounding box in XNA?

I'm trying to rotate a bounding box in xna, this is how I usually do it:
new Rectangle((int)position.X, (int)position.Y, (int)texture.Width, (int)texture.Height);
but It currently does not return the rotation that is in my draw code:
spriteBatch.Draw(texture, position, null, Color.White, rotation, origin, scale, SpriteEffects.None, 1f);
how do I rotate it with the player? I was trying to figure this out and stumbled across this:
2D BoundingRectangle rotation in XNA 4.0
but I'm not quite sure how to implement the Matrices he's talking about,and I'm making a 2d game as opposed to the 3d one here.
The Rectangle structure is an axis aligned bounding rectangle. The sides will always be parallel to the X and Y axes. If you want a rotated bounding rectangle you have to implement it yourself.
One algorithm for calculating collision of rotated rectangles is the Separating Axis Theorem.
Matrices are, as stated in the linked answer, essential in computer graphics. You can rotate a shape by rotating each of its vertices with the same rotation matrix. This is the general rotation matrix for two dimensions:
Matrices are then "applied" to vectors with matrix-vector multiplication:
which equals
I struggled with this problem for two days before finding the solution
Rotating bounding box
Hope this will help !

How to translate a sprite and a vertex geometry by the same distance?

I'm trying to build up a 2.5 engine with XNA. Basically, I want to display a 2D sprites (the main hero and other monsters) in a 3D background. The game will be a platform.
Now, using a translation matrix on a sprite doesn't yield the same result of translate a vertex geometry in world space.
I mean, if I apply
Matrix.CreateTranslation(new Vector3(viewportWidth / 2, viewportHeight / 2, 0));
the sprite will be translate at the middle of screen (starting from the display upper left origin). But, if I apply the same transform to a cube in world space, it will translate very far. This doesn't suprising me, but I wonder of to translate a sprite and a 3D object by the same distance, ignoring all the project/unproject coord stuffs.
Thanks!
There are traditionally three matrices: World, View and Project.
BasicEffect, and most other 3D Effects, simply have those matrices. You use Project to define how points are projected from the 3D world onto the 2D viewport ((-1,-1) in the bottom-left of the viewport to (1,1) in the top-right). You set View to move your camera around in world space. And you use World to move your models around in world space.
SpriteBatch is a bit different. It has an implicit Project matrix that causes your world space to match the viewport's client space ((0,0) in the top-left and (width,height) in the bottom-right). You can pass a transformMatrix matrix to Begin which you can generally think of like the View matrix. And then the parameters you pass to Draw (position, rotation, scale, etc) work like the World matrix would.
If you need to do "weird" things to your World or Project matrices in SpriteBatch, you can just build those transforms into your transformMatrix. It may just involve some maths to "undo" the built-in transformations.
In XNA 4 you can also use an Effect (like BasicEffect) directly in SpriteBatch, which you can provide with arbitrary matrices (details).

Categories

Resources