Hinge constraint: How to make body with mass = 1 be static and how to make body rotate an angle (e.g. 30 degrees) - cannon.js

In hinge official example: https://schteppe.github.io/cannon.js/demos/hinge.html
Please help me to make the body with mass = 1 become static (currently it is oscillating).
How can I rotate the body an angle, for e.g. 30 degrees.

Related

How to clamp a quaternion to stay within a certain angle of another

We have one head object and one body object.
These two objects are separate children of one person object.
I need to make the head object rotate freely left and right which I've done.
I also need to make the body object rotate left and right with the head object ONLY if the difference of rotation between the two quaternions is +/- 90 degrees.
In other words, I should be able to move the head freely left and right, if the difference of rotation between the head and body is less than or greater than 90 degrees, then the body will start rotating with the head and stop if the rotation is within +/- 90 degrees. The body's rotation should not snap to the head's rotation but instead make sure it stays inside an invisible 180 degree cone that the head can rotate.
While you could do something like this:
var rotation = Input.GetAxis("Mouse X") * speed * Time.deltaTime;
Head.transform.RotateAround(Vector3.up, rotation);
var angle = Quaternion.Angle(Head.transform.rotation, Body.transform.rotation);
Debug.Log(angle);
if(angle > 90)
{
Body.transform.RotateAround(Vector3.up, rotation);
}
It will also rotate when you look up or down past 90 degrees. So it might be better to have input modify the angles, clamp the body angle, and set them into the rotations.
var rotation = Input.GetAxis("Mouse X") * speed * Time.deltaTime;
headAngle = headAngle + rotation;
bodyAngle = Mathf.Clamp(bodyAngle, headAngle - 90, headAngle + 90);
Head.transform.rotation = Quaternion.AngleAxis(headAngle, Vector3.up);
Body.transform.rotation = Quaternion.AngleAxis(bodyAngle, Vector3.up);

UNITY3D How check direction vector of my camera?

I'm new in Unity. I've got game with FPS mode, camera rotate with mouse's moves and sun is the directional light. I must write script where I check if sun is in player's field of view. I thought that I can calculate angle between 2 vectors and then I decide if sun is visible. First vector is:
var playerSun = light.transform.position - camera.transform.position;
But I have problem with the second one... I don't know which variable I should use, camera.transform.forward is ALWAYS (0,0,1)...
Can you help me? I'll be very grateful.
Vector3 direction = light.position - player.position;
float dot = Vector3.Dot(direction.normalized, player.forward);
if(dot > 0) { Debug.Log("Sun is on the front"); }
dot product returns 1 when two vectors are aligned, 0 when they are 90 degrees and -1 when they are opposite.
The value is in radians so if you need a 90 degrees FOV, it would be 45 degrees (since 90 is 45 left and right) and that is appr. 0.7f.
if(dot > 0.7f) { Debug.Log("Sun is withing 90 degrees");}
There are several ways to achieve that, but I suggest usage of Raycast.
I suppose sun is more than just a dot, it has some area visible to the player, so even if he does not see sun` center point, he still can see some part of its area. If so, I recommend to add a new script to sun object just to identify it programmatically. Then make sure that it has collider component attached with the size approximately equal to sun.
Then in your script in which you want to detect sun visibility to the player you can do something like that:
var ray = Camera.main.ScreenPointToRay(pos);
RaycastHit hit;
if (!Physics.Raycast(ray, out hit, 100))
return false; //sun or any other collider wasnt hit
var objHit = hit.collider.gameObject.GetComponent<Sun>();
So objHit != null means that player can see any part of area that sun has.

unity3d - Clamp rotation value

I have an object that rotates according to mouse position, but I want to clamp it so it doesn't get further or lower than certain value. Here is my code:
void LookAt () {
float distance = transform.position.z - Camera.main.transform.position.z;
Vector3 position = new Vector3(Input.mousePosition.x, Input.mousePosition.y, distance);
position = Camera.main.ScreenToWorldPoint(position);
position.x = Mathf.Clamp(position.x, -70, 70);
position.z = Mathf.Clamp(position.z, -70, 70);
Vector3 target = new Vector3 (position.x, transform.position.y, position.z); // Use current object positin.y
transform.LookAt(target);
}
But unfortunately it doesn't work, it keeps rotating 360.
Edit:
This is a 3D top-down game, I have a tank and I want to rotate it's upper half. The code I wrote above works perfect for the job, but now I don't know how to limit it so the barrel( the part I'm rotating) always facing upwards where the enemies will come from. 70 or whatever are just random values I was testing, first I want to figure what exactly the proper code is, then determining the values is the easy part.
Actually, the problem is that you're clamping a position, not a rotation. You're having it look at a certain point, but limiting that point rather than the angle that it will need to rotate to meet it. You'll have to use trigonometry to calculate the angle it wants to point in (more specifically, the atan2 function), clamp that value to (-70, 70), and then apply that rotation to the object (using euler angles). Do you require further clarification on any of these steps?
Cheers.
P.S. Note that atan2 returns a value in radians, but your range and euler angles use degrees.
You limit your target position by 70 units in world space, which is usually a lot, but depends on your game scale. What I think you wanted to do is to limit mouse position by 70 pixels around the screen center. (Please, provide this remarks in the question itself, so we won't have to guess). However, because you used the same variable both for screen space and world space position of the target, you likely got confused and clamped the position after converting it to world space.
Also, you made the y coordinate of the target to be the same as the object. But this means that the object would have to rotate 360 degrees every time the target passed it. I assume that what you wanted to do instead is to assume that the target location is located on camera place.
void LookAt () {
var cursorPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, camera.main.nearClipPlane);
cursorPosition.x = Mathf.Clamp(position.x, -70, 70);
cursorPosition.z = Mathf.Clamp(position.z, -70, 70);
var targetPosition = Camera.main.ScreenToWorldPoint(cursorPosition);
transform.LookAt(targetPosition);
}
Please, provide details about your reasoning and desired behavior when you ask to find errors in your code.

andengine position a body

I am trying to position a body using the physics engine with this code:
float touchX = pp[0];
float touchY = pp[1];
float diffX = touchX - mBody.getPosition().x;
float diffY = touchY - mBody.getPosition().y;
mBody.setLinearVelocity(new Vector2(( pp[0]) / PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT , ( pp[1]) / PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT));
The X and Y coords are from a TMX tile map and are 32 pixels square, I am trying to get the body in the physics engine to move to certain tiles in a tile map (held in the pp[] array) but instead it moves to a random chaotic path. Is this the right approach to convert X,Y coords and move to that point??
Thanks
.setLinearVelocity doesn't move body to certain possition. To do this you need to use .setTransform
.setLinearVelocity is like you add force to the body and make it move, so it doesn't move to the position you want.
.setTransform is like you set the position of the body. So it doesn't move slowly from A to B, but disappears from A and suddenly appears at B
You can easy move it slowly by code yourself.

Car turning circle and moving the sprite

I would like to use Cocos2d on the iPhone to draw a 2D car and make it steer from left to right in a natural way.
Here is what I tried:
Calculate the angle of the wheels and just move it to the destination point where the wheels point to. But this creates a very unnatural feel. The car drifts half the time
After that I started some research on how to get a turning circle from a car, which meant that I needed a couple of constants like wheelbase and the width of the car.
After a lot of research, I created the following code:
float steerAngle = 30; // in degrees
float speed = 20;
float carWidth = 1.8f; // as in 1.8 meters
float wheelBase = 3.5f; // as in 3.5 meters
float x = (wheelBase / abs(tan(steerAngle)) + carWidth/ 2);
float wheelBaseHalf = wheelBase / 2;
float r = (float) sqrt(x * x + wheelBaseHalf * wheelBaseHalf);
float theta = speed * 1 / r;
if (steerAngle < 0.0f)
theta = theta * -1;
drawCircle(CGPointMake(carPosition.x - r, carPosition.y),
r, CC_DEGREES_TO_RADIANS(180), 50, NO);
The first couple of lines are my constants. carPosition is of the type CGPoint. After that I try to draw a circle which shows the turning circle of my car, but the circle it draws is far too small. I can just make my constants bigger, to make the circle bigger, but then I would still need to know how to move my sprite on this circle.
I tried following a .NET tutorial I found on the subject, but I can't really completely convert it because it uses Matrixes, which aren't supported by Cocoa.
Can someone give me a couple of pointers on how to start this? I have been looking for example code, but I can't find any.
EDIT After the comments given below
I corrected my constants, my wheelBase is now 50 (the sprite is 50px high), my carWidth is 30 (the sprite is 30px in width).
But now I have the problem, that when my car does it's first 'tick', the rotation is correct (and also the placement), but after that the calculations seem wrong.
The middle of the turning circle is moved instead of kept at it's original position. What I need (I think) is that at each angle of the car I need to recalculate the original centre of the turning circle. I would think this is easy, because I have the radius and the turning angle, but I can't seem to figure out how to keep the car moving in a nice circle.
Any more pointers?
You have the right idea. The constants are the problem in this case. You need to specify wheelBase and carWidth in units that match your view size. For example, if the image of your car on the screen has a wheel base of 30 pixels, you would use 30 for the WheelBase variable.
This explains why your on-screen circles are too small. Cocoa is trying to draw circles for a tiny little car which is only 1.8 pixels wide!
Now, for the matter of moving your car along the circle:
The theta variable you calculate in the code above is a rotational speed, which is what you would use to move the car around the center point of that circle:
Let's assume that your speed variable is in pixels per second, to make the calculations easier. With that assumption in place, you would simply execute the following code once every second:
// calculate the new position of the car
newCarPosition.x = (carPosition.x - r) + r*cos(theta);
newCarPosition.y = carPosition.y + r*sin(theta);
// rotate the car appropriately (pseudo-code)
[car rotateByAngle:theta];
Note: I'm not sure what the correct method is to rotate your car's image, so I just used rotateByAngle: to get the point across. I hope it helps!
update (after comments):
I hadn't thought about the center of the turning circle moving with the car. The original code doesn't take into account the angle that the car is already rotated to. I would change it as follows:
...
if (steerAngle < 0.0f)
theta = theta * -1;
// calculate the center of the turning circle,
// taking int account the rotation of the car
circleCenter.x = carPosition.x - r*cos(carAngle);
circleCenter.y = carPosition.y + r*sin(carAngle);
// draw the turning circle
drawCircle(circleCenter, r, CC_DEGREES_TO_RADIANS(180), 50, NO);
// calculate the new position of the car
newCarPosition.x = circleCenter.x + r*cos(theta);
newCarPosition.y = circleCenter.y + r*sin(theta);
// rotate the car appropriately (pseudo-code)
[car rotateByAngle:theta];
carAngle = carAngle + theta;
This should keep the center of the turning circle at the appropriate point, even if the car has been rotated.