Java-Gaming.org    
Featured games (78)
games approved by the League of Dukes
Games in Showcase (430)
Games in Android Showcase (89)
games submitted by our members
Games in WIP (468)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Another collision question  (Read 3721 times)
0 Members and 1 Guest are viewing this topic.
Offline CyanPrime
« Posted 2011-03-28 05:37:00 »

This is over my head, can someone explain it to me better? http://mathworld.wolfram.com/Reflection.html

I'm making a 2d breakout fighting game, so I need the ball to be able to reflect when it hits a wall, paddle, or enemy (or a enemy hits it).

all their formula's are like: x_1^'-x_0=v-2(v·n^^)n^^.

And I can't fallow that. (What does ' mean or x_0? or ^^?)
Offline bobjob

JGO Knight


Medals: 10
Projects: 4


David Aaron Muhar


« Reply #1 - Posted 2011-03-28 06:30:42 »

A paddle war game should be considerably simple.

Currently how are you doing your collision? Rectangles or does the game support diagnal lines?

If no diagnal lines, then all you need to do is negate the direction of the ball on one of the axis, like if the game flow is up and down, then just negate on the y axis. And if it hits a side wall negate the x axis.

Also take into consideration either: the momentum of the paddle when the ball is hit, or the area on which the ball hit that paddle. This will make a sharper angle, depending on how you want the game to feel.

If you are using diagnal line collisions, then it will work a little differently.


My Projects
Games, Webcam chat, Video screencast, PDF tools.

Javagaming.org with chat room
Offline CyanPrime
« Reply #2 - Posted 2011-03-28 06:35:19 »

Well, it's going to be you vs a boss. Kinda like this: http://www.youtube.com/watch?v=jo5tW7fk1sc

There are no diagonal lines, but if the boss swats the ball I would need to know the angle he hit the ball at, and make it go flying in the reverse angle. That's why I'm trying to make the collision detection so complicated.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline bobjob

JGO Knight


Medals: 10
Projects: 4


David Aaron Muhar


« Reply #3 - Posted 2011-03-28 06:42:36 »

that game is really cool. I thought you ment a paddle war, but this seems more like a pinball machine.

In that case you would need to make the ball entity store an angle (direction it is moving) and a momentum value to store its speed.

then apply a gravity value on each game cycle.

are you familar with line equations (eg. y = mx + c)?

My Projects
Games, Webcam chat, Video screencast, PDF tools.

Javagaming.org with chat room
Offline CyanPrime
« Reply #4 - Posted 2011-03-28 07:04:03 »

No, no. Mine's a paddle game.

Nope, don't know what that formula means at all.

This is what I got for my collision right now, but the ball just stops when it hits a wall.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
for(int i = 0; i < wall.length; i++){
         if(new Rectangle((int) position.x, (int) position.y, size, size).intersects(new Rectangle(wall[i].x, wall[i].y, wall[i].width, wall[i].height))){
            Vector2f rvelo = velo.copy(); //get velo (direction)
           rvelo.set(rvelo.x*-1, rvelo.y*-1); //reverse it for back tracking
           
            position.add(rvelo);
            Vector2f prevpos = position.copy();
            prevpos.add(velo);
            System.out.println("Angle: " + Math.toDegrees(Math.atan2(-(position.x -prevpos.x), (position.y - prevpos.y))));
           
            velo.x = (float) (Math.sin(Math.atan2(-(position.x -prevpos.x), (position.y - prevpos.y))) * 5);
            velo.y = (float) (Math.cos(Math.atan2(-(position.x -prevpos.x), (position.y - prevpos.y))) * 5);
           
            //position.x += (wall[i].x + wall[i].width) - position.x;
           //velo.x = -velo.x;
           accel = velo.scale(speed);
            velo.add(accel);
             
         }
      }
Offline lhkbob

JGO Knight


Medals: 32



« Reply #5 - Posted 2011-03-28 08:41:33 »

The ^ symbol over the n in the variable names is a common symbol for a normalized vector.  If the variable doesn't have a ^, then in the equations in that link, it represents a point.  When you subtract two points, you get a vector representing the difference.  The ' symbol is just part of the variable name, it usually symbolizes "new version".  So x1' means the new x1, or in this case the reflected x1.

Another way to write the reflection equation (x1' = -x1 + 2x0 + 2n[(x1-x0)•n]) in a more programmatic way is:
1  
2  
3  
4  
Vector2f dir = ...
Vector2f n = dir.normalize();

Vector2f reflected = x0.scale(2).sub(x1).add(n.scale(2 * dot(n, x1.sub(x0)));


In the above example, x0 and x1 are the points in the diagram from the link, but they're stored as the same Vector2f type.  Vector2f is a type I made up for this example, the methods used are scale(float), sub(Vector2f), add(Vector2f), normalize() and dot(Vector2f, Vector2f).  These are all vector math operations that are pretty easy to implement.  In this code, I'm assuming that a new Vector2f is created by each operation so that the proper order of operations is preserved.

HTH

Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #6 - Posted 2011-03-28 11:41:53 »

Does dot product mean multiplying 2 vectors?
And what does normalize really mean?

Offline DzzD
« Reply #7 - Posted 2011-03-28 12:18:33 »

Does dot product mean multiplying 2 vectors?
And what does normalize really mean?

dot product is :
 dotProduct= x1*x2+y1*y2+z1*z2
or
 dotProduct= |V1| * |V2| * cos(angleBetweenV1AndV2)

it is especially usefull to find angle between two vectors, or to make a projection of one vector onto another (changing frame of reference)

normalizing is an operation that make the final vector 1 unit lenght by dividing all its components by the initial vector length :
 vectorLength=sqrt(x*x+y*y+z*z);
 x/=vectorLength
 y/=vectorLength
 z/=vectorLength

Offline refri89

Senior Newbie





« Reply #8 - Posted 2011-03-28 12:30:13 »

.
Online Roquen
« Reply #9 - Posted 2011-03-28 17:30:40 »

I'm assuming this is actually 2D and not 3D.  It's easy to just remember that:  "The angle of incidence equals the angle of reflection".  So the angle (with respect to the normal of the surface) that the ball strikes the surface is the same as the angle that it will move away from the surface, on the opposite side of the normal.  In break-out style games, most of the surfaces will be aligned to an axis and the "equation" is simple:  Striking the top/bottom = negate y (assuming y is up/down) and likewise striking the sides negates x.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline CyanPrime
« Reply #10 - Posted 2011-03-28 22:29:06 »

x0 and x1 are the points in the diagram from the link
Everything looks good so far, but I can't figure out what points x0 and x1 are, and what they mean. I think x0 is 0,0 bu I have no idea what to put for x1. This is my code (Using slick2d's Vector2f class)

1  
2  
3  
4  
5  
6  
Vector2f n = velo.normalise();
            Vector2f x0 = new Vector2f(0,0);
            Vector2f x1 = new Vector2f(0,0);
           
            Vector2f reflected = x0.scale(2).sub(x1).add(n.scale(2 * n.dot(x1.sub(x0))));
            velo = reflected.copy();
Offline avm1979
« Reply #11 - Posted 2011-03-28 23:02:05 »

x0 is the point where the collision occurs.

n is the line which the ball hit (i.e., one of the 4 edges of the rectangle you're checking against).  x0 is on that line.

Looking at your code, it doesn't seem like you're computing the actual collision point, just that a collision actually occurred.  That's not enough to compute reflection, though you could possibly hack around it.

... also, you're setting both x0 and x1 to (0, 0) and then doing stuff with them like scaling.


In your case, if I understand correctly, all of the wall pieces are aligned with the x and y axis.  If so, all you have to do is flip the x or y component of your velocity, depending on whether the wall piece you are checking against is to the left/right/above/below the ball.  For example, if it's above or below the ball, you'd flip the y component. 

You might get into trouble if multiple collisions are detected - but that's going to be tricky regardless of what you do.


I'd also suggest taking a step back to try and really understand the math. Vectors are very useful.

Offline CyanPrime
« Reply #12 - Posted 2011-03-28 23:39:01 »

Anyone know why this collision for my enemy doesn't work right? It seems when hit from the side it goes through him instead of bouncing off.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
if(new Rectangle((int) position.x, (int) position.y, size, size).intersects(
new Rectangle((int) enemy.x, (int) enemy.y, enemy.width, enemy.height))){
         if(position.y + size >= enemy.y && position.y + size <= enemy.y + (enemy.height/6))
            velo.y = -velo.y;
         
         else if(position.y <= enemy.y + enemy.height && position.y >=
enemy.y + enemy.height - (enemy.height/6))
            velo.y = -velo.y;
         
         else
            velo.x = -velo.x;
         
         enemy.hp--;
      }
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #13 - Posted 2011-03-28 23:50:22 »

Sorry to be so intrusive, but I merged your topics.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline CyanPrime
« Reply #14 - Posted 2011-03-29 00:08:34 »

That's fine. But this last question wasn't using reflection, or even trying to ^^;
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 613
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #15 - Posted 2011-03-29 00:09:39 »

I merged it because you're littering JGO. You shouldn't start a new thread for every tiny problem you run into.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline CyanPrime
« Reply #16 - Posted 2011-03-29 00:15:53 »

Fair enough. +1 rep.
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #17 - Posted 2011-03-29 00:33:09 »

Fair enough. +1 rep.
Whaattt? Y did u give him a rep?!? He has too many alreadddyy Angry

Wink Grin

Offline appel

JGO Wizard


Medals: 49
Projects: 4


I always win!


« Reply #18 - Posted 2011-03-29 01:22:30 »

This is why I prefer to have x,y of my entities as the center point, and not the top-left point.

If you have two rectangles intersecting, and you know the center point of both of them, and the width and height outward from the center point, you can simply check if x+width of A reaches beyond x-width of B to check if right side of A goes over the left side of B.

You do the same for all the sides: (size being the distance from centre to any side)

Check if x+size of A reaches beyond x-size of B to check if right side of A goes over the left side of B.
if Ax+size > Bx-size: Aright hit Bleft.

Check if x-size of A reaches beyond x+size of B to check if left side of A goes over the right side of B.
if Ax-size > Bx+size: Aleft hit Bright.

Check if y+size of A reaches beyond y-size of B to check if bottom side of A goes over the top side of B.
if Ay+size > By-size: Abottom hit Btop.

Check if y-size of A reaches beyond y+size of B to check if top side of A goes over the bottom side of B.
if Ay-size > By+size: Atop hit Bbottom.

You should try to visualize this using two cubes or rectangular shapes in the real world, e.g. with some cards. There are only four ways for the rectangles to collide, left to right, right to left, top to bottom, bottom to top. (that is if they don't rotate)

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline appel

JGO Wizard


Medals: 49
Projects: 4


I always win!


« Reply #19 - Posted 2011-03-29 11:50:45 »

btw. you need to ensure that your game uses a fixed step delta.

If the objects were to move using delta 3, collision is detected and direction is reversed.
Then the objects were updated to move using delta 1, then you would again have a collision and you would reverse direction again!

If the delta is always 1, or 3, then you would not encounter this.

But there are other ways to solve this as well.

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline CyanPrime
« Reply #20 - Posted 2011-03-29 23:51:07 »

Back to The Future Reflection!

I asked a question on stackoverflow, and I got this for a answer: http://stackoverflow.com/questions/5476384/how-do-i-calculate-a-normal/5476665#5476665

Now, I am just lost, so the first thing I am going to ask is what all do I need to keep track of for the
Wall, and in what format, in order reflect things off it?
Offline CyanPrime
« Reply #21 - Posted 2011-03-30 00:34:18 »

After talking to MatthiasM on IRC I got to this point, but it doesn't seem to work Sad The ball goes right through the paddle.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
if(velo.y > 0){
         float t = position.distance(paddle.position)/ velo.y;
         t -= size/2;
         
         if(t <= 1.0){
            if(velo.x * t >= paddle.position.x && velo.x * t <= paddle.position.x + paddle.width){
               velo.y = -velo.y;
            }
         }
      }


Correct code:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
if(velo.y > 0){
         float t = ((position.y - radius) - paddle.position.y)/ velo.y;
         
         float ballHitX = position.x + velo.x * t;
         
         if(t <= 1.0){
            if(ballHitX >= paddle.position.x && ballHitX <= paddle.position.x + paddle.width){
               velo.y = -velo.y;
            }
         }
      }

Offline CyanPrime
« Reply #22 - Posted 2011-03-30 03:34:03 »

ARG! Why isn't my top collision working right? (the ball goes up when under the paddle, and down when not)

1  
2  
3  
4  
5  
6  
7  
if(velo.y < 0){
            float t = ((position.y - radius) - (wall[2].y + wall[2].height))/ velo.y;
           
            if(t <= 1.0){
            velo.y = -velo.y;
            }
         }
Offline CyanPrime
« Reply #23 - Posted 2011-03-30 05:27:15 »

Fixed it!
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
if(velo.y < 0){
            float t = ((position.y - radius) - (wall[2].y + wall[2].height))/ velo.y;
           
            //float ballHitX = position.x + velo.x * t;
           
            if(t >= 1.0){
               //if(ballHitX >= paddle.position.x && ballHitX <= paddle.position.x + paddle.width){
                 velo.y = -velo.y;
               //}
           }
         }
      //}
     
      if(velo.y > 0){
         float t = ((position.y + radius) - paddle.position.y)/ velo.y;
         
         float ballHitX = position.x + velo.x * t;
         
         if(t >= 1.0){
            if(ballHitX >= paddle.position.x && ballHitX <= paddle.position.x + paddle.width){
               velo.y = -velo.y;
               System.out.println("hit paddle");
            }
         }
      }
Offline CyanPrime
« Reply #24 - Posted 2011-03-30 09:47:50 »

Can someone tell me whats wrong with my collision? After I added in the enemy parts it just went haywhire.
Here is the entire ball class code, please help me  Cry

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
import java.awt.Rectangle;

import org.newdawn.slick.geom.Vector2f;


public class Ball {
   //int diameter = 30;
  int radius = 15;
   float speed = 1f;
   float maxSpeed = 3;
   
   float angle;
   
   Vector2f position;
   Vector2f velo;
   Vector2f accel;
   
   public Ball(){
      velo = new Vector2f(-1,1);
      velo.scale(speed);
     
      position = new Vector2f(640/2 - radius, 300);
     
      accel = new Vector2f(0,0);
      //accel.scale(speed);
  }
   
public void move(Wall[] wall, Paddle paddle, Enemy enemy){
     
      position.add(velo);
     
      //for(int i = 0; i < wall.length; i++){
        if(velo.y < 0){
            float t = ((position.y - radius) - (wall[2].y + wall[2].height))/ velo.y;
           
            float ballHitX = position.x + velo.x * t;
           
            if(t >= 1.0){
               if(ballHitX >= wall[2].x && ballHitX <= wall[2].x + wall[2].width){
                  velo.y = -velo.y;
                  accel = velo.scale(speed);
                  velo.add(accel);
                 
                  if(velo.x > maxSpeed)
                     velo.x = maxSpeed;
                 
                  if(velo.y > maxSpeed)
                     velo.y = maxSpeed;
                  System.out.println("hit top");
               }
            }
         }
      //}
     
      if(velo.y > 0){
         float t = ((position.y + radius) - paddle.position.y)/ velo.y;
         
         float ballHitX = position.x + velo.x * t;
         
         if(t >= 1.0){
            if(ballHitX >= paddle.position.x && ballHitX <= paddle.position.x + paddle.width){
               velo.y = -velo.y;
               System.out.println("hit paddle");
            }
         }
      }
     
      //for(int i = 0; i < wall.length; i++){
        if(velo.x < 0){
            float t = ((position.x - radius) - (wall[0].x + wall[0].width))/ velo.x;
           
            float ballHitY = position.y + velo.y * t;
           
            if(t >= 1.0){
               if(ballHitY >= wall[0].y && ballHitY <= wall[0].y + wall[0].height){
                  velo.x = -velo.x;
                  accel = velo.scale(speed);
                  velo.add(accel);
                 
                  if(velo.x > maxSpeed)
                     velo.x = maxSpeed;
                 
                  if(velo.y > maxSpeed)
                     velo.y = maxSpeed;
                  System.out.println("hit LWall");
               }
            }
         }

         if(velo.x > 0){
            float t = ((position.x + radius) - wall[1].x)/ velo.x;
           
            float ballHitY = position.y + velo.y * t;
           
            if(t >= 1.0){
               if(ballHitY >= wall[1].y && ballHitY <= wall[1].y + wall[1].height){
                  velo.x = -velo.x;
                  accel = velo.scale(speed);
                  velo.add(accel);
                 
                  if(velo.x > maxSpeed)
                     velo.x = maxSpeed;
                 
                  if(velo.y > maxSpeed)
                     velo.y = maxSpeed;
                  System.out.println("hit RWall");
               }
            }
         }
         
         //enemy col start
        if(velo.y < 0){
            float t = ((position.y - radius) - (enemy.y + enemy.height))/ velo.y;
           
            float ballHitX = position.x + velo.x * t;
           
            if(t >= 1.0){
               if(ballHitX >= enemy.x && ballHitX <= enemy.x + enemy.width){
                  velo.y = -velo.y;
                  accel = velo.scale(speed);
                  velo.add(accel);
                 
                  if(velo.x > maxSpeed)
                     velo.x = maxSpeed;
                 
                  if(velo.y > maxSpeed)
                     velo.y = maxSpeed;
                  System.out.println("hit top");
               }
            }
         }
         
         if(velo.x < 0){
            float t = ((position.x - radius) - (enemy.x + enemy.width))/ velo.x;
           
            float ballHitY = position.y + velo.y * t;
           
            if(t >= 1.0){
               if(ballHitY >= wall[0].y && ballHitY <= enemy.y + enemy.height){
                  velo.x = -velo.x;
                  accel = velo.scale(speed);
                  velo.add(accel);
                 
                  if(velo.x > maxSpeed)
                     velo.x = maxSpeed;
                 
                  if(velo.y > maxSpeed)
                     velo.y = maxSpeed;
                  System.out.println("hit LWall");
               }
            }
         }

         if(velo.x > 0){
            float t = ((position.x + radius) - enemy.x)/ velo.x;
           
            float ballHitY = position.y + velo.y * t;
           
            if(t >= 1.0){
               if(ballHitY >= wall[1].y && ballHitY <= enemy.y + enemy.height){
                  velo.x = -velo.x;
                  accel = velo.scale(speed);
                  velo.add(accel);
                 
                  if(velo.x > maxSpeed)
                     velo.x = maxSpeed;
                 
                  if(velo.y > maxSpeed)
                     velo.y = maxSpeed;
                  System.out.println("hit RWall");
               }
            }
         }
         
         if(velo.y > 0){
            float t = ((position.y + radius) - enemy.y)/ velo.y;
           
            float ballHitX = position.x + velo.x * t;
           
            if(t >= 1.0){
               if(ballHitX >= paddle.position.x && ballHitX <= enemy.x + enemy.width){
                  velo.y = -velo.y;
                  accel = velo.scale(speed);
                  velo.add(accel);
                 
                  if(velo.x > maxSpeed)
                     velo.x = maxSpeed;
                 
                  if(velo.y > maxSpeed)
                     velo.y = maxSpeed;
                  System.out.println("hit paddle");
               }
            }
         }
         //enemy col end
  }
Offline CyanPrime
« Reply #25 - Posted 2011-03-30 21:54:36 »

Fixed it! had to switch
1  
if(Math.abs(t) >= 1.0){


to

1  
if(Math.abs(t) <= 1.0){
Offline Captain Awesome

Junior Member


Medals: 2


Hi


« Reply #26 - Posted 2011-03-30 22:13:16 »

Fixed it! had to switch
1  
if(Math.abs(t) >= 1.0){


to

1  
if(Math.abs(t) <= 1.0){


+rep for solving your own problem  Wink
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

theagentd (6 views)
2014-04-24 23:00:44

xsi3rr4x (83 views)
2014-04-15 18:08:23

BurntPizza (75 views)
2014-04-15 03:46:01

UprightPath (86 views)
2014-04-14 17:39:50

UprightPath (69 views)
2014-04-14 17:35:47

Porlus (86 views)
2014-04-14 15:48:38

tom_mai78101 (109 views)
2014-04-10 04:04:31

BurntPizza (169 views)
2014-04-08 23:06:04

tom_mai78101 (265 views)
2014-04-05 13:34:39

trollwarrior1 (217 views)
2014-04-04 12:06:45
Escape Analysis
by Roquen
2014-04-25 10:38:58

Escape Analysis
by Roquen
2014-04-25 10:22:13

List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!