How to scale a sprite(2D) using a matrix - c#

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);

Related

2D Depth System Method XNA C#

I am creating a 2D Top-Down RPG game like the Legend of Zelda: A link to the past.
when the player is drawn i want to update the tree depth so that it is over and under the player when the player Y position is higher or lower than the trees Y position, i think whether the tree is on top or not should be decided by the players Y position, being lower or higher. is it possible to do this in this way? can i change the layer depth in the update method?
I'm not sure you can. i'm not very experienced when coding. If there's a right way of doing this even without useing the spriteBatch layer depth i would appreciate any help.
I have discovered how to use the layer depth in the
spriteBatch.Draw();
Method.
What i am attempting to do is shown in the images below
The code i am using to separate trees from grass tiles uses layer depth like below:
spriteBatch.Begin(SpriteSortMode.FrontToBack, blendState = null, samplerState = null, DepthStencilState.DepthRead);
spriteBatch.Draw(tree, treePos, null, null, Vector2.Zero, 0, null, Color.White, SpriteEffects.None, 0.6f);
spriteBatch.End();
Tile draw method for the
tile
has the float value set
0.5f
Here's a way to do it:
Slice your sprites and do tile-based rendering, starting from the ground up to the sky.
Say you have a tile grid whose each is 32*32 pixels, if you have a tree that is 32*96 pixels, then when sliced it will be like:
A // layer 2
A // layer 1
A // layer 0 (floor)
Logic:
draw all tiles on floor 0
draw all tiles on floor 1
etc ...
Then obviously the part that should hide your player will be drawn correctly (before, if player is behind).
(note that the lowest tile of the tree should not be walk-able)

How do I apply multiple matrices in spriteBatch.Draw()?

I'm making a game in C# and XNA 4.0. In some levels I need a camera matrix to make the level appear to scroll left/right. Additionally, I also need a scaling matrix to scale the graphics when the settings are used to change the window size. Both of my matrices are functional, but I'm currently calling them in the draw method like this:
if (scrollingLevel)
{
//Use the camera matrix to make the stage scroll
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, camera.transform);
}
else
{
//Use the scaling matrix to scale the graphics
spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, transform);
}
What I want is to apply both matrices at the same time if it is a scrolling level (scale the graphics based on the window size and then use the camera matrix to make the level scroll). However, simply adding and multiplying the matrices does not produce an accurate result (adding prevents the graphics from scaling to the exact amount that they should and multiplying makes the camera scroll inaccurately). How can I apply both of the matrices at once?
Simply multiply the matrices before passing to spriteBatch.Begin.
Matrix multiplication allows the effects of both matrices appended into a single matrix. Note that this operation is not commutative, meaning that A * B != B * A.
In your case, you should probably multiply scaling matrix with the camera matrix.

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.

Render isometric text in 2D

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.

Generating one Texture2D from multiple Texture2Ds

My problem is the I need to represent a length-changing floor using a Texture2D, which means a floor that the sides has the image of the sides, and in the middle it repeats the same 'middle' image, like so:
To achieve this, I get the 'left edge', the 'middle' and the 'right edge' textures, problem is I don't know how to merge them into one single texture2D,
It is important to do that at run-time because the floor length is changing (horizontally),
I read you can do that using SetData but I have no idea how...
It is very important for me that it will act as one texture and not multiple texture parts because I am using Farseer Physics Engine to move the floor and use it.
I am using C# and XNA with Visual Studio 2010, I am an almost-experienced C# programmer,
Thank you!
This answer may help you. Either you should use HLSL for repeating your floor or you should draw your floor on a RenderTarget and save it as single Texture. Enjoy.
First, create a new Texture2D to serve as your floor texture, specifying the appropriate width and height. Then, get the data of the three textures you want to merge, using the GetData method. Finally, use the SetData method to set the data of the new texture as appropriate (check the link, you can specify the start index).
Warning: GetData and SetData methods are slow. If you need to create this texture only once per game (at the initialization for example), it's not a problem, though.
You are using farseer... but it does not prohibit you to use a tiling approach...
I don't know farseer, but I suppose that it provide a transform matrix...
do:
Vector2 pos = Vector2.Zero;
spriteBatch.Begin(...,....,...,..., Transform);
spriteBatch.Draw(LeftTexture, pos, null, Color.White);
pos.X += LeftTexture.Width;
for (int i=0; i<floor_repeats; i++)
{
spriteBatch.Draw(MidleTexture, pos , null, Color.White);
pos.X += MiddleTexture.Width;
}
spriteBatch.Draw(RightTexture, pos , null, Color.White);

Categories

Resources