How to make 3D Viewport within that 3D viewport square
You can use the Normalized Viewport Rectangles' approach, achieved by editing the Viewport Rect of the Camera.
The Documentation explains an example of split screen for a two-player game. You can adapt the explanation having the game in a particular area, and the GUI in the other screen space.
Normalized Viewport Rectangles
Normalized Viewport Rectangle is specifically for defining a certain
portion of the screen that the current camera view will be drawn upon.
You can put a map view in the lower-right hand corner of the screen,
or a missile-tip view in the upper-left corner. With a bit of design
work, you can use Viewport Rectangle to create some unique behaviors.
It’s easy to create a two-player split screen effect using Normalized
Viewport Rectangle. After you have created your two cameras, change
both camera’s H values to be 0.5 then set player one’s Y value to 0.5,
and player two’s Y value to 0. This will make player one’s camera
display from halfway up the screen to the top, and player two’s camera
start at the bottom and stop halfway up the screen.
Related
I'm using Unity 2020.1.17f.
To do align correction between VR lens and Display, I want to control size of screen, offset of screen, and rotation of screen(screen means area of display where actual game scene is appeared, my game has letter box in 4 ways).
I could control size and offset by changing values of Viewport Rect, but I cannot find a way to control rotation of screen. (Like Cv2.GetRotationMatrix2D() of openCV in C#)
You can say "why don't you rotate your camera?", but rotating camera is not what I want. As you know, in VR, Game screen is distorted in several shapes to optimize to their lens shape. Thus, even I rotate camera, it is not helpful for mis-align correction.
In Google, there are many answers, but only related with rotation of mobile phone, not controlling rotation in arbitrary angle(that what i really want).
How can control of rotation of game screen?
You need to go to Edit/PlayerSettings/Player
And open the section called resolution and presentation
as you see there is a section called default orientation and here you can set the orientation of the build just opened.
Down there is also a section called Allowed orientations for auto rotations where you can set the other rotations allowed. In my case, everything is allowed, but you can just set the 2 landscapes or the 2 portraits depending on your game and your canvas and camera orientation
I'm currently creating a drawing software using WPF Shapes on canvas.
I've created a system allowing the user to move and rotate shapes on a Canvas using a transparent canvas upon the shape (which rotate with the shape) :
The green point is used to rotate the shape, the blue zone upon the rectangle is used to move the shape. I'd like to use my 4 red points to re-size the shape.
But the shape is rotatable, so corners coordinates aren't completely relevant to resize the shape. It seems, in my opinion, to be relevant only if the rotation is equals to 0, because the Left-Top Corner can be the Bottom-Right one after a 180 degree rotation.
Right now I'm using a RotateTransform to achieve the rotation with a 0.5, 0.5 RenderTransformOrigin. I'd like to avoid the use of a ScaleTransform because I want to keep the StrokeThickness at the size it is.
All red dots are pseudo-draggable (using MouseDown, MouseMove, MouseUp events). I use a buffer point which gives me the delta in X and Y between two mouse events.
How can use the deltas to resize the shape, even if it is rotated or moved ?
You can use the deltas to resize the shape if it is rotated. The only thing you have to do is rotating the mousemovement either. As you can see:
The movement of the mouse from origin to location describes a 2-D-vector. You can rotate this vector mathematically by using this formula:
x' = cos(theta) * x - sin(theta) * y
y' = sin(theta) * x + cos(theta) * y
where x/y is the current location of the mouse relative to the origin of the resize and theta the angle of rotation which can be found in the RotateTransform-object (Angle-Property) of the shape. At this point I don't know exactly if you have to use -theta, because the vector has to rotate in the opposite direction.
You can pick x'/y' for calculating the deltas and resize the shape like if it wasn't rotated.
I did not implement this myself. This is just a general idea. Maybe I can serve with a little code if you try this and give feedback or specify the problem more deeply or update your question with some code.
Appendix:
Resizing the shape using the deltas should be easy if you can access the width- and height-property of the shape. You simply add/subtract the x-delta to/from width and/or add/subtract the y-delta to/from height, depending on the grabbed point. This isn't affected by the location of the shape within the canvas.
Maybe you have to adjust the Canvas.Left/Canvas.Top-Property of the shape. I.e. if the user grabs the left upper point and resizes it to left/up, you should subtract the deltas from left and top porperty as well. Otherwise it will expand to right/down.
To be honest I am quite lost with world, screen and viewport coordinates in Unity.
My question is rather simple: in a 2d game how do I place an object in bottom left corner no matter what the resolution and screen aspect ratio is?
It is a little vague your description, but I think your talking about this:
Vector3 screenPos = new Vector3(x,y,z);
camera.ScreenToWorldPoint(screenPos);
As a side note, there are specific algorithms for 2D Unity, search for that also.
For Orthographic check this unity space which might help you:
http://answers.unity3d.com/questions/501893/calculating-2d-camera-bounds.html
I see no one ever followed up on this. Let's get some terms straight first:
Camera.main = the main camera that is looking at your game world
"game world" = the entire game map you've drawn
World Point = an absolute, unique position in the game world. Can be 2D or 3D (x,y,z)
Screen Point = a 2D x,y location of a pixel on the screen
So, when you want to place an object (i.e.transform its location) what you are really doing is placing it somewhere within the Game World. If the camera happens to be looking at that location in the World then it will appear on screen.
To figure out what parts of the World are currently on screen, you must convert a Screen Point to a World Point. So...assuming your object's size is 20x20, try this:
//Attach this script to the item you want "pinned" to the bottom, left corner of the screen
void Update() {
//fetch the rectangle for the whole screen
Rect viewportRect = Camera.main.pixelRect; //again, this has nothing to do with the World, just the 2D screen "size", basically
//now, let's pick out a point on the screen - bottom, left corner - but leave room for the size of our 20x20 object
Vector3 newPos = new Vector3(viewportRect.xMin + 20, Camera.main.pixelHeight - 20, 0);
//now calculate where we need to place this item in the World so that it appears in our Camera's view (and, thus, the screen)
this.transform.position = Camera.main.ScreenToWorldPoint(newPos);
}
I'm 98% certain this is all accurate info but if someone sees a mistake please point it out.
Inside my project, I have a sprite being draw of a box. I have the camera zoom out when clicking a key. When I zoom out, I want my box to scale it's dimensions so it stays consistent even though the camera has zoomed out and "shrunk" it.
I have tried multiplying the object's dimensions by 10% which seems to be the viewpoint's adjustment when zooming out, but that doesn't seem to work. Now this may sound dumb, but would scaling the sprite in the draw function also change the sprite's dimensions?
Let's say the box is 64x64 pixels. I zoom out 10% and scale the sprite. Does the sprite still have the boundaries as 64x64 or is the up-scaling also changing it's dimensions?
Scaling using SpriteBatch.Draw()s scale argument will just draw the sprite smaller/bigger, i.e. a 64x64 one will appear as 7x7 pixels (the outer pixels being alpha blended if enabled). However there are no size properties on the sprite, if you have your own rectangle, position variables for the sprite SpriteBatch.Draw() of course will not change those.
An alternative is draw the sprite in 3D space then everything is scaled when you move your camera, so the sprite will appear smaller though it will still be a 64x64 sprite.
How to draw a sprite in 3D space? Here is a good tutorial http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2/Point_sprites.php. (You will need to take time to learn about using 3D viewports, camera's etc, see here: http://msdn.microsoft.com/en-us/library/bb197901.aspx)/
To change sprite dimensions you need to change Rectangle parameter for SpriteBatch.Draw. To calculate zoom on rectange:
Rectangle scaledRect = new Rectangle(originalRectangle.X, originalRectangle.Y, (int)(originalRectangle.Width*zoom), (int)(originalRectangle.Height*zoom)); // where zoom default is 1.0f
When drawing use:
spriteBatch.Draw(Texture, scaledRect, Color.White);
Now I'm sorry to assume it, but without knowing why you doing what you doing - I think you doing something wrong.
You should use camera transformation to zoom out/in. It is done like that:
var transform = Matrix.CreateTranslation(new Vector3(-Position.X, -Position.Y, 0))* // camera position
Matrix.CreateRotationZ(_rotation)* // camera rotation, default 0
Matrix.CreateScale(new Vector3(Zoom, Zoom, 1))* // Zoom default 1
Matrix.CreateTranslation(
new Vector3(
Device.Viewport.Width*0.5f,
Device.Viewport.Height*0.5f, 0)); // Device from DeviceManager, center camera to given position
SpriteBatch.Begin( // SpriteBatch variable
SpriteSortMode.BackToFront, // Sprite sort mode - not related
BlendState.NonPremultiplied, // BelndState - not related
null,
null,
null,
null,
transformation); // set camera tranformation
It will change how sprites are displayed inside sprite batch, however - now you also must account for different mouse coordinates (if you using mouse input). To do that you must transform mouse position to transformed world matrix:
// mouse position, your tranformation matrix
public Vector2 ViewToWorld(Vector2 pos, Matrix transform)
{
return Vector2.Transform(pos, Matrix.Invert(transform));
}
I used the code without direct access to test it, so if something will not work - feel free to ask.
This is not answer to your question directly, if you could provide reason why you want re-size sprite when zooming instead of zooming camera - maybe I could better answer your question, also you should fallow markmnl link to understand world transformations and why you seem to need it in this situation.
What I'm actually trying to do, is to get the mouse coordinates inside a windowed game. So far, I've only found ways to retrieve the screen coordinates of the mouse. Therefore, I would like to know the position of the window, so that I can subtract that from the mouse's screen coordinates in order to get the mouse's window coordinates.
Is this possible, and if so, how?
Have you tried Mouse.GetState? It returns a MouseState with X and Y properties on it. The documentation on MSDN is pretty sparse, but if you look carefully at documentation for the specific X and Y properties you'll see that it returns a position relative to the upper left corner of the window which is more in line with what your after.
MouseState.X - Horizontal position of the mouse cursor in relation to the upper-left corner of the game window.
MouseState.Y - Vertical position of the mouse cursor in relation to the upper-left corner of the game window.
The advantage of doing this way is that it's not platform specific, so if you port your game to another platform in the future, the code won't have to change.