C
C#13mo ago
arch_il

2d collision, Chaotic Ball

I am trying to write code for chaotic ball. I know it can be written using equation of motion, but wanted to create simulation for it. This is my code right now and it is terrible. I can't seem to make it collide with top part of the circle, there are energy leaks and ball sometimes exits out the sphere. Any recommendation for how to improve it? I want to learn more about real time simulations. note: dt is fixed to 0.001 so that shouldn't be a problem.
velocity.Y += g * dt;
position += velocity * dt;

double intersect_y = -Math.Sqrt(radius * radius - position.X * position.X);

if (position.Y <= intersect_y)
{
Vec2 n = new Vec2(position.X / radius, intersect_y / radius);

if (position.X > 0)
n.Y *= -1;

double v_normal = Vec2.dot(velocity, n);

velocity = -1.0 * velocity + 2 * (v_normal * n) * n;

position.Y = intersect_y;
}
velocity.Y += g * dt;
position += velocity * dt;

double intersect_y = -Math.Sqrt(radius * radius - position.X * position.X);

if (position.Y <= intersect_y)
{
Vec2 n = new Vec2(position.X / radius, intersect_y / radius);

if (position.X > 0)
n.Y *= -1;

double v_normal = Vec2.dot(velocity, n);

velocity = -1.0 * velocity + 2 * (v_normal * n) * n;

position.Y = intersect_y;
}
No description
19 Replies
exokem
exokem13mo ago
This is just an idea but you can probably just calculate the distance between the ball center and the center of the big circle and trigger a collision whenever the distance would become greater than the large radius minus the small radius Then there would be no edge case checking for the top Vs the bottom
arch_il
arch_ilOP13mo ago
thanks. that's better way for triggering, but trigger was never really the issue. I had both cases together, but split them up in the process of trying to get it right.
exokem
exokem13mo ago
Is it more an issue of calculating the resulting motion vector? Or the direction
arch_il
arch_ilOP13mo ago
motion vector
exokem
exokem13mo ago
I will do some math and get back to you You could try mirroring the motion vector over the normal to the point of collision It's not that simple but it might work
arch_il
arch_ilOP13mo ago
No description
arch_il
arch_ilOP13mo ago
i attempted this
exokem
exokem13mo ago
Is that what your current code does
arch_il
arch_ilOP13mo ago
yes I made mistake somewhere, so it doesn't work on the right side. Couldn't find issue there either
exokem
exokem13mo ago
Are you also getting the X intersection? It looks like you only have intersect y
arch_il
arch_ilOP13mo ago
my logic is that if y is out of bounds, x will be too
exokem
exokem13mo ago
I would have thought the normal calculation needed the vector from the intersection point Right now you are using the X position of the ball which is probably different
arch_il
arch_ilOP13mo ago
what can i do to fix that? nudge the ball towards center until it is inside bounds?
exokem
exokem13mo ago
You just need to get both coordinates for the intersection point
exokem
exokem13mo ago
This could be helpful for the math https://math.stackexchange.com/a/311956
Mathematics Stack Exchange
Get location of vector/circle intersection?
I'm a coding guru, and I'm good with math - but only math that I know. Which isn't even at calculus level yet. So I'm hoping I can get some help here for my algorithm. Say I have a circle. I know ...
exokem
exokem13mo ago
Then the normal calculation would be the same and you still just reflect over it
arch_il
arch_ilOP13mo ago
that is much neater solution anyways its late for me. will try implementing tomorrow. thanks a bunch
exokem
exokem13mo ago
No problem, good luck
arch_il
arch_ilOP13mo ago
hey @exokem . thanks for help. here is solution i came up with today.
if (position.Length() >= radius)
{
double ratio = radius / position.Length();
position *= ratio;

double collision_angle = Math.Acos(position.X / radius);
double vector_angle = Math.Atan2(velocity.Y, velocity.X) + Math.PI;
double new_angle = 2 * collision_angle - vector_angle;
double vlen = velocity.Length();

velocity = new Vec2(-Math.Cos(new_angle), Math.Sin(new_angle)) * vlen;
}
if (position.Length() >= radius)
{
double ratio = radius / position.Length();
position *= ratio;

double collision_angle = Math.Acos(position.X / radius);
double vector_angle = Math.Atan2(velocity.Y, velocity.X) + Math.PI;
double new_angle = 2 * collision_angle - vector_angle;
double vlen = velocity.Length();

velocity = new Vec2(-Math.Cos(new_angle), Math.Sin(new_angle)) * vlen;
}
instead of fiddling around with vectors, i decided to find an angle of resulting velocity and then convert polar coordinate to traditional form. With some fiddling around, this works great.
Want results from more Discord servers?
Add your server