Circle-Line Sliding Collision (js) - javascript

I'm doing a video-game in pure javascript with the Html-Canvas.
I need to find new save x and y coordinates of a circle colliding with a line.
I already find out a easy way to tell if a circle is intersecting with a line , but then i cant figure out how to find the new circle position according to the direction of the circle and the friction of the line.
screenshot example
So the collision detection is done and its working now the problem is the future position of the ball.
I am not looking for a bouncing physic , i am looking for a inelastic collision.
What i thinked was :
Ratio of angleOfStart + angleOfImpact (lets say the angle of the impact is 90° , that means I'm colliding at the line in a perpendicular way , and the angle of start is 0° that means i'm moving right , so x shouldnt be able to grow , but y can go up and down... I thought that by applying this report we could find a formula valid for all collision angles.
Following the direction of the segment collided with ( when i collide with a line i know bot point a and point b , then i can calculate the angle of this line , then i can force my circle to moove only in that direction , multiplying the initial speed - some friction).
Both of those idea in my mind works , but once implemented them in javascript seems works only sometimes...
Lets say i have an object segment collided :
segment = {
a : {
x : // some value,
y : // some value
},
b : {
x : // some value,
y : // some value
}
}
circle = {
x: // value,
y: // value,
ray: // value
}
future_circle = {
x: // x where user wants to go,
y: // y where user wants to go,
ray : // value
}
I know that circle is not colliding with segment.
But if i let the circle move becoming "future circle" then they will collide.
I need to change future circle values so my circle doesnt stops and doesnt go trought the line ... i need my circle mooves in line with the segment, taking care about friction.
I decided to open my mind to other solutions , that surely will work better than mines.
Any help is appreciated.
Sorry for my bad english.

Related

Three JS check if position is behind object

I have a 3D character along with several predefined positions on the floor. Is there a way to check if a position is behind the 3D character and not in front or sideways?
I’ve included a rough sketch of what I’m trying to achieve (sorry for the poor drawing). Essentially I would like to return all of the positions of the red circles within the red lines and exclude all other circles outside of these two lines.
Is this possible? If so, is there any suggestion on how I can achieve this? I’m sorry but I don’t actually know which functions to use from Three JS for something like this or if it is possible.
Thank you!
Yes, it's possible.
You start out by first checking if a point/circle is behind the player. You do this by getting the dot product between the direction player is facing (a unit vector) and the direction vector to the circle (normalize it so that it's also a unit vector). If the values dotProduct <= 0 then the circle is behind your player.
(unit vector means that your vector has a magnitude of one. Which is a fancy way of saying your x/y/z will never go beyond 1)
Code example
// Let's assume that the following code is in some sort of loop, yes
// Get the direction vector to the circle
const directionVect = circle.position.clone().sub(player.position).normalize();
// If your player is a camera you can get the direction like so
const playerFacing = player.getWorldDirection(new THREE.Vector3());
// Orientation
if (playerFacing.dot(directionVect) <= 0) {
// Circle is behind the player
// ...to be continued...
} else {
return;
}
Now that you know which circles are behind your player, you can get the circles within the cone. This is done by getting the angle between the player's position and the circle's position. Then check that the angle fits some criteria (e.g. the angle can't be more than 45deg from back of player).
// ...
// Orientation
if (playerFacing.dot(directionVect) <= 0) {
// Circle is behind the player
const angle = player.position.angleTo(circle.position);
if (angle < Math.PI * 0.25) {
// Do something with circle
}
} else {
return;
}

three.js lookAt() : how to point some local axis which *isn't* the positive Z axis towards another object

I'm creating an app where a person (right now I'm using a cone-shape) is standing on some surface (right now I'm using a cylinder laid lengthwise) and I'd like their feet to orient toward some point (right now it's the center of the cylinder).
(edit: I just realized that my Z axis in this photo is pointing in the wrong direction; it should be pointing towards the camera, but the question remains unchanged.)
Here is a version of the code similar to what I'm trying to accomplish. https://codepen.io/liamcorbett/pen/YMWayJ (Use arrow keys to move the cone)
//...
person = CreatePerson();
person.mesh.up = new THREE.Vector3(0, 0, 1);
//
// ...
//
function updateObj(obj, aboutObj=false){
let mesh = obj.mesh;
if (aboutObj) {
mesh.lookAt(
aboutObj.mesh.position.x,
aboutObj.mesh.position.y,
mesh.position.z)
};
}
//
// ...
//
function animate() {
// ...
updateObj(person);
// ...
}
The code above gives me something similar to what I'm looking for, but the issue is that lookAt() seems to always point the local Positive Z-axis in some direction, and I'd much prefer that it point the local Negative Y-axis instead.
I'd prefer to not change the x,y,z axes of the model itself, as I feel that's going to be a pain to deal with when I'm applying other logic to the person object.
Is there a way to change which axis lookAt() uses? Or am I going to have to roll my own lookAt() function? Thanks ~
Is there a way to change which axis lookAt() uses?
No, the default local forward vector for 3D objects (excluding cameras) is (0, 0, 1). Unlike other engines, three.js does not allow to configure the forward vector, only the up vector. But this is not really helpful in your case.
You can try to transform the geometry in order to achieve a similar effect.
If you don't want to do this for some reasons and you still want to use Object3D.lookAt(), you have to compute a different target vector (so not the cylinder's center).
Even if the forward vector of the lookAt method can't be changed (as #Mugen87 said), you can still adjust the local rotation afterwards by knowing in advance the difference between the forward Z axis used, and the axis you consider your mesh to be "upward" (ex: a person standing up on the Y axis).
Basically, in your case, just add this line after the lookAt method :
mesh.rotateOnAxis( new THREE.Vector3(1,0,0), Math.PI * -0.5 );
And the cone will look up :)

Limit max velocity of a particle in javascript

Im working on a little project, I have some particles i want to move towards target positions without exceeding a max velocity, first i tried capping the X and Y velocities seperately which caused the hypotenuse of the two to be able to go over the max speed, i then remembered my maths classes and attempted this:
var totalVel = Math.sqrt(Math.pow(curVelocity[0],2) + Math.pow(curVelocity[1],2));
if(totalVel > maxSpeed){
//sin(θ) = Opposite / Hypotenuse
var angle = Math.asin(curVelocity[1]/totalVel);
var newHyp = maxSpeed;
var newOp = Math.sin(angle)*newHyp;
var newAdj = Math.sqrt(Math.pow(newHyp,2) - Math.pow(newOp,2));
curVelocity[1] = newOp;
curVelocity[0] = newAdj;
}
(curVelocity is an array where index 0 is X and index 1 is Y)
This works well hald the time, the other time it curves away from the target its trying to reach.. matches it on the Y plane but heads in the whole wrong direction in the X plane. im guessing its something to do with using math.sin when perhaps it no longer applies in the direction its traveling but i wouldnt know where ot begin differentiating what to use, or if that idea is even correct.
A live example of what im talking about can be found at this location here, refreshing the page will change the starting location and target location, the black circle is the particle the green circle is the target location

Function to get X/Y coordinates for move on triangle with soft edges

i want to make an animation in javascript where an object moves on a path.
For this i need a function that returns me X/Y coordinates on the path for a given time.
The path should be a triangle with soft edges.
At the beginning of the animation it should soft move into the triangle path - but this i could solve maybe in a different function .. more important to me is the function which can return me the X/Y coordinates for the move on the triangle.
The animation should then loop endless on the triangle path.
Are there (online) tools to create coordinates for such a animation?
Can someone help me with the function?
I'd recommend something like sqrt(x²+y²)=2.5+sin(atan2(y,x)*3)/5 - polar: ρ(θ)=2.5+sin(3θ)/5. It's a simple polar coordinate system, and adding a compressed sine wave (3 periods per turn) on a circle:
θ(t) = t // angle
ρ(t) = 2.5 + 0.2 * sin (t * 3) // radius
// of course, you can play with the parameters :-)
You can easily convert those polar coordinates into cartesion ones.
The animation at the beginning, moving from the center into the path, would need an extra function of course. Yet, it could be done with the same mechanic - leaving out the circle part: ρ(θ)=2.5*sin(3θ)

How can you keep rotated draggable objects inside the Raphael paper?

I have an application with many draggable objects that can also be rotated in 90 degree increments. I'm trying to figure out how to stop the user from dragging the objects outside the Raphael paper (canvas).
This is fairly simple for unrotated objects. I can simply see if the current x and y coordinates are less than 0 and set them to 0 instead. I can adjust similarly by checking if they are outside the canvas width and height.
However, a problem arises when the object is rotated because for some odd reason the coordinate plane rotates as well. Is there an easy way to keep objects inside the canvas? Or is there an example of some this somewhere?
I have spent many hours fiddling with this and I can't seem to make sense of the rotated coordinate plane in order to adjust my calculations. Even when debugging the current coordinates, they seem to shift oddly if I drag an object, release it, and then drag the object again.
Any help is greatly appreciated.
Thanks,
Ryan
I had a similar problem, I needed to move a shape within the boundaries of another shape, so what I did was:
element.drag(onstart, onmove, onend);
...
onStart: function(x,y,e){
// Initialize values so it doesn't recalculate per iteration
// this allows to resume dragging from the point it were left
App.oldX = 0;
App.oldY = 0;
App.currentCircleX = App.fingerPath.attr('cx');
App.currentCircleY = App.fingerPath.attr('cy');
},
onMove: function(dx,dy,x,y,e){
App.setDirection(dx,dy);
},
onEnd: function(e){
// nothing to do here for now
},
// this function tells the element to move only if it's within the bound area
setDirection: function(dx, dy){
var isXYinside;
this.newX = this.currentCircleX - (this.oldX - dx);
this.newY = this.currentCircleY - (this.oldY - dy);
// HERE is the key, this method receives your bounding path and evaluates the positions given and then returns true or false
isXYinside = Raphael.isPointInsidePath(this.viewportPath, this.newX, this.newY);
this.oldX = dx;
this.oldY = dy;
// so if it is within the bound area, will move, otherwise will just stay there
if (isXYinside) {
this.fingerPath.attr({
"cx": this.newX,
"cy": this.newY
});
this.currentCircleX = this.newX;
this.currentCircleY = this.newY;
}
}
I know this is an old one, but I stumbled upon this question when trying to figure out a way to do it. So here's my 2 cents in case someone has this problem.
Reference:
Raphael.isPointInsidePath
Have you tried Element.getBBox()
There Are 2 flavones which give the result before rotation and after rotation
You should toggle the Boolean argument and test it

Categories

Resources