Ok this is a kind of complicated subject I'm trying to work with.
Basically, I want to have collision detection, that given an arbitrary non-polygonal background obstactle that a player is colliding with, can return the vector of PROPER reflection. So if you throw a ball at a wall, it bounces back at a reflection over the perpendicular to the wall.
With flat, X/Y aligned horizontal/vertical platforms this is very easy, as it will always be either simply inverting the X or Y vector properties. However, at oddly shaped, oddly angled, or curved objects, this becomes very difficult to figure out.
Now I don't have any problems calculating the reflected vector once I've determined the angle of incidences; its simply a matter of finding the difference of the angle of the projectile BEFORE striking and the angle of incidence, and adding that to the angle of incidence, and then recalculating a vector of the same scalar distance from that position at that angle.
That much is easy, even if it sounds confusing. The problem, however, lies in trying to FIND this angle of incidence. This is where some ingenuity is required. With conventional game programming, in a 3d environment, you'll always have a polygonal obstactle where a sprite is stretched over a planar wireframe. In this case, you always have the perpendicular to the frame as derived from the points that form its corners. So for a 3d game, you'll always be able to extract the angle of incidence from an obstactle itself. However, in our 2d program, our obstactles give only a single function:
---> Given a single X/Y coordinate, it returns whether this area is an obstactle or not.
This is TGF/MMF's backdrops in a nutshell; you can see if any position is an obstactle, but you have no idea what shapes or angles or objects are around. For all intensive purposes, we absolutely cannot derive the angle of incidence from something stored in the object itself.
Instead, I need to find a way to calculate the angle at the surface of the object. And thats my question; How can this be done? I've come up with a passable, workable solution for now, but I need to know if theres any better way:
Basically, I use this algorithm:
1) I draw the vector between the player and his "next position" that has been checked to be overlapping an obstactle, and is therefore not used.
2) I move the "next position" along this line towards the player until it is NOT overlapping an obstactle anymore. This gives the exact location of where you *should* be colliding with the backdrop.
3) I position 2 detectors along a line extending from this collision point. They are positioned along a circle from this point, using a cos/sin function. These are the black points in the screen shot. They are then swung one clockwise and one counterclockwise until they are respectively not overlapping the backdrop. So basically this finds the point along the perimeter of the backdrop exactly XX pixels away.
4) Using these 2 points, I find the angle between them, add 90 to find the perpendicular, and reflect over it.
Now, while this works to an extent, it runs into the problem that along the edges of some objects, and basically more complicated, smaller or oddly shapen objects, the funny little detectors will goof up and report an angle of incidence that might be more then slightly off. For example, on the very corner of a rectangle as in the following screenshot, even though the player should be striking the platform and reversing his vertical movement vector, it instead will count it as a slightly angled to the side collision, since the rightmost detector swung itself downwards onto the next side of the rectangle. So instead of bouncing straight up, a falling ball would bounce to the side. Thats not right.
Does anyone have ANY better methods for doing this? Cripes, this might be complicated, but I swear theres gotta be an easier way
holy shit man. I'm at work and on my itouch. I may be able to figure this one out but I need my computer. if you don't find what your looking for by the time I get off I'll try and work it out.
why dont you just use something smaller than the unit circle (i'm assuming the unit circle as you didnt really state otherwise. using cos/sin it should be on the unit circle about the point of collision). the closer the detectors are to the point at which youre going to collide with the more accurate it will be towards edges and on curved objects. i doubt there is any better way to do it. if there was a way to check pixels near the point of collision you could use calculus to find the tangent line and then the reflections would truly be flawless. but i doubt that is going to happen...unless, maybe you can move the detectors outward from the point and store that information somewhere and using that information you can find the tangent line at the point of collision. that would most likely be the best and most accurate way to do it.
(also at the edges you can just set the reflection to be negative, kind of like how in pong when the ball hits the edge of the paddle it just reverses and goes back the way it came.)
Well I guess yeah, the way I'm doing it is probably be the most efficient. I just think it wouldn't be very applicable to too many AO's bouncing around the place, and would be restricted to character movements, since if I had like 50 objects all having to test their collisions, it could lag the game a tad. I'm using about a 5 pixel to 8 pixel radius; the more distance I use the more accurate it is on a flat surface, but the less accurate on a complex object. If I only used a 1 pixel radius, it would be restricted to returning 0, 90, 180, or 270 degree angles. Its a finer precision if the object doesn't have an edge at the spot of collison.
This is all mostly to help out my Super Smash Bros style engine; I've noticed that when a new game comes out, like super mario galaxy, that uses a complex system, alot of people want to know how to works. I'm anticipating that SSBB will drum up this kind of interest, so I'm working on a polished engine in advance.
Assault Andy Administrator
I make other people create vaporware
Registered 29/07/2002
Points 5686
12th February, 2008 at 01:15:22 -
Unless you have dynamic backgrounds you could manually code in the angle of incidence into background objects (using actives instead of backdrop objects for walls etc.)
So using what you said "So for a 3d game, you'll always be able to extract the angle of incidence from an obstactle itself", you could simply do that in your 2D game. So if you stored "90" as an alt val in the floors and then 45 for 45 degrees slopes etc, then that method would work. However it would be impractical if you had sonic styled loops in your level or something. But for a smash brothers game it might work.
Ok, I'm too lazy to read all that (Which is ironic, since I always write things like that). So I offer a solution that you probably thought of.
Couldn't you do something like
angle of incidence = arctan((Y(Object)-Y(PositionHit))/(X(Object)-X(PositionHit)))
Disclaimer: Any sarcasm in my posts will not be mentioned as that would ruin the purpose. It is assumed that the reader is intelligent enough to tell the difference between what is sarcasm and what is not.