Is there a way that I could basically develop my XNA game at 1080p (or 720p) as my default resolution and then depending upon the set resolution just scale everything in the game to the proper size, without having to set the scaling factor in every Sprite Draw() method?
My thought is that, I could develop all the graphics, configure coordinates, etc based on a resolution of 1080p but then for the XBOX just set the res to 720p and scale down (so that the XBOX sees everything as being at 720 and therefore handles all resolutions as mentioned in the developer docs) and on PC scale to any needed resolution or aspect ratio by automatically letterboxing the view for resolutions that are not 16:9.
I already had my game setup so that spritebatch.begin() and end() were called at the highest level, around all the other Draw calls, so that I could technically just pass in the scaling matrix there, but whenever I do that it will do something weird like make the view off center, or only take up a quarter of the screen.
Is there a best practice way for achieving this?
If you set a scaling matrix in SpriteBatch.Begin, then it will scale the sizes and positions of every single sprite you draw, with that SpriteBatch, up until you call End.
SpriteBatch uses a client space where zero is the upper left corner of the Viewport, and one unit in that space is equivalent to one pixel in the viewport.
When you give SpriteBatch a transformation, the sprites that you draw will have that transformation applied to them for you, before they are drawn. So you can (and should) use this same technique to translate your scene (to centre it on your player, for example).
For Example:
Your game is developed at 720p and you're using SpriteBatch without a transformation. You have a sprite centred at the bottom right corner. Let's say its texture is (32, 32) pixels and the sprite's origin is (16, 16) (origin is specified in texture space, so this is the centre of the sprite). The sprite's position is (1280, 720). The sprite's scale is 1, which makes its resulting size (32, 32). You will see the top left quarter of the sprite at the bottom-right corner of your screen.
Now you move to a screen that is 1080p (1.5 times bigger than 720p). If you don't add a scaling matrix to SpriteBatch, you can see the whole sprite, with its at two-thirds of the screen, rightwards and downwards.
But you want to scale up your whole scene so that at 1080p it looks just like it did at 720p. So you add the matrix Matrix.CreateScale(1.5f, 1.5f, 1f) (note using 1 for Z axis, because this is 2D not 3D) to your SpriteBatch.Begin, and do nothing else.
Now your scene of sprites will be scaled 1.5 times bigger. Without making any changes to the actual Draw call, your sprite will be drawn at position (1920, 1080) (the bottom right corner of the screen), its size will be (48, 48) (1.5 times bigger), and its origin will still be the centre. You will see the sprite's top-left quadrant at the bottom-right corner of your screen, just like you did at 720p, and at the same relative size.
Related
I need some advice regarding the UI Menu in my game. So, I've created several canvases on a scene and set it all to world space. The idea is that the camera should move around the scene with several canvases representing different menu sections (main, options, new game, etc.). Now I've started to adjust the elements according to the resolution set in settings.
Now it does the following: when the game starts it looks for the current resolution and scales all objects according to this resolution by scale ratio (currentResolution/defaultResolution). And it scales fine and looks fine as well.
The problem is with the camera. The idea is to set the camera to focus on the centre of a canvas and hold a certain distance by Z. What I did is I've taken the canvas height (i.e. 720 as in currentResolution (1280x720)) and devided it by two and set Z position to be 1280/2 as well it as Y position of the mainCamera.
The problem is with Z position. It works well with 16:9 aspect ratio but when I change it to, say, 5:4 this Screen.width/2 thing doesn't work correctly. The camera gets too close to the canvas and cuts out some elements and other parts of the UI. How do I set the camera Z position right for every resolution? Or is my approach entirely incorrect?
P.S. I've watched this Unity video on adjustung UI menu to all resolutions but this technique doesn't apply in my case since I have a wrold space menu which is a bit different. The only problem now is this Z position of the camera.
I'm developing a little game where I generate rooms of different size and would like this randomly generated room to be always visible on the screen without caring about it's size. The camera is on a top view angle (rotation = 90,0,0).
I tried to create a relationship between it's size and the Y axis position of the camera to make it always visible but it wasn't successful. There is the solution where the object is kept on the bottom left corner of the screen but if the object is too big only a part of it is visible by the camera. I really have no more idea ^^
Thank you for your help !
I guess you are using an Orthographic camera. For the Orthographic Camera, the size is the number of unity units from the center of the camera to the top/bottom of the screen. The width is then based on the aspect ratio. So, if you know how big the objects are that should be easy!
You can get or set the main camera size with Camera.main.orthographicSize
then get/set the aspect ratio (width/height) with Camera.main.aspect
and you can reset it after with Camera.main.ResetAspect();
I have a 2D unity project.
I cannot depend on OnMouseExit because overlapping 2D box colliders cause the method to trigger even when the mouse is inside the bounds, since something else is in front (which is not my intention).
I was going to manually check for the mouse exiting on every frame by using:
if(!_collider.bounds.contains(Input.MousePosition))
But this does not work because `mouse position' is in terms of the number of pixels across the screen, and 'bounds' is in terms of "units" relative to the origin of the scene. The camera is Orthographic and slides around to look at the 2D plane that the world's sprites sit on. I have no idea how many "units" fit across the screen and suspect that it would change as soon as you change the aspect ratio or screen size.
You can use ScreenToWorldPoint(), to convert from screen point to 3D/2D point based on the camera's viewport, something like this:
if(!_collider.bounds.contains(Camera.main.ScreenToWorldPoint(Input.MousePosition)))
I am trying to segment arms from a Kinect depth image in my app (click for larger picture):
I tried using joint positions to get the vector between elbow and wrist/hand-tip, and created a 2D bounding rotated rectangle between these two joints, and then removed all pixels outside the rectangle. The problem is that, depending on the distance from the sensor, this rectangle changes width, and can become trapezoidal (e.g. if hand is closer to the camera), so it can basically only allow me to discard parts of the image before doing actual processing.
When the hand is near the body (like my left arm below), I need to detect the edge of the hand - presumably by checking the depth gradient. But I couldn't find a flood fill algorithm which "stops" at gradients.
Is there a better approach perhaps? I could use an algorithm idea.
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.