# GMS 2 [Solved]Bouncing off Circle Line

Discussion in 'Programming' started by gdkid, Jul 7, 2019.

Tags:
1. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
Hi guys

I'm having the problem with making a ball bouncing off a circle line

I attached my screenshot so you can get my point.

So the white circle is created using draw_circle

I'd like to make the yellow ball bounce off the circle line, but since it doesn't have a mask, I found it difficult to do so.

Here's the code that I come up so far

I checked the area outside the circle, when the ball collides with this area then it will bounce back

But it doesn't seem to work, since the ball just comes through the circle line.

Code:
```if(!collision_circle(room_width/2,room_height/2,global.radius,objBallParent,false,false))
{
direction += 360-(direction*2)

}```

File size:
22.2 KB
Views:
6
2. ### NightFrostMember

Joined:
Jun 24, 2016
Posts:
1,785
Since both are round, you don't need to do any collision checking. You just measure if the ball has moved over certain distance from the center of the circle, being the circle radius minus the ball radius. Bounce angle can be figured from the angle difference between the ball's current direction and its position's angle as measured from the center of the circle.

gdkid likes this.
3. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
Sounds like a good alternative, thanks a lot Nightfrost, will give it a try.

4. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
Hi @NightFrost

Just implement the code as you suggested

Code:
```dist = point_distance(ball.x,ball.y,room_width/2,room_height/2);

{
dir =point_directionball.x,ball.y,room_width/2,room_height/2);
hspeed = 8* cos(dir);
vspeed = 8* -sin(dir);

}```
It works, but not perfect, since the ball often "shake" a few times at the collision point (seems a bit weird) before bouncing back and moves

Do you have any suggestion where I can improve the code?

5. ### NightFrostMember

Joined:
Jun 24, 2016
Posts:
1,785
It could be that after turning around, the ball is still beyond the rebound distance due to rounding. A fix might be as simple as not testing for a new bounce on a step immediately after a bounce.

6. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
So should we use the Alarm to check this, like every 2-3 steps?

7. ### GMWolfaka fel666

Joined:
Jun 21, 2016
Posts:
3,315
Angles for bouncing gets complicated fast.

Use vectors!
I would normally recommend the impulse method, but a simple alternative is the penalty method.
It goes something like this:

Get the depth of the collision.
Code:
```var d = point_distance(ball.x, ball.y, room_width / 2, room_height / 2) - ball.radius;
```
If you want to collide with the inside of the circle, the reverse it
Code:
```d =global.radius - d;
```
Now find the collision normal. In our case it's quite simple:
Code:
```var nx = (room_width / 2) - ball.x;
var ny = (room_height / 2) - ball.y;
//Normalize
if(nx != 0 && ny != 0)
{
var nl = sqrt(sqr(nx) + sqr(ny));
nx /= nl;
ny /= nl;
}
```
now we can add a force in that direction proportional to the depth:
Code:
```var k = 0.2; //change k to get the response you need.
var fx = nx * d * k;
var fy = ny * d * k;

ball.hspeed += fx;
ball.vspeed += fy;
```

Hope this helps.

Last edited: Jul 9, 2019
gdkid likes this.
8. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
Thanks @GMWolf

I used the code in the Step event of object but it moves quite crazy (it doesn't bounce off the circle line )

As you suggested, the code is as follow (in Step Event)
Code:
```var d = point_distance(ball.x, ball.y, room_width / 2, room_height / 2) - ball.radius;

var nx = (room_width / 2) - ball.x;
var ny = (room_height / 2) - ball.y;
//Normalize
if(nx != 0 && ny != 0)
{
var nl = sqrt(sqr(nx) + sqr(ny));
nx /= nl;
ny /= nl;
}

var k = 0.2; //change k to get the response you need.
var fx = nx * d * k;
var fy = ny * d * k;

ball.hspeed += fx;
ball.vspeed += fy;```
Do we have to check the value of "d" before applying the normalize process and force?

9. ### GMWolfaka fel666

Joined:
Jun 21, 2016
Posts:
3,315
Yeah, you will want to check that you are actually colliding with the circle.
So you could check that d > 0 for example.

The code care right out of my head so it could be a little wrong, you might need to tweak it/debug it a little.

10. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
OK, I tweak the code a little bit
Code:
```var d = point_distance(ball.x, ball.y, room_width / 2, room_height / 2) ;

if (d >= (global.radius  - ball.radius)) //since the collision is inside the circle
{

var nx = (room_width / 2) - ball.x;
var ny = (room_height / 2) - ball.y;
//Normalize
if(nx != 0 && ny != 0)
{
var nl = sqrt(sqr(nx) + sqr(ny));
nx /= nl;
ny /= nl;
}

var k = 0.2; //change k to get the response you need.
var fx = nx * d * k;
var fy = ny * d * k;

ball.hspeed += fx;
ball.vspeed += fy;
}```
Now it works like a charm

Thank you so much you guys @GMWolf and @NightFrost

GMWolf likes this.
11. ### GMWolfaka fel666

Joined:
Jun 21, 2016
Posts:
3,315
Oh, I almost forgot, before you move on, it would be great if you made sure you understand what every line of code is doing.
If you are not sure what some of the code is doing or why, please ask! We would be happy to explain.

12. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32

Please explain your code, it seems brilliant, but I'm still not sure what it is doing

Starting from here

Code:
```var nx = (room_width / 2) - ball.x;

.....```

13. ### GMWolfaka fel666

Joined:
Jun 21, 2016
Posts:
3,315
You are going to need to ask more specific questions I'm afraid...
Here we are getting the difference between the ball position and the circle position.
If we do it for X and y, this gives us the direction between them (as a vector, in terms of X and y). After that we nornalize it (divide by its length) which makes it have a length of one. So nx and ny represent the direction from the ball to the circle. In other words, the direction of the collision, or 'collision normal'.

14. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
@GMWolf :Sorry for being vague

What I meant is, I need the explanation for the whole code starting from "var nx = (room_width / 2) - ball.x"

I'll ask questions next to the code (in comment form)

Code:
```// So at first we calculate the direction of the collision from the ball to the circle (nx and ny)

var nx = (room_width / 2) - ball.x;
var ny = (room_height / 2) - ball.y;

//Then we normalize it

if(nx != 0 && ny != 0) // Is this step checking if the ball is not in the center of the circle?
{
var nl = sqrt(sqr(nx) + sqr(ny)); // Correct me, is it a Pythagorean theorem ?
nx /= nl; // So this step is the normalization, I'm kind of noob about this, why do we divide nx and ny to nl?
ny /= nl;
}

var k = 0.2;
var fx = nx * d * k; //This one is brilliant, but I don't know about this formula, what dpes "k" stand for?
var fy = ny * d * k;

ball.hspeed += fx;
ball.vspeed += fy;
}```

15. ### GMWolfaka fel666

Joined:
Jun 21, 2016
Posts:
3,315
So yes, we are in essence calculating the distance to the ball along the X, and the Y axis separately.
(nx, ny) is a vector that represents the direction and distance from the ball to the circle. A vector is a direction and distance, but represented and the distance along X axis, and distance along Y axis.

Yes, that is the Pythagorean theorem! Exactly right! We use it the get the actual distance from ball to circle.

By dividing (nx, ny) by its length, we get a new vector with a length of 1. (x/x ==1 right? Here it's the same but we do it along X and y separately).
Making a vector have a length of one means it now only represents the direction, and we loose the length component of the vector. This is called normalizing. We do that because we care about the direction to apply the force in. The actual distance between the ball and circle doesn't matter.

That last equation is similar to the spring equation, or hooks law.
Basically we apply a force in the direction (nx, ny) proposal to how 'deep' the collision is.
K is a constant used to change how 'hard' the spring is. A value of 1 would represent a perfectly stuff collision. But in practice this ends up quite unstable, so we use a smaller value instead.

This is called the penalty method for collision response. You should find a lot of info about it online.
If you are interested in learning more, look at the impulse method. That is what games tend to use most often.

I would also recommend you learn vectors. Very useful tools in games programming.

The check we do is to check that the distance isn't 0. That is because dividing by 0 is not allowed.

Last edited: Jul 12, 2019 at 11:21 AM
gdkid likes this.
16. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
Now I got it

Thanks @GMWolf for your detailed explanation.

Will definitely take a look into vectors, sounds like a lot of fun.

17. ### gdkidMember

Joined:
Sep 22, 2016
Posts:
32
Hi @GMWolf

Is it possible if I add some random to the force applied to hx (or hy) ? Since the balls keep moving in the same direction back and forth through the center

var fx = nx * d * k * random_range(1.5,2.5);

18. ### GMWolfaka fel666

Joined:
Jun 21, 2016
Posts:
3,315
Yeah sure. The code you posted should do the trick. Though the values are a little high.
If you don't want the ball to speed up, you could add the random values to nx and ny before they are normalized

Joined:
Sep 22, 2016
Posts:
32