Determine what side of rectangle is hit by ball

Started by
15 comments, last by Dovakhiin 7 years, 11 months ago

k := ( t - t0 ) / ( t1 - t0 ) so that 0 <= k <= 1 within the last time step,

we can say

pb(k) := pb(t0) + k * ( pb(t1) - pb(t0) )

pp(k) := pp(t0) + k * ( pp(t1) - pp(t0) )

How I wish I could understand it clearly as you. Im pretty bad at math especially reading a formula and then converting to code. Although I can understand basics of vectors and a little trig. I still coudnt read math signs and formula in your answer. If I can get where the exactly collision takes place and which side, then this will help me a lot. But sadly, its just too foreign for me to read this kind of thing. I really dont understand this following. Might help if you can explain this to me. TY

pb(k) -- I call it Player Ball(Pb) but what is (K) doing there? is it to multiply or something?

:= -- is this some condition on math?

[ -w/2 +h/2 ]T -- what is the T here? Is this the same t? or is it different? and are you denoting this as an exponent? or does it meant something else?

k' -- this I sometimes see a lot the ' thing. What does it meant by this?

I notice about the radius. I guess, this is applied for Bounding-circle collision? I didnt go any complicated, I just use two rectangles(AABB).

Advertisement

// If the right side of the ball hit the left side of the paddle and the height of the ball is greater than the paddle's y position
               if (Position.X + Width > catcher.Position.X    && Position.Y + Height > catcher.Position.Y + (catcher.Height / 2))

This code doesn't do what you say, the "x" part is missing "left side".

Position.x + Width // right side of the ball

catcher.Position.X // left side of the paddle

So right-side ball > left-side paddle, but there is no upper limit in your condition, ie even at the right edge of the screen this holds.

Likewise, the second 'if' holds for the ball left side to be anywhere to the left of the center of the paddle, ie at the left of the screen. The second condition isn't about the right side at all!!!

Do you make drawings of the precise area in these cases? I find it often helps if I draw the situation, with the expressions to calculate each relevant point in the drawing.

[attachment=31865:ballcatcher.png]

Since you're using both left-side and right-side of ball, I would guess you'll have a problem in the middle where either both conditions hold, or none of them holds. Don't know if that is intentional. You can get out of it by always using the center of the ball, but that may not be what you desire.

How I wish I could understand it clearly as you. Im pretty bad at math especially reading a formula and then converting to code. Although I can understand basics of vectors and a little trig. I still coudnt read math signs and formula in your answer. If I can get where the exactly collision takes place and which side, then this will help me a lot. But sadly, its just too foreign for me to read this kind of thing. I really dont understand this following. Might help if you can explain this to me. TY

pb(k) -- I call it Player Ball(Pb) but what is (K) doing there? is it to multiply or something?

:= -- is this some condition on math?

[ -w/2 +h/2 ]T -- what is the T here? Is this the same t? or is it different? and are you denoting this as an exponent? or does it meant something else?

k' -- this I sometimes see a lot the ' thing. What does it meant by this?

I notice about the radius. I guess, this is applied for Bounding-circle collision? I didnt go any complicated, I just use two rectangles(AABB).

pb(k) means a vector (the bold letter) p which denotes a position in space, with an identifying index b (set in subscripted style) denoting that the position is that of the ball, and an independent variable k (written in parentheses) denoting that the position is not constant but varies with k. Due to the conditional 0 <= k <= 1 the value of k is restricted to be between 0 and 1, inclusively. In summary: The position of the ball at moment k is … (whatever is written in the following).

pb(t0) is hence to be read as position of the ball at moment t0. Since we defined that t0 denotes the moment in time at the previous update of the game and t1 denotes the moment in time of the current update, the time t ticked from t0 to t1 in the meanwhile. The normalization formula shown in the former post makes it just a bit easier to deal with this, because when setting t = t0 the normalization gives a value of k = 0, and setting t = t1 gives a value of k = 1. So, while time t ticked from t0 to t1, the equivalent k ticked from 0 to 1. Hence: pb(k) with 0 <= k <= 1 denotes all the positions where the ball was in the time that has elapsed between the previous update and the current update. All those positions form a straight line segment. Of course, the ball was not really there because you have computed only pb(t0) and pb(t1), but the collision impact was somewhere in the interval between t0 and t1 and hence we need to look at all the inbetween positions.

pp(k) is to be read identically to pb(k) but with the identifying index p denoting that this is the varying position of the paddle.

The sign := means that we define the term on the side of the : by the formula on the side of the =, i.e. "a := b + c" is read "a is defined as b plus c". For all practical purposes, it can be used like an equation "a = b + c". It just expresses that another term (here "a") is introduced.

The notion [ a b ]T means a 2D vector with elements a and b, written as a row vector (elements side-by-side) and being transposed (denoted by the superscripted T). A transposed row vector results in a column vector, i.e. the elements are written one over the other. Since side-by-side writing is much simpler to be used with, well, typesetter text, using it with the transpose operator is just for convenience.

The apostrophe is used with many different meanings. In my post it just means "a specific value of k" (here k') to make a distinction to the "a variable value k" (just k).

Using a circle instead of an aligned box is often easier. In the given case, it is definitely easier, and it gives more accurate results at the paddle corners! I suggest you to use it.

Of course, feel free to ask if something isn't clear...

Of course, feel free to ask if something isn't clear...

Hi, Ive been trying to convert your formula to code. Im not sure if this is correct?


currentDeltaTime = deltatime;


          //k:= (t - t0) / (t1 - t0)  so that  0 <= k <= 1 within the last time step,
          float k = (currentDeltaTime - prevDeltatime) / (currentDeltaTime - prevDeltatime);


          //   pb(k) := pb(t0) + k * ( pb(t1) - pb(t0) )
          Position = prevPosition + k * (Position - prevPosition);

          //pp(k) := pp(t0) + k * (pp(t1) - pp(t0))
          catcher.Position = catcherPrevPosition + k * (catcher.Position - catcherPrevPosition);

          // ctl(k) := pp(k) + [-w / 2 + h / 2]T
          Vector2 ctl = catcher.Position + new Vector2(-catcher.Width /2,catcher.Height / 2);

          // ctr(k) := pp(k) + [+w / 2 + h / 2]T
          Vector2 ctr = catcher.Position + new Vector2(catcher.Width / 2, catcher.Height / 2);


          // cbl(k) := pp(k) + [-w / 2 - h / 2]T
          Vector2 cbl = catcher.Position + new Vector2(-catcher.Width / 2, -catcher.Height / 2);


          // cbr(k) := pp(k) + [+w / 2 - h / 2]T
          Vector2 cbr = catcher.Position + new Vector2(catcher.Width / 2, -catcher.Height / 2);



          prevDeltatime = currentDeltaTime;
          prevPosition = Position;
          catcherPrevPosition = catcher.Position;

Basically, I just copied your formula and try to convert it to code base on how I understand it(How I understand your explanation on your 2nd post).

Although the next part was just an example, can you help me convert it to code?

el(k,f) := cbl(k) + f * ( ctl(k) - cbl(k) ) = cbl(k) + f * [ 0 h ]T w/ 0 <= f <= 1

The f here is kinda magic. I dont know where it came from?

There are some mistakes in your conversion (notably: "t" without a number is not currentDeltaTime, it is the time at which the collision occurs). Your current code would always have k = 1*.

The magic f is just a variable that exists solely to ensure that a line segment is output instead of an infinite line.

However, I still have a feeling this is a lot more complicated than it probably needs to be.


*or divide by zero if currentDeltaTime and prevDeltaTime were equal.

---

While there might be edge cases where the following is not true, I would imagine this would work in most simple cases involving linear motion, and it should be fairly quick to implement/test:

Keep track of the ball's previous position (i.e. last frame's position) and the paddle's previous position, and whether a collision occurred in the previous frame.

If an intersection occurs, and there was no intersection in the previous frame, compare the positions of the paddle and the ball in the previous frame.

If the ball was to the left of the paddle in the previous frame, collision occurred on the left side of the paddle. Conversely, if the ball was to the right of the paddle before the collision occured, collision occured on the right side of the paddle.

Hello to all my stalkers.

...
Basically, I just copied your formula and try to convert it to code base on how I understand it(How I understand your explanation on your 2nd post).

Ugh, that's not the way to go. Much of the stuff as was written is for explanation and derivation of the solution. The approach to convert this stuff into code is to pick the formulas usable to solve for a variable (here k' and eventually f'), derive the solution on paper, decide which variables are worth to be coded separately, and write all that as code.

...
The f here is kinda magic. I dont know where it came from?

Lactose! has answered this correctly.

However, I still have a feeling this is a lot more complicated than it probably needs to be.

It is too complicated just to decide on which side the collision happened, that's true. However, I think the game mechanics requires to reflect the ball. Doing this appropriately requires more information than just the side. The full solution requires the location of collision in space, and that is the matter shown in my approach.

Hi, Thanks everyone. I really wanted to implement that math thing to code. Its really really hard. I just dont know how to implement it. Might be because I still lack experience. I hope though sooner or later I will learn how to just look at the formula and have an idea on how to implement it to code

. Anyway I just did something really really simple.


if (Position.X + Width > catcher.Position.X  && Position.X < catcher.Position.X + catcher.Width / 2   && Position.Y + Height > catcher.Position.Y + (catcher.Height / 2))
                    {
                        Debug.WriteLine("hit at side");
                        Position = new Vector2(catcher.Position.X - Width, Position.Y); // place the ball on the side where it hits(left side of paddle) before bouncing the ball downwards
                        Direction = new Vector2(-1, -Direction.Y);  // bounce the ball downwards

                        //Speed = 0f;
                    }
                  

                    // If the Left side of the ball hit the Right side of the paddle and the height of the ball is greater than the paddle's y position
                    else if (Position.X < catcher.Position.X + catcher.Width  && Position.X > catcher.Position.X + catcher.Width / 2 && Position.Y + Height > catcher.Position.Y + (catcher.Height / 2))
                    {
                        Debug.WriteLine("hit at right side");
                        Position = new Vector2(catcher.Position.X + catcher.Width, Position.Y); // place the ball on the side where it hits(the right side of paddle) before bouncing the ball downwards
                        Direction = new Vector2(-1, -Direction.Y); // bounce the ball downwards
                        //Speed = 0f;

                    }

I just basically check if the balls position is greater than the paddles X position and less than the paddles width in half. Same in the right side of paddle. I got a feeling this might not be the best work around for this but this is just on my level of my understandings.

This topic is closed to new replies.

Advertisement