im working on a 2d canvas game. i have a player circle and some circles (random in size and position). i made the random circles move around an random x.y point. this means i have to radii. one is the radius from the rotationpoint to the middlepoint of the "bubble" and the other ist die radius of the bubble itself.
what i need is the collision between playercircle und the bubbles. i know how to create circle to circle collisondetction with pythagorean theorem and it works quite well. However there is a problem:
right now the collision works for the random x and y point + the radius (from rotationpoint) but not for the bubble itself.
what i tryed is to store the x and y of the rotationpoint + the radius to the middlepoint of the bubble into a variable to use them in collision. it works quite fine. if i console.log these x and y points they give me the changing x and ys from the middlepoint of the bubble.
my problem now is that if if substract these point from the playercircle x and y i didnt work with the right collision. so obviously im missing somethig and right now i am at a dead end.
i made a fiddle to show you, the function for the collision is on line 170, variablenames BubbleX and BubbleY. The .counter to animate the around the neg. or positiv:
http://jsfiddle.net/CLrPx/1/ (you need to use the console to the if there is a collision or not)
function collideBubbles(c1, c2) {
// moving/rotation xPos and yPos
var bubbleX = c2.xPos + Math.cos(c2.counter / 100) * c2.radius; // actual x and y pos. from bubble!
var bubbleY = c2.yPos + Math.cos(c2.counter / 100) * c2.radius;
//console.log('bubbleX: ' + bubbleX);
//console.log('bubbleY: ' + bubbleY);
var dx = c1.xPos - bubbleX; // change with pos from actual bubble!
var dy = c1.yPos - bubbleY; // change with pos from actual bubble!
var distance = c1.radius + c2.bubbleRadius
// Pytagorean Theorem
return (dx * dx + dy * dy <= distance * distance);
}
Related
I'm writing a simple computer animation, which is a line that rotates around a fixed point at the center of that line. The amount of rotation is based on a gradient noise algorithm (OpenSimplex noise). The line has an origin [x,y] and a nr of the animation frame. These three values plugged into OpenSimplex noise give a rotation value. This part is working perfectly.
The problem is I want to make the line appear to follow the mouse cursor, depending on how far the mouse cursor is from the line. The cursor has coordinates [mx, my] (which change for every frame of animation). I can easily rotate the line and point straight towards the cursor. But I'm having difficulties factoring in the distance. To clarify; the line is rotation on the gradient noise and the mouse cursor alters that rotation to make the line (at [x, y]) point at [mx, my].
Also, the line has an 180 degree identity, so the closest end should point towards the mouse.
Basically what I'm doing now is taking "rotation line" plus "rotation mouse". If it is between 90 and 270 deg the back of the line is closest to the cursor, otherwise the front (for simplicity this is not included in the example code below). So I then take the difference, factor in the distance and substract or add it to the rotation of the line. And this works fairly well except for some artifacts.
let r = OpenSimplexNoise(x, y, frame); // gives current original rotation
let frame = 68; // whichever frame
let x = 60; // some fixed coordinate of line
let y = 60; // some fixed coordinate of line
let mouseX = 10; // changes when the mouse moves
let mouseY = 10; // changes when the mouse moves
let mouseRadius = 200;
let width = 100;
let height = 1;
function distance (x, y, cx, cy) {
return Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy));
}
function angle (x1, y1, x2, y2) {
let dx = x1 - x2;
let dy = y1 - y2;
return 360 + (Math.atan2(dy, dx) * 180 / Math.PI);
}
if (distance(x, y, mouseX, mouseY) <= mouseRadius) {
let dist = distance(x, y, mouseX, mouseY);
let mouseR = angle(x, y, mouseX, mouseY) % 360;
let near = (mouseRadius - dist) / mouseRadius;
let far = 1 - near;
r = (r * far + near * mouseR) % 360;
}
// r now includes mouse
A live version:
https://jsfiddle.net/Ruudt/56pk2wd1/1/
The problem lies in the cases where the mouse passes from being left to right of perpendicular to the (original rotation) line. Here the calculation will nominate the other end as "closests", then calculate the distance and apply this to the rotation. This results in the line jumping from pointing slightly left of the cursor to right of the cursor (or vice versa).
Is there a way to fix this?
I've made an image to illustrate the situation.
The red line represents the line using only the rotation of the gradient noise
The black line is the line that also includes mouse position
the blue arc is the mouse rotation value (right end is origin)
line rotation:
I'm trying to use the answer provided here: Intersection of two Moving Objects with Latitude/Longitude Coordinates
But I have some questions..
What is this angle:
var angle = Math.PI + dir - target.dir
I was thinking that the angle that should be used in the law of cosines is already "alpha or target.dir".. What is that line doing? Also in these two steps:
var x = target.x + target.vel * time * Math.cos(target.dir);
var y = target.y + target.vel * time * Math.sin(target.dir);
Shouldn't the code be using the angle between x- or y-axis and the target velocity vector? Why is the author using alpha here?
What is this angle:
var angle = Math.PI + dir - target.dir
The variable named angle is indeed the angle alpha. Because the direction dir is the direction from chaser to target, and we need it the other way round for this calculation, we add π to it before we subtract target.dir.
Maybe using the word angle as a variable name was a bit vague; I'll change it to alpha, the name I used for this angle in the images.
Shouldn't the code be using the angle between x- or y-axis and the target velocity vector? Why is the author using alpha here?
var x = target.x + target.vel * time * Math.cos(target.dir);
var y = target.y + target.vel * time * Math.sin(target.dir);
We are indeed using target.dir, which is the direction of the target, i.e. the angle between the x-axis and the target vector, to calculate the coordinates of the interception point, and not the angle alpha.
I've been working on this problem for a bit, and it doesn't seem too hard, but I'm getting tired and it seems more and more complicated the more I try (but it's probably really easy).
My goal is to have a ball bounce off another ball. Seems easy enough.
Ball 2 is controlled by the user's mouse (so far it's sort of like single player pong, but it's a circle instead of a rectangle) so its velocity doesn't matter.
Ball 1 has a few attributes, including dx (the x distance it moves every frame) and dy (dx, but for the y coordinate)
The problem with what I have so far is that you don't know what values will be positive and what will be negative (so the speed can severely increase or decrease instantly), you might be able to fix this using many else if's, but I'm too confused to think right now.
Here is the important part of this function. Also, I've tried to set it up so that dx + dy is always the same, even when the numbers change, so that it looks more natural.
if (collision(ball, paddle)) {
diffX = paddle.x-ball.x;
diffY = paddle.y-ball.y;
totalVel = ball.dx+ball.dy;
dir = {
x : diffX/(diffX+diffY)*-totalVel,
y : diffY/(diffX+diffY)*-totalVel
};
ball.dx = dir.x;
ball.dy = dir.y;
}
Here is a JSFiddle with the full code
https://jsfiddle.net/a2prr0uw/1/
So firstly let's start by defining what a "bounce" is - the speed is the same, but the direction (on both axis) will be inverted. If we treat dx and dy like a vector, then we can first get the incoming speed of the ball like this:
var ballSpeed = Math.sqrt((ball.dx * ball.dx) + (ball.dy * ball.dy));
The above value will always be positive, regardless of what dx and dy are doing.
Next, we'll need the incoming direction of the ball - that bit is the same as what you've currently got:
diffX = paddle.x-ball.x;
diffY = paddle.y-ball.y;
However if we treat this as a vector too, it essentially has a totally unknown length. So, let's normalise it so it's a direction vector with a length of 1:
var distanceBetweenPaddleAndBall = Math.sqrt((diffX * diffX) + (diffY * diffY));
diffX /= distanceBetweenPaddleAndBall;
diffY /= distanceBetweenPaddleAndBall;
diffX and diffY is now a normalised direction vector - the direction the ball is currently going in - and ballSpeed is the speed we'd like it to go.
So now we'll apply our bounce - flip the direction and retain the speed. That becomes this:
dir = {
x : -diffX * ballSpeed,
y : -diffY * ballSpeed
};
Put it all together and we end up with this:
if (collision(ball, paddle)) {
diffX = paddle.x-ball.x;
diffY = paddle.y-ball.y;
// How fast is the ball coming in?
var ballSpeed = Math.sqrt((ball.dx * ball.dx) + (ball.dy * ball.dy));
// How far is the ball from the paddle?
var distanceBetweenPaddleAndBall = Math.sqrt((diffX * diffX) + (diffY * diffY));
// Normalise diffX and diffY so we have a direction vector:
diffX /= distanceBetweenPaddleAndBall;
diffY /= distanceBetweenPaddleAndBall;
// Apply the bounce and the original ball speed:
dir = {
x : -diffX * ballSpeed,
y : -diffY * ballSpeed
};
ball.dx = dir.x;
ball.dy = dir.y;
}
And here it is as a fork of your fiddle too.
not an answer but some considerations on your bouncing logic:
you have to calculate the balls direction (dy/dx)
the collision has also a direction (angle beween both centers = b.x-p.x / b.y-p.y)
the angle after bouncing has to be calculated based on these two angles: using ther 2nd for mirroring
to calculate the new dx & dy after collision you will need the original velocity Math.abs(Math.sqrt(Math.pow(dx)+Math.pow(dy))) of the ball
based on this velocity and the new direction you can calc the new dx & dy
I'm trying to draw the perimeter of a circle depending on the angle inputed by the user. The angle determines the perimeter completion : 360° being the full circle, 180 half of the circle, and so on.
My problem is : given the radius, the angle and the center coordinates of the circle, how can I dynamically compute the path of the perimeter ?
I know it's probably basic math but everything I tried so far didn't work.
Here is my fiddle : https://jsfiddle.net/Hal_9100/L311qq88/
My problem is finding the right formula for the x and y coordinates of the path :
var x = i * (radius * Math.cos(angle)) + centerX;
var y = i * (radius * Math.sin(angle)) + centerY;
Am I going all wrong here ?
Here is an example of what I'm trying to do : please note that only the black perimeter should be drawn : I just used the dotted red lines to give a visual example of how the perimeter should be drawn depending on the value given by the user.
Yes, the problem is your maths. Here is the correct way to calculate the x,y coordinate pairs (note that the iteration is from zero to the required angle, not from zero to the radius):
for (var i = 0; i <= angle; i++) {
var x = (radius * Math.cos((i-90)*Math.PI/180)) + centerX;
var y = (radius * Math.sin((i-90)*Math.PI/180)) + centerY;
Your fiddle works fine if you substitute these three lines.
I'm trying to find a point that is equal distance away from the middle of a perpendicular line. I want to use this point to create a Bézier curve using the start and end points, and this other point I'm trying to find.
I've calculated the perpendicular line, and I can plot points on that line, but the problem is that depending on the angle of the line, the points get further away or closer to the original line, and I want to be able to calculate it so it's always X units away.
Take a look at this JSFiddle which shows the original line, with some points plotted along the perpendicular line:
http://jsfiddle.net/eLxcB/1/.
If you change the start and end points, you can see these plotted points getting closer together or further away.
How do I get them to be uniformly the same distance apart from each other no matter what the angle is?
Code snippit below:
// Start and end points
var startX = 120
var startY = 150
var endX = 180
var endY = 130
// Calculate how far above or below the control point should be
var centrePointX = ((startX + endX) / 2);
var centrePointY = ((startY + endY) / 2);
// Calculate slopes and Y intersects
var lineSlope = (endY - startY) / (endX - startX);
var perpendicularSlope = -1 / lineSlope;
var yIntersect = centrePointY - (centrePointX * perpendicularSlope);
// Draw a line between the two original points
R.path('M '+startX+' '+startY+', L '+endX+' '+endY);
Generally you can get the coordinates of a normal of a line like this:
P1 = {r * cos(a) + Cx, -r * sin(a) + Cy},
P2 = {-r * cos(a) + Cx, r * sin(a) + Cy}.
A demo applying this to your case at jsFiddle.