Hello Stack Overflow users, I have a fun problem that I have in my XNA Game.
So basically I have an asteroid, 80x80, and I set the origin as imageW / 2, imageH / 2 (If order would matter, it wouldn't, the asteroid is a square).
Here is an image, explaining the problem! Visualization FTW :D
http://i.imgur.com/dsawS.png
So, any ideas on what is causing this? I spend 1 hour, I looked at examples, I found out it is supposed to rotate like this:
http://www.riemers.net/images/Tutorials/XNA/Csharp/Series2D/rotation.jpg
But it's not.
Here is a code sample. I have a object named Drawable that has properties which hold the vector position, etc.
Vector2 asteroidOrigin = new Vector2(asteroidImgs[asteroid.asteroidType].Width / 2, asteroidImgs[asteroid.asteroidType].Height / 2);
drawableList.Add(new Drawable(asteroidImgs[asteroid.asteroidType], asteroid.asteroidPos, asteroid.angle, asteroidOrigin));
Here is the Draw Method:
foreach (Drawable drawable in renderManager.getRenderList)
{
spriteBatch.Draw(drawable.image, drawable.position, drawable.sourceRectangle, drawable.tint, drawable.angle, drawable.origin, drawable.imageScale, drawable.spriteEffects, drawable.depth);
}
And yes, the Drawable Class has multiple constructors and they assign default values.
When you define an Origin in SpriteBatch.Draw, you are defining the new point on your texture which will draw at the Position argument. Obviously this affects translation as well as your desired rotation. When you set the origin to the center of the image, the image is translated so that the center is at your Position, then rotated around that point. When you set the origin to Vector2.Zero, the translation is not changed, but the image rotates around its top left corner.
The solution is to either redefine what you mean as "Position" for sprites to be where the CENTER of the image draws on screen (I recommend this, makes things nice) or perform a bit of work before drawing by adding the Origin to the Position before calling Draw.
I, again, recommend the first solution, because then when you want to draw a circle in the center of the screen you can just set its position to be the center of the screen and be done. You won't need to take its size into account. And so on.
Related
I'm working on an RTS game with some pretty extensive UI, so I moved the main camera's output to a quad which only makes up about half the screen, and I'm blitting some UI effects over the rest. My current way of interacting with the game uses unity's Input.mousePosition. When I moved the camera's feed to the quad, obviously those pixel coordinates were distorted, so I fixed them like this:
mapMousePos = (Input.mousePosition * mscaleCorr - mapCorrection * mscaleCorr);
mapCorrection being the pixel offset of the smaller feed, and mscaleCorr being a magic number that got through trial and error — a temporary fix.
Point is, now I'm realizing that running this game at a different resolution will almost certainly break these magic numbers.
What I want mapMousePos to be is what Input.mousePosition was before I moved the gameplay to the small quad - going from (0,0) in the bottom left of the quad to the screen (width, height) in the top right of the quad. This is just so it works with screenToWorld point really nicely on my gameplay camera.
I have the camera-feed quad parented to a full-screen quad, and tried using their relative positions to apply the necessary transformations, but it didn't work, I'm guessing because it's a pixel problem.
I've dug around the docs for a solution using Camera's builtin worldToScreenPoint function, without any luck. I'm sure I'll bump into a fix eventually, but would greatly appreciate any pointers.
Here's what I've come up with; it's stupid, but it works.
I've placed objects at the bottom left and top right of the quad, stored in code as bL and tR.
Then I convert the mousePosition to a worldPosition using ScreenToWorldPoint(), remap it by subtracting the bottom left position, and get it as a percentage across the screen by dividing it by the delta to the top right. Multiply the percentage by the pixel dimensions of the gameplay camera, and voila.
In code, this:
Vector3 wPos = finalcam.ScreenToWorldPoint(Input.mousePosition);
wPos -= bL.transform.position;
mapMousePos = new Vector2(Mathf.Abs(wPos.x), Mathf.Abs(wPos.y));
mapMousePos = new Vector2(
mapMousePos.x / (tR.transform.position.x -bL.transform.position.x),
mapMousePos.y / (tR.transform.position.y - bL.transform.position.y));
mapMousePos = new Vector2(mapMousePos.x * Camera.main.pixelWidth, mapMousePos.y * Camera.main.pixelHeight);
Again, it's dumb, but it seems to work. I'm leaving this up in case anybody knows a cleaner method.
How do I rotate a Drawable in android?
I have a class that inherits from Drawable and overrides the Draw(canvas) method in order to create an arrow head that I need to place on a line and rotate it to match the slope of the line.
I cannot figure out how to rotate the Drawable; everything I've seen on this has been how to rotate a Bitmap, not a Drawable.
I have tried rotating the canvas first but that causes odd results.
Any suggestions?
The last thing I have tried that I have seen a lot of people discuss is this:
how to rotate a bitmap 90 degrees
So I figured it out. It seems there is a pretty specific way you must rotate the canvas in order to rotate a drawable on it:
canvas.Save(SaveFlags.Matrix);
canvas.Rotate(_degrees, _location.X, _location.Y);
canvas.DrawPath(path, _paint);
canvas.Restore();
So basically, you save the canvas' current state, rotate it (here, I'm using _location which holds a point in which the user lifted their finger from the screen), then draw on the rotated canvas and then restore it to it's previous state (with the drawable drawn still drawn).
I'm trying to render to texture using FBO using OpenTK in C#.
When I try to render, everything show up and just fine except the texture is shown on bottom-left corner, I'm expecting it shown on the top left corner.
Also the Texture appear flipped in Y axis, So I need to modify the Texture Matrix after binding the Texture Target.
If I just bind my texture and draw the vertices, the sprite will appear on top-left corner.
The codes I use is looks exactly same from the official documentation.
I got 2 questions:
1. Am I doing it right to make the target texture show up properly by modifying the Texture Matrix?
2. How to make the texture target appear on top left corner?
Thanks in advance!
Actually Origin is at Bottom Left , therefore the FBO is getting displayed in the Bottom Left.
In the normal images , the texture space 0,0 is at top therefore you don't see it flipped.
So you have to add the texture matrix to make the space same.
When I try to render, everything show up and just fine except the texture is shown on bottom-left corner,
Yes. In OpenGL the origin (0,0) of 2D images (the viewport, textures, render buffers) is in the lower left.
I'm expecting it shown on the top left corner.
Why? The origin (as far as OpenGL is concerned) is in the lower left. Why'd you expect it in the top?
I encountered similar problems when the first time I tried FBO, so here my answer:
Although there several ways to workaround against this Upside down problem, Modifying Texture Matrix isn't bad idea at all. Sometimes modifying Texture matrix could be handy in certain situation, e.g: Use non normalized texture coordinate, So you can add such features to your bind texture function.
It's seems projection / viewport issue, if you are sure that the normal sprite appear on top-left coordinate, try to re-setup your projection / view / camera before unbind the FBO handle.
Currently, all my textures are being scaled and move into the right position when the viewport that I draw them in changes size or position (I don't have to do any calculations myself to do this).
However, when I use DrawString() (while still in the same viewport), and the viewport changes size or position, the text follows no logic that I can figure out. It scales as expected, but it moves in a very weird way.
Here's
(to get the main player's name to move correctly when scaling down, I came up with this bad "formula": X -= Viewport.X / 2.15f. Y -= Viewport.X / 3.2f)
Now, is there any way to make DrawString() work like Draw() does when it comes to scaling with viewports?
The way I've got it set up now is:
_spriteBatch.GraphicsDevice.Viewport = ScreenGame.Viewport;
// Draw tile sprites
// Draw player sprites
// Draw text
My apologies in advance if I've forgotten to mention something relevant.
On the DrawString() try
x /= Scale.X;
y /= Scale.Y;
This is of course pseudo code. I think if you can find the new scale and store it in a struct or something, you can do this to scale the text's location properly.
this site has been really amazing for helping me with game development however I'm unable to find an answer for the following question (nor am I able to solve it on my own).
I am trying to do rectangle collision in my game. My idea is to 1) get the original collision bounding rectangle 2) Transform the texture (pos/rot/scale) 3) Factor changes of item into a matrix and then use this matrix to change the original collision bounds of the item.
However, my textures contain a lot of transparency, transparency that affect the overall height/width of the texture (I do this to maintain power of two dimensions).
My problem: How to create a rectangle that forms dimensions which ignore transparency around the object. A picture is provided below:
I guess you could step through each row of pixels in the bounding rectangle, starting from the top, checking when you first hit a pixel with colour by checking its alpha value (Color.A != 0).
That way you'll get Y coordinate of the rectangle.
Then step through each column starting from the left of the bounding rectangle, looking for the first coloured pixel.
You'll get the X this way.
Then step through each row again but starting from the bottom and you'll get the height.
Then step through each column again but starting from the right and you'll get the width.
Hope that helps
I think dois answer is the way to do it. I use the following code to find the pixel value at a specific point inside my texture. You can change this code to get line by line the pixels, check for transparency and stop when you find a line with a pixel which is not transparent.
Color[] colorData = new Color[1];
Texture2D texture = //Get your Texture2D here
texture.GetData<Color>(0, new Rectangle(targetPoint.X, targetPoint.Y, 1, 1), colorData, 0, 1);
To check if pixel is not transparent I do this :
if(colorData[0].A > 0)
I don't know how expensive can this operation be for collision detection though.
I know for my games, I use circles. If your objects are reasonably round, it can often provide a closer estimate AND collision detection is dead easy. If the distance between the centres of the objects is less than the sum of the radii, then they are colliding.
If circles are out of the question, then muku or Dois have provided decent answers.