|
ricochets |
David Sopala
Member #5,056
September 2004
|
My current code for bouncing a bullet off of an arbitrary line in my game. Currently it does some odd things such as a bullet getting up to the line and stopping. Occasionally it bounces off the line then bounces off nothing hits the line again and does this for a while. Other times it works perfectly. Currently all my lines are horizontal or vertical, but I intend to add triangles to give the game a better feel instead of being square. does anyone see the issue I am overlooking in my code? 1void Bullet::Ricochet(C_Rect *r)
2{
3 C_Line Line;
4 x = x + ceil(speed * ((double)fcos(itofix(angle)) / 65536));
5 y = y + ceil(speed * ((double)fsin(itofix(angle)) / 65536));
6 C_Point Prev(x,y);
7
8 Line = r->Get_Closest_Line(Prev); //checks our position to all the lines will give us an answer which line we will hit.
9
10 if(!Line.Is_Horizontal())
11 {
12 int langle = Line.Get_Point1().Find_Fixed_Angle(Line.Get_Point2());
13 //to make my incidence line horizontal I will subtract my angle from the bullet's angle to get the angle of incidence.
14 int tangle = angle - langle; //this makes it seem as though we are hitting the x-axis of a graph. Basicly subtracted the angle from both sides of the equation one side (the line) is zero the other is the angle of approach of the bullet
15 if(tangle > 0 && tangle < 128)//hitting from the bottom
16 {
17 angle = 128 - tangle + langle;
18 }else //hitting from above
19 {
20 angle = 256 + tangle + langle;
21 }
22 }else
23 {
24 angle = 256 - angle;
25 }
26
27}
<img src="http://imgur.com/bfHvGkj.jpg" /> |
gnolam
Member #2,030
March 2002
|
You can start by not using Allegro angles for anything other than the final rotate_sprite()/pivot_sprite() call. They make the code hard to read, unnecessarily painful to write, and give you no performance benefits whatsoever. -- |
Schyfis
Member #9,752
May 2008
|
To me it sounds like sometimes your bullet is registering more than one collision on consecutive frames. This would explain the bouncing back and forth you're experiencing. Ideally it should only collide once, right? Try printing something in the console when a collision is detected and see if that's the problem. (i.e. two or more printed lines appear in the console) ________________________________________________________________________________________________________ |
David Sopala
Member #5,056
September 2004
|
Is cout still safe to use even with the graphics window open from allegro? Or is printf preferred? <img src="http://imgur.com/bfHvGkj.jpg" /> |
LennyLen
Member #5,313
December 2004
|
David Sopala said: Is cout still safe to use even with the graphics window open from allegro? Or is printf preferred? I'm not sure what you mean by safe, but they both use stdout, so they will both work equally.
|
David Sopala
Member #5,056
September 2004
|
I was trying to ask if I could still use it with allegro in the picture and not have issues. -I did a data dump to a file to trace the bullet, it is bouncing off the same wall multiple times. Although my calculations seem to be working - at the very least. Never done any math like what I am using here that I can remember anyways everything was applied to electronics and such back in college and not to programming or arbitrary angles and the like. Very very close to the code working correctly... although I am having some issues on one wall segment for some reason, it is like it doesn't even try to bounce it flys through, but does the ricochet calculations many many times on the bullet, but never fixes the issue. 1void Bullet::Ricochet(C_Rect *r)
2{
3 C_Line Line;
4 x = x + ceil(speed * ((double)fcos(itofix(angle)) / 65536));
5 y = y + ceil(speed * ((double)fsin(itofix(angle)) / 65536));
6 C_Point Prev(x,y);
7
8 Line = r->Get_Closest_Line(Prev); //checks our position to all the lines will give us an answer which line we will hit due to no lines with angles > 90 lines of a rect always shield the other lines.
9 int langle = 0;
10 if(!Line.Is_Horizontal()) //we need to rotate the line to a horizontal position
11 {
12 langle = Line.Get_Point1().Find_Fixed_Angle(Line.Get_Point2());
13 angle = angle - langle; //to give us the new angle of approach
14 }
15 //at this point the line is horizontal and the bullet is ready to be fixed.
16 angle = 256 - angle;
17 angle += langle;
18}
I am clueless as to why my test situation was acting weird doing what I said - I randomly thought to myself screw it I will make one big wall all by itself out there in the world and see if it is a clipping issue or something - well one big wall works fine... maybe my lines were too close or something with lots of little walls :/ Well maybe one day this code will help someone else it seems to be working perfectly now. <img src="http://imgur.com/bfHvGkj.jpg" /> |
decepto
Member #7,102
April 2006
|
Hi David, I'm not sure what the "horizontal position" part of your code is trying to do, but I might be able to help with your overall goal. All of the data required to simulate and render a ricochet can be calculated using some rather simple mathematics. Try the following: 1. Think of your wall (or object which the bullet will bounce off) as a line or line segment, W. 2. Think of your bullet (and it's initial path) as a line, L. 3. Perform an intersection test between L and W. We'll call their intersection point P. 4. If L and W intersect, calculate L's normal vector. This is easy, it just involves changing the sign of one of the components. From this vector and the point of intersection, we can build another line which represents the bullets first ricochet path. We'll call this line R1. So, now you have four pieces of data: R1 is the bullet's first ricochet path. You could continue to calculate ricochets off other walls if you wish. This is exactly how one builds a billiards game. All of these calculations should be done before any animation or rendering takes place. From my understanding, you don't often work with mathematical code. However, I would strongly suggest you take this approach. You code will be much shorter, easier to follow, and easier to change. Since you're using C++, I would highly recommend using GLM as a math library. It's a header only library, so no need for compilation. Intersection testing is this most difficult part of this process. It's a large area of research when you get into higher dimensions and more complex shapes. However, testing for a Line/Line intersection is fairly painless. edit A quick method for performing Line/Line intersection is to take the cross product of two vectors, which is effectively the determinant. The lines don't intersect if their parallel. In all other cases, they do intersect...somewere. If the determinant is Zero, the lines are parallel. float det = glm::cross( glm::vec3(1, 0, 0), glm::vec3(1, 0, 0) ) if ( det == 0 ) { // lines are parallel, no intersection } else { // lines are _not_ parallel, but where do they intersect // next, find intersection point of lines ... }
-------------------------------------------------- |
David Sopala
Member #5,056
September 2004
|
I wrote all my line - line point comparison code and the like myself from my research. Looks like your functions are coded for 3D space which is nice, but not something I want to dive into before my long vacation in October so I have time to learn whats going on. The line - line intersection code is: 1bool C_Line::Lines_Intersect(C_Line l)
2{
3
4 C_Point A = p;
5 C_Point B = p1;
6 C_Point C = l.Get_Point1();
7 C_Point D = l.Get_Point2();
8
9 int x1 = A.Get_X();
10 int x2 = B.Get_X();
11 int x3 = C.Get_X();
12 int x4 = D.Get_X();
13
14 int y1 = A.Get_Y();
15 int y2 = B.Get_Y();
16 int y3 = C.Get_Y();
17 int y4 = D.Get_Y();
18
19
20 float denom = ((y4 - y3)*(x2 - x1)) - ((x4 - x3)*(y2 - y1));
21 if(denom == 0)return false;
22 float ua = ((x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3)) / denom;
23 float ub = ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3)) / denom;
24
25 if(ua <= 1 && ua >= 0 && ub <= 1 && ub >= 0)return true;
26 else return false;
27}
Cross product? Yea I got that too. float C_Point::Dot_Product(const C_Point &p) { return ((x * p.x) + (y * p.y)); } float C_Point::Cross_Product(const C_Point &p) { return (x * p.y) - (y * p.x); } Note you can take the primary line normalize x1 and x2 to the origin and then multiply by the ua factor then add that back to the first x1 to get the x intersect. Works as well with the y coordinate with ub I believe. The reason my code was written how it is was because normally I am checking vs shapes in the game loop, see how this function takes a rectangle? My goal was to write code that would handle the bounce properly and it does although I think your might be better designed to push two objects away from each other(like in pool when two balls hit they both move.) Currently this is working better I still need to code a few things, but I am a lot closer to what my goal is now. I just need to rotate some shapes now and I will be all set. <img src="http://imgur.com/bfHvGkj.jpg" /> |
|