Im making a 2D game where the player controls a tank.
I can make the tank, and all, but whats really messing with my mind is how to make it rotate accordingly.
I want it to behave just like the Wii game, Tanks.
Fixed directions, and with no real front and back on the tank.
Driving up, then left should make it rotate to the left.
Driving up, then down should not make it rotate, just drive the other direction.
I red a tutorial a while back about some way to do that by dividing the degrees into 2 180 degree parts. But i have simply not been able to find that damn site again.
I hope you guys are able to understand what im trying to say.
Thanks in advance :)
I assume you're drawing your tank as a sprite? In that case there's an overload of the SpriteBatch.Draw method that allow you to specify the rotation angle around the origin.
SpriteBatch.Draw overload
Here's an example on how to use it from MSDN
The example above will keep rotating your sprite, so you will need to add some custom logic so it will only rotate it according to keyboard input. Here's a simple example on how to check for keyboard input. So add logic that checks if the right or left button has been pressed, and update the rotation angle if they have. If it's the up or down button that has been pressed you simply modify the position of your sprite.
I hope it makes sense, otherwise just let me know.
I think what you're looking for is simply the best way to minimize the rotation of the tank, modulo 180 degrees.
I would use the angle between the desired movement direction and the tank's current direction to start. Make sure this is the minimum angle, then compare that with the angle between the tank's current direction + 180 degrees. Something like:
// smallest angle between the current direction and the desired direction
minAngle1 = Math.Abs(Math.Min(tankAngle - desiredAngle, desiredAngle - tankAngle));
// smallest angle between the opposite direction and the desired direction
oppositeAngle = (tankAngle + 180) % 360;
minAngle2 = Math.Abs(Math.Min(oppositeAngle - desiredAngle, desiredAngle - oppositeAngle));
// get the smaller of two to rotate to
if (minAngle1 < minAngle2) {
// we know that we should rotate the current direction to the desired direction
} else {
// rotate the opposing direction to the desired direction
}
Note you'll need to play with your rotation signs to ensure you're rotating the right way. Also, I've assumed you know your rotation angles, if you have vectors you can simplify this a little bit by using the dot product between the two vectors instead of the angle for comparisons.
Is your problem with the direction of movement based on the angle they have rotated?
Vector2 moveDir = new Vector2(Math.Cos(rotation), Math.Sin(rotation));
position += (moveDir * speed);
Speed here would be a number for how fast you want to move in that direction. position is another Vector2 for the position of the sprite. As Tchami says you can draw it with the rotation using the SpriteBatch.Draw overload. Rotation for the the Cos and Sin methods should be in radians but I think Draw should be in degrees if I remember correctly. MathHelper.ToRadians(degrees) and MathHelper.ToDegrees(radians) should solve that.
There is lots of XNA tutorials and examples on the site http://creators.xna.com/en-US/education/catalog/
Related
i am creating a 3d top down shooter with unity and wanted to create an aim assist for it since hitting enemies is difficult. my idea was to create a trigger that slows down the rotation of the joystick on the weapon when the player aims at an enemy. i implement my rotation as follows:
float eulerY = (Mathf.Atan2(_JoystickShoot.Direction.x, _JoystickShoot.Direction.y) * 180 / Mathf.PI);
However, I don't know how to implement the slowdown now. The player should rotate slower than the actual rotation of the joystick.
My approaches have not really been successful so far.
does anyone have any idea?
thanks :)
You can add a variable that scales the rotation. Set it to 1, except when you're pointing at an enemy, where you set it to a value between 0 and 1 that feels good for you.
float eulerY = rotationScaling * (Mathf.Atan2(_JoystickShoot.Direction.x, _JoystickShoot.Direction.y) * 180 / Mathf.PI);
If you want to draw the crosshair towards an enemy, you can calculate the angle (or distance) to the closest enemy. If it is below a certain threshold you can adjust your rotation function to favor rotations towards the enemy over rotations away from it. You can use something like this:
float eulerY = (Mathf.Atan2(_JoystickShoot.Direction.x, _JoystickShoot.Direction.y) * 180 / Mathf.PI);
if (closest enemy is within threshold range)
if (eulerY * (difference in Y angle to closest enemy) < 0) // if we rotate away from the enemy we scale the rotation down
eulerY *= 0.5;
else // if we rotate towards the enemy we scale it up
eulerY *= 1.5;
You can adjust this for multiple angles as well, but just doing the same calculation for X and Y direction might feel a bit awkward. The reason is that in that case you have to compare it against the "true" angle/distance, not against the X and Y angles/distances individually.
I think it is more useful to talk about 'direction' rather than 'rotation'.
Presumably your ship travels and/or shoots in the same direction as the joystick is pointing in. This is a natural and intuitive relationship. "slowing down rotation" will most likely break this, making your interface less intuitive to use. There are also usually ways to go directly from a direction-vector to a rotation, for example Quaternion.LookRotation, avoiding the need to deal angles directly.
You could instead check if there is any enemy within a small arc, select the enemy closest to the center of the arc, and use the direction towards that enemy to fire in. Note that this can fail if enemies are moving and shots are slow, since it can prevent 'leading' your shots.
Other alternatives could be to simply make your enemies easier to hit. Make the enemies or shots larger, or possibly, just make the hitboxes larger. Or increase fire-rate and/or dispersion.
I have an image to be rotated in a pivot point(top) through animation. I am able to rotate it in anti-clockwise direction by simply changing the z-rotation value. But I want to rotate an image in clockwise direction.
If I put a z-rotation value -45 degree, unity converts it to 315 degree and rotates an image in anti-clockwise direction.
The image to be rotated has pivot point at top as shown in the figure below.
You could lerp the angle (single float) instaed of the entire rotation. Lerp from your min angle to max angle and just directly set ,rotation = Quaternion.Euler(0,angle,0).
There shouldn't be any issue with wrapping from 0 to 360; those are the same rotation (and so are 720 and -360, etc).
(you can't force slerp to go a different direction; it's wired to take the shortest route, just like lerp is (though, understandably, it's harder to tell with lerp))
maybe this code help :
needleHub.transform.localRotation = Quaternion.Euler(0, 0, Mathf.LerpAngle(90f, -90f, lerpFactor));
Try changing the interpolation type. I remember having almost the exact same problem and fixing it by changing the interpolation to something other than Eulers Angles.
Thanks #UriPopov for your reference. Finally I am able to rotate an image in clockwise direction through animation. I change the rotation to EulerAngles(Quaternion) as said by UriPopov. But main point to be remember during this animation is that each animation frame should be considered. If one frame is placed empty, then the animation will be in anti-clockwise direction.
Hey guys how do I find the rotation of the phone with Google Cardboard SDK in Unity3D, like the way the persons head is facing? I need to find if it is facing more towards the east, the west, or the north. Do I find the rotation of the head, or the parent Main camera?
The Cardboard class contains a property called HeadRotation which is a Quaternion.
Quaternion crtRot = youCardboardController.HeadRotation;
To use its rotation like you'd in Unity with directional vectors you may simply multiply it by Vector3.forward.
Vector3 lookDir = crtRot * Vector3.forward;
Visualizing the vector in editor might help narrow down issues
void Update () {
// ..
Debug.DrawRay( pos, lookDir * 100, Color.blue );
// ..
}
From here you only need to know where North is, in meaning of the facing vector. Do a Vector3.Angle() and you have the angle between your avatar's and North's vector. You might want to evaluate both vectors with their y axes set to 0.
You could also use Vector3.Dot() (the dot product) to determine how much both vectors look into the same direction.
I had an issue with HeadPosition, which wasn't updated properly. So if you operate from HeadPosition keep in mind it may stick to 0,0,0 .
Take Head.transform.rotation - that's the orientation of the user's head.
I'm not really sure what do you mean by North or West. If the mobile device has a magnetometer, then maybe you could read it's data to determine where North is, but I've never done that
It would be the rotation of the Head object, although the Main Camera usually has the same rotation.
But if you want the direction relative to the real world, that information is not available in the SDK. The compass cannot be used because of the magnet, so there is no way to get the real direction.
Just take the rotation angle of the main camera in the scene. It will gives you the head rotation angles with respect to x, y and z axis.
In GVR based VR scenes the system is internally rotating the camera with respect to our head movements. So it's easy to get the head rotation using main camera rotation angles.
For that,
//local rotation of the Transform of the camera
Camera.main.transform.localEulerAngles.y
//The world Y rotation
Camera.main.transform.rotation.y
So I need some help with my C# XNA top-down 2D "wave spawn" game. Basically, I have a player that has the functionality of shooting a laser at enemies that spawn in waves. The problem that I'm looking at fixing right now is my enemy collision code with a stationary non-rotated wall (rectangle)
I need to detect which side the enemy hits the rectangle on so he can properly get around the rectangle and to the player. (Example: if the enemy is blocked from the right side of the wall, move up the wall until he can get around the wall)
Here is the code I have to detect the angle between the enemy and the stationary wall when collided:
// I am blocked, find angle to find which side I'm blocked from
centerOfWall = wall.CenterOfWall;
Vector2 difference = centerOfWall - centerOfEnemy;
// Getting the angle of intersection between the two rectangles!
angle = Math.Atan2(difference.X, difference.Y);
// Converting angle to degrees!
degrees = angle * (180 / MathHelper.Pi);
I guess what I'm asking is, with this angle, can I find the side at which the enemy hits the wall? Like if the angle is less than 90 degrees but greater than 0 degrees I will be hitting from the Left or something like that.
If this doesn't work, can someone help me in finding another way that would work?
Thanks,
Johan
I am making a game, using a onscreen/virtual joystick. The joystick it self works fine.
What I want is when you turn the joystick, a bullet is fired in that direction. I got that working too. Now the problems arises when shooting a bullet when the joystick is not at the edge/radius.
When the joystick is at the edge/radius, the bullet move at maximum speed, exactly what I want. But when the joystick is, lets say, somewhere between the radius and the center of the joystick, the bullets move slower. This is logical because of the radians and stuff.
But it is not what I want. What should happen is that the bullets always move at the maximum speed.
Does anyone know how this could be achieved? I am completely stuck at this.
Thanks!
EDIT: since I still dont understand this at all, basically what I want is that I have a point in radians within a circle and I want to get the position of that point at the edge of the circle.
So let's say I have this Vector2 in radians.
Vector2(-0.3, 0.3);
and the radius of the circle is 40.
The length from the center of the circle to the Vector2 point would propably be somewhere around
radius = 40 * 0.3 = 12
Now what would the Vector2 point be when the length is 40?
I can't seems to figure this out. Trigonometry is definetely not my strongest point.
I fixed it! I just multiplied to localPosition of the joystick with a very large number, so that the localPosition woul fall outside of the radius. Then I just use clampMagnitude to get it at the edge of the radius. Now I get the correct behaviour.