Lo, after many weeks of doing a bunch of stuff that is only sort of tangentially related to game development, finally some progress has been made! In order to accomplish that, I had to squash some of my own completion-ist developer tendencies, though. Still, progress marches ever onward.
The main bulk of development work done this week, in between family leaving and everything getting back to normal and preparing for a little minor surgery which is happening yesterday (or later on today, if you’re me and thus writing this entry ahead of time) was finalizing collision detection work in ts-game-engine and officially releasing a 0.2.6 version, and then integrating that into ts-tennis. I also started on actually using the new routines to detect collisions, but as of yet that is not complete; it may be by the end of the day though, since I’m writing this entry early.
This is the culmination of most of the last few weeks of exploration into vector math. What we have now is a Vector class with relevant methods, some extra utility code, and most importantly, the ability to be able to detect the exact first point of intersection between a line segment and a rectangular bounding box. This is not as complete as I wanted it to be, because on the one hand besides finding the exact intersection point I would also like to have a method that just detects if there IS an intersection before worrying about where it might be. Also, this is still not implemented for circular bounding volumes, only rectangular.
However, I did ultimately decide that I’ve been slowing down long enough in this whole endeavour and it’s time to start accelerating again. I don’t currently need the ability to detect collisions for circles and I don’t currently need to know just if a collision happened and not where. Besides which, if I was willing to pay the cost of determining the exact point of intersection, you don’t have to actually examine the returned point to know that it is one and a collision did actually happen. This is a prime example of developing only what you need, not just what would be nice to have.
My method for detecting the intersection is not the fastest, but for the purposes of a simple pong game, it’s good enough. What I did is basically an extension of line to line intersections, since a rectangle is just composed of four line segments anyway. A quick initial test is done to see if there’s any possibility of an intersection before we get down to the work of actually trying to find one, as a simple little optimization, since this test needs to be done twice for every frame of the ball moving.
Once we think there could possibly be an intersection, we just test the line segment provided with segments that represent each of the four sides of the bounding rectangle, storing any collision points found. When there are no collisions found, we just return null. A single collision point means that one of the line segment endpoints is inside of the rectangle, and so we can just return that one directly. The only other possibility is two intersections, if the line passes completely through the rectangle.
In this case, we know that the vector created from moving from one collision to the next is going to describe exactly the direction of the vector created from moving from the first point on the line segment we’re testing to the second. We also know that in order to reverse the direction of a vector we just need to flip the signs of both components. So determining which of the two collision points is the initial point is as simple as checking the signs of the offsets between them with the line segment.
As I say, this is not terribly efficient, but for our purposes here it’s good enough. More importantly, at this point I’m still striving towards code that is more readable. So even though there are algorithms for line clipping that would perform this operation a lot faster, I like how easily readable the code is.
I’ve gotten as far as using the new code to determine if the line described by the current and previous ball position intersects with the paddle and using that information to adjust the position of the ball so that it stops before passing completely through the paddle. I guess since the ball is a circle I could use more vector math to move backwards along its movement vector so that it visually rebounds when its edge touches and not its center, but for a fast moving pong game I’m going to call this good enough.
This doesn’t entirely work and the ball does a weird little joggle around whenever it touches a paddle. However, in describing what I was doing I realized exactly why it’s doing that. So I’m going to schedule up this post and go fix that problem. See you next week!