My Rocket is hitting this Inertia object, as defined in handleCollision. I'm passing in a rocket which has a .r value for its theta and .power for its magnitude.
I'm wanting to update my .rotation & .magnitude according to an inelastic collision as defined by Wikipedia
When colliding from the left, my Inertia moves to the right.
But when colliding from the right it errors and moves exactly 180 degrees off. So if the rocket is up and right at a 45 degree angle from the inertia object, the object will move up and right at a 45 degree angle.
What am I missing here? I thought it might be an issue with the atan function so I converted by the y component & x component of the vector to radians first, same issue.
handleCollision(rocket) {
var angle = rocket.r * Math.PI / 180.0;
var rr = this.rotation * Math.PI / 180;
var rocketVector = {'x' : r.power * Math.cos(angle), 'y' : r.power * Math.sin(angle)};
var inertiaVector = {'x' : this.magnitude * Math.cos(rr), 'y' : this.magnitude * Math.sin(rr)};
var rMass = 10;
var shipMass = 10;
var x = (rMass * rocketVector.x) + (shipMass * inertiaVector.x);
var y = (rMass * rocketVector.y) + (shipMass * inertiaVector.y);
var xDividedByMass = x / (rMass + shipMass);
var yDividedByMass = y / (rMass + shipMass);
var yRadians = (yDividedByMass * Math.PI / 180);
var xRadians = (xDividedByMass * Math.PI / 180);
var theta = Math.atan( yRadians / xRadians);
theta = theta * 180 / Math.PI;
console.log(theta);
var hypotenuse = Math.sqrt((xDividedByMass * xDividedByMass) + (yDividedByMass * yDividedByMass));
this.magnitude = hypotenuse;
this.rotation = theta;
if (this.rotation < 0) {
this.rotation += 360;
} else if (this.rotation > 360) {
this.rotation -= 360;
}
}
If xDividedbyMass>0, you are great because you are quadrant I or IV where arctangent kicks out its values. If you do not like the negative angle, okay add 360 like you did.
But if x<0 and y>0, you will get a negative angle and want to add 180 to get to Q II (tangent has a period of 180). And if x<0, and y<0, you are in QIII and again arctan gives you something in Q1 to which you must add 180.
The logic will look something like this.
if ((x > 0) && (y<0)) {
this.rotation += 360;
} else if (x<0) {
this.rotation += 180;
}
Related
I am trying to find the X, Y points on a circle where 0 degrees starts at the top of the circle and moves clockwise. Typically, to find the x, y coordinates on a circle with a known radius and angle you could simply use the formula x = r(cos(degrees°)), y = r(sin(degrees°)). The circle would look like this and the degrees would expand counterclockwise from 0°.
However, I am using a circle where the 0° starts at the top and the degrees expand as one moves clockwise around the circle. Supposing that var r = 60; and var degrees = 130; what formula could I use (or javascript methods) to determine the X, Y values. Note: I can assume an origin point of 0, 60 because r = 60. Thanks.
As full circle has 2 radiants so you could calculate point coordinates for your circle with following formula:
x = radius * Math.sin(Math.PI * 2 * angle / 360);
y = radius * Math.cos(Math.PI * 2 * angle / 360);
var radius = 60;
var angle = 140;
var x = radius * Math.sin(Math.PI * 2 * angle / 360);
var y = radius * Math.cos(Math.PI * 2 * angle / 360);
console.log('Points coors are x='+
Math.round(x * 100) / 100 +', y=' +
Math.round(y * 100) / 100)
The trick is to convert your problem into the problem you know how to solve. You can do this by subtracting 90 degrees from your angle and negating y, i.e. x=r cos(theta-90) and y = -r sin(theta-90). In JavaScript:
function circleXY(r, theta) {
// Convert angle to radians
theta = (theta-90) * Math.PI/180;
return {x: r*Math.cos(theta),
y: -r*Math.sin(theta)}
}
for (var theta=0; theta<=360; theta += 30) {
var answer = circleXY(60, theta);
console.log('(x, y) = ' + '(' + answer.x + ', ' + answer.y + ') for theta=' + theta);
}
produces the following result:
(x, y) = (3.67394039744206e-15, 60) for theta=0
(x, y) = (30.000000000000007, 51.96152422706631) for theta=30
(x, y) = (51.96152422706632, 29.999999999999996) for theta=60
(x, y) = (60, 0) for theta=90
(x, y) = (51.96152422706632, -29.999999999999996) for theta=120
(x, y) = (30.000000000000007, -51.96152422706631) for theta=150
(x, y) = (3.67394039744206e-15, -60) for theta=180
(x, y) = (-29.999999999999986, -51.96152422706632) for theta=210
(x, y) = (-51.96152422706632, -29.999999999999996) for theta=240
(x, y) = (-60, -7.34788079488412e-15) for theta=270
(x, y) = (-51.96152422706631, 30.000000000000007) for theta=300
(x, y) = (-30.00000000000003, 51.961524227066306) for theta=330
(x, y) = (-1.1021821192326178e-14, 60) for theta=360
Should be
x = Math.cos(Math.PI * 2 * angle/360);
and
y = Math.sin(Math.PI * 2 * angle/360);
I am developing a game where there are enemies and cars.So currently my cars move towards the enemies in a diagonal shape they hit them and earn points.Now I want to make the hero to make the move in a straight manner(like snake game no diagonal movement) and then hit the enemy and gain points.
So my current way of hitting the enemy is like
function angleBetweenTwoPoints(p1, p2) {
return Math.atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Math.PI;
}
function degreeToRadian(degrees) {
return degrees * (Math.PI / 180);
}
var angle = angleBetweenTwoPoints(this.target.position, this.position);
var cos = Math.cos(degreeToRadian(angle)) * -1;
var sin = Math.sin(degreeToRadian(angle));
this.angle = angle;
this.position.x += cos * this.speed;
this.position.y -= sin * this.speed;
if (distance(this.position, this.target.position) < 10) {
this.target.position.x = Math.random() * mainCanvas.width;
this.target.position.y = Math.random() * mainCanvas.height;
this.hitCount++;
console.log("Hit!");
ctx.fillText("points : " + hitCount, 32, 32);
}
So now I want to make the car move by not diagonally and in a straight manner.
This is my working game.Any help is appreciated.
Use Pixi : http://www.pixijs.com/
And GSAP : https://greensock.com/
You will find easily everything to do it better ;)
So I am a bit confused on how I can make a shape animate to the center of a canvas. I can get the center value:
width = canvas.width = window.innerWidth,
height = canvas.height = window.innerHeight,
centerX = width / 2,
centerY = height / 2;
and a simple decrement or increment depending on whether the initial position is positive or negative can be done as well:
var x = 100;
var y = 100;
function fn (){
ctx.beginPath();
ctx.arc(x, y, 50, 0, 2 * Math.PI, false);
ctx.fillStyle = '#444';
ctx.fill();
ctx.closePath();
x -= 1;
y -= 1;
}
The animation would be done using:
requestAnimationFrame(fn)
Problem with all this is. I need to manually adjust the x and y everytime. How can I better simply make the x and y values random for the shape and make it animate to the center, no matter from what direction and if the initial position is negative or positive. I was thinking of atang2 but honestly im not entirely sure.
You're basically on the right track. Use Math.sqrt for the distance and Math.atan2 to find the direction. Then its just the matter of how fast (velocity) you want the object to move to the target (centre of the canvas).
var tx = centerX - x,
tx = centerY - y,
distance = Math.sqrt(tx * tx + ty * ty),
radius = Math.atan2(ty, tx),
angle = (radius / Math.PI) * 180;
// Ensure we don't divide by zero if distance is 0
if (distance !== 0)
{
velX = (tx / distance) * velocity;
velY = (ty / distance) * velocity;
x += velX;
y += velY;
}
The answer given is flawed as there is no check for divide by zero. This error can easily be overlooked and then crop up in production code making it very hard to find out what has gone wrong.
Should be
var tx = centre.x - x;
var ty = centre.y - y;
var dist = Math.sqrt(tx * tx + ty * ty);
// or
var dist = Math.sqrt(Math.pow(tx, 2) + Math.pow(ty, 2));
if(dist !== 0){ // must have this test or when the coords get to the centre
// you will get a divide by zero
tx /= dist; // Normalise direction vector
ty /= dist;
}
tx *= speed; // set the magnitude to required speed;
ty *= speed; // Note that if at the centre this will be zero
x += tx;
y += ty;
I've been working with phoria.js and have really got a kick out of it. I have a player avatar model and have been using a first person camera. The phoria.js camera is positioned with two coordinates of 3D space: the first: the camera's actual position in the scene graph, the second: the point which the camera looks at. I've been using two angles: angleX and angleY defined in degrees (I know that radians are better) for easy thinking as well as a constant distance of 10 units.
The code for the fp camera goes like
{within an object definition}
setLookAtByAngle: function(camera, angleX, angleY) {
lookAt = {x: camera.position.x, y: camera.position.y, z: camera.position.z};
extent = 10;
lookAt.x += Math.tan(angleX * (Math.PI / 180)) * extent;
lookAt.y += Math.tan(angleY * (Math.PI / 180)) * extent;
lookAt.z += extent;
camera.lookat = lookAt;
},
getAngleByLookAt: function(camera) {
xPlanarLookAt = {x: camera.lookat.x, y: camera.position.y, z: camera.lookat.z};
yPlanarLookAt = {x: camera.position.x, y: camera.lookat.y, z: camera.lookat.z};
hypotX = getDistanceBetweenTwoPoints(camera.position, xPlanarLookAt);
oppX = Math.abs(camera.lookat.x - camera.position.x);
angleX = Math.asin(oppX / hypotX) * (180/Math.PI);
hypotY = getDistanceBetweenTwoPoints(camera.position, yPlanarLookAt);
oppY = Math.abs(camera.lookat.y - camera.position.y);
angleY = Math.asin(oppY / hypotY) * (180/Math.PI);
return {x: angleX, y: angleY};
},
{continue object definition}
. What I have so far of the third person camera uses my own SpaceUtils. It takes the observee's position1 and the inverted x[2],y[3] angles and calls SpaceUtils.translateByAngle([1], [2], [3], 10) with 10 as a distance constant to be modified later along with FOV when I add zooming functionality.
SpaceUtils looks like
SpaceUtils = {
degSin: function(theta) {
return Math.sin(theta * (Math.PI / 180));
},
degCos: function(theta) {
return Math.cos(theta * (Math.PI / 180));
},
degTan: function(theta) {
return Math.tan(theta * (Math.PI / 180));
},
translateByAngle: function(pos, angleX, angleY, distance) {
dest = {x: pos.x, y: pos.y, z: pos.z};
dest.z += distance * SpaceUtils.degSin(angleY);
hyp = distance * SpaceUtils.degCos(angleY);
dest.x += hyp * SpaceUtils.degCos(angleX);
dest.y += hyp * SpaceUtils.degSin(angleX);
return dest;
}
};
My calculator has Pol() and Rec() functions which do the job in 2D.
I supposed I just need the correct one of these for 3D, so I began implementing. It all works in the four x > 0 quadrants, but pushes the camera down as I transition across x == 0 where y > 0 (y is up-down axis) so that when I start with x > 0 and y > 0, I end up with x < 0 and y < 0 when y > 0 should be the case.
In short, I need a 3D Rec(r, theta) function ideally in degrees, but radians is fine if it's not purpose written.
I realise that this is a sizable ask, so I'll bounty 50 or 100 rep if it comes to that.
Phoria uses x as forward-backward, y as upward-downward, and z as sideways, while conventional mathematics swaps the purposes of y and z. You should to. That last function in SpaceUtils should go something more along the lines of the follwing.
translateByAngle: function(pos, angleX, angleY, distance) {
dest = {x: pos.x, y: pos.y, z: pos.z};
dest.y += distance * SpaceUtils.degSin(angleY);
hyp = distance * SpaceUtils.degCos(angleY);
dest.x += hyp * SpaceUtils.degSin(angleX);
dest.z += hyp * SpaceUtils.degCos(angleX);
return dest;
}
I am working with SVG graphics to draw Pie Graphs. I am given the degrees a pie graph should be - eg 277 degrees - and the diameter - eg 200px - and I need to draw a circle of 277 degrees.
With SVG graphics I need to resolve that 277 degrees to a point where that circle will end.
I am not the greatest with math, so I have come up with a formula/javascript function that will allow me to take a degrees value & come up with a x,y point of where the circle will end.
Will my Javascript function(at the bottom) correctly resolve a degrees to a correct point? Can you help me develop my algorithm to obtain the coordinate from a degree value? Or maybe there is an existing algorithm I can use that I dont know about?
My Algorithm: (Which I require help with)
So the values I am given are: Circle Diameter: 200px, Circle size: 277 degrees.
I require the point at which 277 ends when rotating around the point 0,0.
277 ends in the 1st quadrant which means I need to use sin (is that correct?)
So the values I know now of the triangle are: the hypotenuse=100px(the radius), the angle=7 degrees(277-270).
sin(7) = o/100;
0.1219 = o/100;
o = 12.2;
Therefore the y point is 12.2 (for my sakes 0,0 is the top left corner so its really midY-x = 100-12.2 = 87.8; (is that correct?)
Now to determine the x pos, I use cos(is that correct?).
cos(7) = a/100;
a = 99.25;
Therefore the x point is 99.25 or 100-99.25=0.75;
So the x,y coordinate of 277 degrees is 0.75,87.8. Is that correct?
So in code this algorithm would be:
function resolveToPoint( deg, diameter )
{
if ( deg <= 0)
return 0;
var x = 0;
var y = 0;
var angle = 0;
var rad = diameter/2;
var midX = rad;
var midY = rad;
if (deg <= 90)
angle = 90 - deg;
else if (deg <= 180)
angle = deg - 90;
else if (deg <= 270)
angle = deg - 180;
else if (deg <= 360)
angle = deg - 270;
// Q: Will I ALWAYS use cos to determine the x & sin for the x NO MATTER what quadrant the angle is in??
x = Math.cos(angle) * rad;
y = Math.sin(angle) * rad;
if (deg <= 90)
{
x = midX + x;
y = midY - y;
}
else if (deg <= 180)
{
x = midX + x;
y = midY + y;
}
else if (deg <= 270)
{
x = midX - x;
y = midY + y;
}
else if (deg <= 360)
{
x = midX - x;
y = midY - y;
}
return {mX: x, mY: y};
}
Then I'll use it in a SVG like so:
function outputPiegraph( point, rad, diameter )
{
var svg = '<svg width="%spx" height=""%spx" id='pie' style="background-color: green;">
<path d="M%spx,%spx L%spx, %spx A%spx,"%spx 1 1,1 %spx,%spx z"
fill="red" stroke="blue" stroke-width="2" />"
</svg>';
return sprintf(svg, diameter, diameter, point.mX, point.mY, rad, rad, rad, diameter);
}
This is simple conversion from polar to Cartesian coordinates:
function resolveToPoint(deg, diameter) {
var rad = Math.PI * deg / 180;
var r = diameter / 2;
return {mX: r * Math.cos(rad), mY: r * Math.sin(rad)};
}
http://en.wikipedia.org/wiki/Polar_coordinates#Converting_between_polar_and_Cartesian_coordinates
If you consider the unit circle, then the X-coordinate for a given (radians-based) angle is given by the cosine, likewise, the Y-coordinate is given by the sine. So, you can solve this easily as follows.
function resolveToPoint(deg, diameter) {
var radians = angle_in_degrees / 180 * Math.PI;
var x = diameter / 2 * cos(radians);
var y = diameter / 2 * sin(radians);
return {mX : x, mY: y};
}